// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _DEBUGINFO_H_ #define _DEBUGINFO_H_ #include "jit.h" class InlineContext; // Represents information about the location of an IL instruction. class ILLocation { public: ILLocation() : m_offset(BAD_IL_OFFSET), m_isStackEmpty(false), m_isCall(false) { } ILLocation(IL_OFFSET offset, bool isStackEmpty, bool isCall) : m_offset(offset), m_isStackEmpty(isStackEmpty), m_isCall(isCall) { } IL_OFFSET GetOffset() const { return m_offset; } // Is this source location at a stack empty point? We need to be able to // report this information back to the debugger since we only allow EnC // transitions at stack empty points. bool IsStackEmpty() const { return m_isStackEmpty; } // Is this a call instruction? Used for managed return values. bool IsCall() const { return m_isCall; } bool IsValid() const { return m_offset != BAD_IL_OFFSET; } inline bool operator==(const ILLocation& other) const { return (m_offset == other.m_offset) && (m_isStackEmpty == other.m_isStackEmpty) && (m_isCall == other.m_isCall); } inline bool operator!=(const ILLocation& other) const { return !(*this == other); } ICorDebugInfo::SourceTypes EncodeSourceTypes() const; #ifdef DEBUG // Dump textual representation of this ILLocation to jitstdout. void Dump() const; #endif private: IL_OFFSET m_offset; bool m_isStackEmpty : 1; bool m_isCall : 1; }; // Represents debug information about a statement. class DebugInfo { public: DebugInfo() : m_inlineContext(nullptr) { } DebugInfo(InlineContext* inlineContext, ILLocation loc) : m_inlineContext(inlineContext), m_location(loc) { } InlineContext* GetInlineContext() const { return m_inlineContext; } ILLocation GetLocation() const { return m_location; } // Retrieve information about the location that inlined this statement. // Note that there can be associated parent information even when IsValid // below returns false. bool GetParent(DebugInfo* parent) const; // Get debug info in the root. If this debug info is in the root, then // returns *this. Otherwise returns information of the call in the root // that eventually produced this statement through inlines. DebugInfo GetRoot() const; #ifdef DEBUG void Validate() const; #else void Validate() const { } #endif #ifdef DEBUG // Dump textual representation of this DebugInfo to jitstdout. void Dump(bool recurse) const; #endif // Check if this debug info has both a valid inline context and valid // location. bool IsValid() const { return m_inlineContext != nullptr && m_location.IsValid(); } inline bool operator==(const DebugInfo& other) const { return (m_inlineContext == other.m_inlineContext) && (m_location == other.m_location); } inline bool operator!=(const DebugInfo& other) const { return !(*this == other); } private: InlineContext* m_inlineContext; ILLocation m_location; }; #endif