- //===- DIContext.h ----------------------------------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file defines DIContext, an abstract data structure that holds 
- // debug information data. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_DEBUGINFO_DICONTEXT_H 
- #define LLVM_DEBUGINFO_DICONTEXT_H 
-   
- #include "llvm/ADT/SmallVector.h" 
- #include "llvm/Object/ObjectFile.h" 
- #include "llvm/Support/WithColor.h" 
- #include "llvm/Support/raw_ostream.h" 
- #include <cassert> 
- #include <cstdint> 
- #include <memory> 
- #include <optional> 
- #include <string> 
- #include <tuple> 
- #include <utility> 
-   
- namespace llvm { 
-   
- /// A format-neutral container for source line information. 
- struct DILineInfo { 
-   // DILineInfo contains "<invalid>" for function/filename it cannot fetch. 
-   static constexpr const char *const BadString = "<invalid>"; 
-   // Use "??" instead of "<invalid>" to make our output closer to addr2line. 
-   static constexpr const char *const Addr2LineBadString = "??"; 
-   std::string FileName; 
-   std::string FunctionName; 
-   std::string StartFileName; 
-   std::optional<StringRef> Source; 
-   uint32_t Line = 0; 
-   uint32_t Column = 0; 
-   uint32_t StartLine = 0; 
-   std::optional<uint64_t> StartAddress; 
-   
-   // DWARF-specific. 
-   uint32_t Discriminator = 0; 
-   
-   DILineInfo() 
-       : FileName(BadString), FunctionName(BadString), StartFileName(BadString) { 
-   } 
-   
-   bool operator==(const DILineInfo &RHS) const { 
-     return Line == RHS.Line && Column == RHS.Column && 
-            FileName == RHS.FileName && FunctionName == RHS.FunctionName && 
-            StartFileName == RHS.StartFileName && StartLine == RHS.StartLine && 
-            Discriminator == RHS.Discriminator; 
-   } 
-   
-   bool operator!=(const DILineInfo &RHS) const { return !(*this == RHS); } 
-   
-   bool operator<(const DILineInfo &RHS) const { 
-     return std::tie(FileName, FunctionName, StartFileName, Line, Column, 
-                     StartLine, Discriminator) < 
-            std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line, 
-                     RHS.Column, RHS.StartLine, RHS.Discriminator); 
-   } 
-   
-   explicit operator bool() const { return *this != DILineInfo(); } 
-   
-   void dump(raw_ostream &OS) { 
-     OS << "Line info: "; 
-     if (FileName != BadString) 
-       OS << "file '" << FileName << "', "; 
-     if (FunctionName != BadString) 
-       OS << "function '" << FunctionName << "', "; 
-     OS << "line " << Line << ", "; 
-     OS << "column " << Column << ", "; 
-     if (StartFileName != BadString) 
-       OS << "start file '" << StartFileName << "', "; 
-     OS << "start line " << StartLine << '\n'; 
-   } 
- }; 
-   
- using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>; 
-   
- /// A format-neutral container for inlined code description. 
- class DIInliningInfo { 
-   SmallVector<DILineInfo, 4> Frames; 
-   
- public: 
-   DIInliningInfo() = default; 
-   
-   /// Returns the frame at `Index`. Frames are stored in bottom-up 
-   /// (leaf-to-root) order with increasing index. 
-   const DILineInfo &getFrame(unsigned Index) const { 
-     assert(Index < Frames.size()); 
-     return Frames[Index]; 
-   } 
-   
-   DILineInfo *getMutableFrame(unsigned Index) { 
-     assert(Index < Frames.size()); 
-     return &Frames[Index]; 
-   } 
-   
-   uint32_t getNumberOfFrames() const { return Frames.size(); } 
-   
-   void addFrame(const DILineInfo &Frame) { Frames.push_back(Frame); } 
-   
-   void resize(unsigned i) { Frames.resize(i); } 
- }; 
-   
- /// Container for description of a global variable. 
- struct DIGlobal { 
-   std::string Name; 
-   uint64_t Start = 0; 
-   uint64_t Size = 0; 
-   std::string DeclFile; 
-   uint64_t DeclLine = 0; 
-   
-   DIGlobal() : Name(DILineInfo::BadString) {} 
- }; 
-   
- struct DILocal { 
-   std::string FunctionName; 
-   std::string Name; 
-   std::string DeclFile; 
-   uint64_t DeclLine = 0; 
-   std::optional<int64_t> FrameOffset; 
-   std::optional<uint64_t> Size; 
-   std::optional<uint64_t> TagOffset; 
- }; 
-   
- /// A DINameKind is passed to name search methods to specify a 
- /// preference regarding the type of name resolution the caller wants. 
- enum class DINameKind { None, ShortName, LinkageName }; 
-   
- /// Controls which fields of DILineInfo container should be filled 
- /// with data. 
- struct DILineInfoSpecifier { 
-   enum class FileLineInfoKind { 
-     None, 
-     // RawValue is whatever the compiler stored in the filename table.  Could be 
-     // a full path, could be something else. 
-     RawValue, 
-     BaseNameOnly, 
-     // Relative to the compilation directory. 
-     RelativeFilePath, 
-     AbsoluteFilePath 
-   }; 
-   using FunctionNameKind = DINameKind; 
-   
-   FileLineInfoKind FLIKind; 
-   FunctionNameKind FNKind; 
-   
-   DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::RawValue, 
-                       FunctionNameKind FNKind = FunctionNameKind::None) 
-       : FLIKind(FLIKind), FNKind(FNKind) {} 
-   
-   inline bool operator==(const DILineInfoSpecifier &RHS) const { 
-     return FLIKind == RHS.FLIKind && FNKind == RHS.FNKind; 
-   } 
- }; 
-   
- /// This is just a helper to programmatically construct DIDumpType. 
- enum DIDumpTypeCounter { 
- #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \ 
-   DIDT_ID_##ENUM_NAME, 
- #include "llvm/BinaryFormat/Dwarf.def" 
- #undef HANDLE_DWARF_SECTION 
-   DIDT_ID_UUID, 
-   DIDT_ID_Count 
- }; 
- static_assert(DIDT_ID_Count <= 32, "section types overflow storage"); 
-   
- /// Selects which debug sections get dumped. 
- enum DIDumpType : unsigned { 
-   DIDT_Null, 
-   DIDT_All = ~0U, 
- #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \ 
-   DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME, 
- #include "llvm/BinaryFormat/Dwarf.def" 
- #undef HANDLE_DWARF_SECTION 
-   DIDT_UUID = 1 << DIDT_ID_UUID, 
- }; 
-   
- /// Container for dump options that control which debug information will be 
- /// dumped. 
- struct DIDumpOptions { 
-   unsigned DumpType = DIDT_All; 
-   unsigned ChildRecurseDepth = -1U; 
-   unsigned ParentRecurseDepth = -1U; 
-   uint16_t Version = 0; // DWARF version to assume when extracting. 
-   uint8_t AddrSize = 4; // Address byte size to assume when extracting. 
-   bool ShowAddresses = true; 
-   bool ShowChildren = false; 
-   bool ShowParents = false; 
-   bool ShowForm = false; 
-   bool SummarizeTypes = false; 
-   bool Verbose = false; 
-   bool DisplayRawContents = false; 
-   bool IsEH = false; 
-   std::function<llvm::StringRef(uint64_t DwarfRegNum, bool IsEH)> 
-       GetNameForDWARFReg; 
-   
-   /// Return default option set for printing a single DIE without children. 
-   static DIDumpOptions getForSingleDIE() { 
-     DIDumpOptions Opts; 
-     Opts.ChildRecurseDepth = 0; 
-     Opts.ParentRecurseDepth = 0; 
-     return Opts; 
-   } 
-   
-   /// Return the options with RecurseDepth set to 0 unless explicitly required. 
-   DIDumpOptions noImplicitRecursion() const { 
-     DIDumpOptions Opts = *this; 
-     if (ChildRecurseDepth == -1U && !ShowChildren) 
-       Opts.ChildRecurseDepth = 0; 
-     if (ParentRecurseDepth == -1U && !ShowParents) 
-       Opts.ParentRecurseDepth = 0; 
-     return Opts; 
-   } 
-   
-   std::function<void(Error)> RecoverableErrorHandler = 
-       WithColor::defaultErrorHandler; 
-   std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler; 
- }; 
-   
- class DIContext { 
- public: 
-   enum DIContextKind { CK_DWARF, CK_PDB }; 
-   
-   DIContext(DIContextKind K) : Kind(K) {} 
-   virtual ~DIContext() = default; 
-   
-   DIContextKind getKind() const { return Kind; } 
-   
-   virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0; 
-   
-   virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) { 
-     // No verifier? Just say things went well. 
-     return true; 
-   } 
-   
-   virtual DILineInfo getLineInfoForAddress( 
-       object::SectionedAddress Address, 
-       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; 
-   virtual DILineInfo 
-   getLineInfoForDataAddress(object::SectionedAddress Address) = 0; 
-   virtual DILineInfoTable getLineInfoForAddressRange( 
-       object::SectionedAddress Address, uint64_t Size, 
-       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; 
-   virtual DIInliningInfo getInliningInfoForAddress( 
-       object::SectionedAddress Address, 
-       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; 
-   
-   virtual std::vector<DILocal> 
-   getLocalsForAddress(object::SectionedAddress Address) = 0; 
-   
- private: 
-   const DIContextKind Kind; 
- }; 
-   
- /// An inferface for inquiring the load address of a loaded object file 
- /// to be used by the DIContext implementations when applying relocations 
- /// on the fly. 
- class LoadedObjectInfo { 
- protected: 
-   LoadedObjectInfo() = default; 
-   LoadedObjectInfo(const LoadedObjectInfo &) = default; 
-   
- public: 
-   virtual ~LoadedObjectInfo() = default; 
-   
-   /// Obtain the Load Address of a section by SectionRef. 
-   /// 
-   /// Calculate the address of the given section. 
-   /// The section need not be present in the local address space. The addresses 
-   /// need to be consistent with the addresses used to query the DIContext and 
-   /// the output of this function should be deterministic, i.e. repeated calls 
-   /// with the same Sec should give the same address. 
-   virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const { 
-     return 0; 
-   } 
-   
-   /// If conveniently available, return the content of the given Section. 
-   /// 
-   /// When the section is available in the local address space, in relocated 
-   /// (loaded) form, e.g. because it was relocated by a JIT for execution, this 
-   /// function should provide the contents of said section in `Data`. If the 
-   /// loaded section is not available, or the cost of retrieving it would be 
-   /// prohibitive, this function should return false. In that case, relocations 
-   /// will be read from the local (unrelocated) object file and applied on the 
-   /// fly. Note that this method is used purely for optimzation purposes in the 
-   /// common case of JITting in the local address space, so returning false 
-   /// should always be correct. 
-   virtual bool getLoadedSectionContents(const object::SectionRef &Sec, 
-                                         StringRef &Data) const { 
-     return false; 
-   } 
-   
-   // FIXME: This is untested and unused anywhere in the LLVM project, it's 
-   // used/needed by Julia (an external project). It should have some coverage 
-   // (at least tests, but ideally example functionality). 
-   /// Obtain a copy of this LoadedObjectInfo. 
-   virtual std::unique_ptr<LoadedObjectInfo> clone() const = 0; 
- }; 
-   
- template <typename Derived, typename Base = LoadedObjectInfo> 
- struct LoadedObjectInfoHelper : Base { 
- protected: 
-   LoadedObjectInfoHelper(const LoadedObjectInfoHelper &) = default; 
-   LoadedObjectInfoHelper() = default; 
-   
- public: 
-   template <typename... Ts> 
-   LoadedObjectInfoHelper(Ts &&...Args) : Base(std::forward<Ts>(Args)...) {} 
-   
-   std::unique_ptr<llvm::LoadedObjectInfo> clone() const override { 
-     return std::make_unique<Derived>(static_cast<const Derived &>(*this)); 
-   } 
- }; 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_DEBUGINFO_DICONTEXT_H 
-