Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- DWARFLinkerDeclContext.h ---------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8.  
  9. #ifndef LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
  10. #define LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
  11.  
  12. #include "llvm/ADT/DenseMap.h"
  13. #include "llvm/ADT/DenseMapInfo.h"
  14. #include "llvm/ADT/DenseSet.h"
  15. #include "llvm/ADT/StringRef.h"
  16. #include "llvm/CodeGen/NonRelocatableStringpool.h"
  17. #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
  18. #include "llvm/DebugInfo/DWARF/DWARFDie.h"
  19. #include "llvm/Support/FileSystem.h"
  20. #include "llvm/Support/Path.h"
  21. #include <atomic>
  22.  
  23. namespace llvm {
  24.  
  25. class CompileUnit;
  26. struct DeclMapInfo;
  27.  
  28. /// Small helper that resolves and caches file paths. This helps reduce the
  29. /// number of calls to realpath which is expensive. We assume the input are
  30. /// files, and cache the realpath of their parent. This way we can quickly
  31. /// resolve different files under the same path.
  32. class CachedPathResolver {
  33. public:
  34.   /// Resolve a path by calling realpath and cache its result. The returned
  35.   /// StringRef is interned in the given \p StringPool.
  36.   StringRef resolve(const std::string &Path,
  37.                     NonRelocatableStringpool &StringPool) {
  38.     StringRef FileName = sys::path::filename(Path);
  39.     StringRef ParentPath = sys::path::parent_path(Path);
  40.  
  41.     // If the ParentPath has not yet been resolved, resolve and cache it for
  42.     // future look-ups.
  43.     if (!ResolvedPaths.count(ParentPath)) {
  44.       SmallString<256> RealPath;
  45.       sys::fs::real_path(ParentPath, RealPath);
  46.       ResolvedPaths.insert(
  47.           {ParentPath, std::string(RealPath.c_str(), RealPath.size())});
  48.     }
  49.  
  50.     // Join the file name again with the resolved path.
  51.     SmallString<256> ResolvedPath(ResolvedPaths[ParentPath]);
  52.     sys::path::append(ResolvedPath, FileName);
  53.     return StringPool.internString(ResolvedPath);
  54.   }
  55.  
  56. private:
  57.   StringMap<std::string> ResolvedPaths;
  58. };
  59.  
  60. /// A DeclContext is a named program scope that is used for ODR uniquing of
  61. /// types.
  62. ///
  63. /// The set of DeclContext for the ODR-subject parts of a Dwarf link is
  64. /// expanded (and uniqued) with each new object file processed. We need to
  65. /// determine the context of each DIE in an linked object file to see if the
  66. /// corresponding type has already been emitted.
  67. ///
  68. /// The contexts are conceptually organized as a tree (eg. a function scope is
  69. /// contained in a namespace scope that contains other scopes), but
  70. /// storing/accessing them in an actual tree is too inefficient: we need to be
  71. /// able to very quickly query a context for a given child context by name.
  72. /// Storing a StringMap in each DeclContext would be too space inefficient.
  73. ///
  74. /// The solution here is to give each DeclContext a link to its parent (this
  75. /// allows to walk up the tree), but to query the existence of a specific
  76. /// DeclContext using a separate DenseMap keyed on the hash of the fully
  77. /// qualified name of the context.
  78. class DeclContext {
  79. public:
  80.   using Map = DenseSet<DeclContext *, DeclMapInfo>;
  81.  
  82.   DeclContext() : DefinedInClangModule(0), Parent(*this) {}
  83.  
  84.   DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
  85.               StringRef Name, StringRef File, const DeclContext &Parent,
  86.               DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
  87.       : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
  88.         DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
  89.         LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId) {}
  90.  
  91.   uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
  92.  
  93.   bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
  94.  
  95.   void setHasCanonicalDIE() { HasCanonicalDIE = true; }
  96.  
  97.   bool hasCanonicalDIE() const { return HasCanonicalDIE; }
  98.  
  99.   uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
  100.   void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
  101.  
  102.   bool isDefinedInClangModule() const { return DefinedInClangModule; }
  103.   void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
  104.  
  105.   uint16_t getTag() const { return Tag; }
  106.  
  107. private:
  108.   friend DeclMapInfo;
  109.  
  110.   unsigned QualifiedNameHash = 0;
  111.   uint32_t Line = 0;
  112.   uint32_t ByteSize = 0;
  113.   uint16_t Tag = dwarf::DW_TAG_compile_unit;
  114.   unsigned DefinedInClangModule : 1;
  115.   StringRef Name;
  116.   StringRef File;
  117.   const DeclContext &Parent;
  118.   DWARFDie LastSeenDIE;
  119.   uint32_t LastSeenCompileUnitID = 0;
  120.   std::atomic<uint32_t> CanonicalDIEOffset = {0};
  121.   bool HasCanonicalDIE = false;
  122. };
  123.  
  124. /// This class gives a tree-like API to the DenseMap that stores the
  125. /// DeclContext objects. It holds the BumpPtrAllocator where these objects will
  126. /// be allocated.
  127. class DeclContextTree {
  128. public:
  129.   /// Get the child of \a Context described by \a DIE in \a Unit. The
  130.   /// required strings will be interned in \a StringPool.
  131.   /// \returns The child DeclContext along with one bit that is set if
  132.   /// this context is invalid.
  133.   ///
  134.   /// An invalid context means it shouldn't be considered for uniquing, but its
  135.   /// not returning null, because some children of that context might be
  136.   /// uniquing candidates.
  137.   ///
  138.   /// FIXME: The invalid bit along the return value is to emulate some
  139.   /// dsymutil-classic functionality.
  140.   PointerIntPair<DeclContext *, 1> getChildDeclContext(DeclContext &Context,
  141.                                                        const DWARFDie &DIE,
  142.                                                        CompileUnit &Unit,
  143.                                                        bool InClangModule);
  144.  
  145.   DeclContext &getRoot() { return Root; }
  146.  
  147. private:
  148.   BumpPtrAllocator Allocator;
  149.   DeclContext Root;
  150.   DeclContext::Map Contexts;
  151.  
  152.   /// Cached resolved paths from the line table.
  153.   /// The key is <UniqueUnitID, FileIdx>.
  154.   using ResolvedPathsMap = DenseMap<std::pair<unsigned, unsigned>, StringRef>;
  155.   ResolvedPathsMap ResolvedPaths;
  156.  
  157.   /// Helper that resolves and caches fragments of file paths.
  158.   CachedPathResolver PathResolver;
  159.  
  160.   /// String pool keeping real path bodies.
  161.   NonRelocatableStringpool StringPool;
  162.  
  163.   StringRef getResolvedPath(CompileUnit &CU, unsigned FileNum,
  164.                             const DWARFDebugLine::LineTable &LineTable);
  165. };
  166.  
  167. /// Info type for the DenseMap storing the DeclContext pointers.
  168. struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
  169.   using DenseMapInfo<DeclContext *>::getEmptyKey;
  170.   using DenseMapInfo<DeclContext *>::getTombstoneKey;
  171.  
  172.   static unsigned getHashValue(const DeclContext *Ctxt) {
  173.     return Ctxt->QualifiedNameHash;
  174.   }
  175.  
  176.   static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
  177.     if (RHS == getEmptyKey() || RHS == getTombstoneKey())
  178.       return RHS == LHS;
  179.     return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
  180.            LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
  181.            LHS->Name.data() == RHS->Name.data() &&
  182.            LHS->File.data() == RHS->File.data() &&
  183.            LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
  184.   }
  185. };
  186.  
  187. } // end namespace llvm
  188.  
  189. #endif // LLVM_DWARFLINKER_DWARFLINKERDECLCONTEXT_H
  190.