LLVM 17.0.0git
Go to the documentation of this file.
1//===- DWARFLinkerDeclContext.h ---------------------------------*- C++ -*-===//
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
12#include "llvm/ADT/DenseMap.h"
14#include "llvm/ADT/DenseSet.h"
15#include "llvm/ADT/StringRef.h"
20#include "llvm/Support/Path.h"
21#include <atomic>
23namespace llvm {
25class CompileUnit;
26struct DeclMapInfo;
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.
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);
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 }
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 }
57 StringMap<std::string> ResolvedPaths;
60/// A DeclContext is a named program scope that is used for ODR uniquing of
61/// types.
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.
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.
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.
82 DeclContext() : DefinedInClangModule(0), Parent(*this) {}
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) {}
91 uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
93 bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die);
95 void setHasCanonicalDIE() { HasCanonicalDIE = true; }
97 bool hasCanonicalDIE() const { return HasCanonicalDIE; }
99 uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
100 void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
102 bool isDefinedInClangModule() const { return DefinedInClangModule; }
103 void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
105 uint16_t getTag() const { return Tag; }
108 friend DeclMapInfo;
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;
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.
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.
141 const DWARFDie &DIE,
142 CompileUnit &Unit,
143 bool InClangModule);
145 DeclContext &getRoot() { return Root; }
148 BumpPtrAllocator Allocator;
149 DeclContext Root;
150 DeclContext::Map Contexts;
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;
157 /// Helper that resolves and caches fragments of file paths.
158 CachedPathResolver PathResolver;
160 /// String pool keeping real path bodies.
161 NonRelocatableStringpool StringPool;
163 StringRef getResolvedPath(CompileUnit &CU, unsigned FileNum,
164 const DWARFDebugLine::LineTable &LineTable);
167/// Info type for the DenseMap storing the DeclContext pointers.
168struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
169 using DenseMapInfo<DeclContext *>::getEmptyKey;
170 using DenseMapInfo<DeclContext *>::getTombstoneKey;
172 static unsigned getHashValue(const DeclContext *Ctxt) {
173 return Ctxt->QualifiedNameHash;
174 }
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 }
187} // end namespace llvm
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
LLVMContext & Context
Value * RHS
Value * LHS
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:66
Small helper that resolves and caches file paths.
StringRef resolve(const std::string &Path, NonRelocatableStringpool &StringPool)
Resolve a path by calling realpath and cache its result.
Stores all information relating to a compile unit, be it in its original instance in the object file ...
A structured debug information entry.
Definition: DIE.h:744
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition: DWARFDie.h:42
This class gives a tree-like API to the DenseMap that stores the DeclContext objects.
PointerIntPair< DeclContext *, 1 > getChildDeclContext(DeclContext &Context, const DWARFDie &DIE, CompileUnit &Unit, bool InClangModule)
Get the child of Context described by DIE in Unit.
A DeclContext is a named program scope that is used for ODR uniquing of types.
bool isDefinedInClangModule() const
uint32_t getCanonicalDIEOffset() const
void setDefinedInClangModule(bool Val)
uint32_t getQualifiedNameHash() const
DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag, StringRef Name, StringRef File, const DeclContext &Parent, DWARFDie LastSeenDIE=DWARFDie(), unsigned CUId=0)
void setCanonicalDIEOffset(uint32_t Offset)
bool setLastSeenDIE(CompileUnit &U, const DWARFDie &Die)
Set the last DIE/CU a context was seen in and, possibly invalidate the context if it is ambiguous.
A string table that doesn't need relocations.
StringRef internString(StringRef S)
Get permanent storage for S (but do not necessarily emit S in the output section).
PointerIntPair - This class implements a pair of a pointer and small integer.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
const char * c_str()
Definition: SmallString.h:264
size_t size() const
Definition: SmallVector.h:91
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:111
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition: StringMap.h:256
bool insert(MapEntryTy *KeyValue)
insert - Insert the specified key/value pair into the map.
Definition: StringMap.h:286
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:577
StringRef parent_path(StringRef path, Style style=Style::native)
Get parent path.
Definition: Path.cpp:467
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:456
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
Info type for the DenseMap storing the DeclContext pointers.
static bool isEqual(const DeclContext *LHS, const DeclContext *RHS)
static unsigned getHashValue(const DeclContext *Ctxt)
An information struct used to provide DenseMap with the various necessary components for a given valu...
Definition: DenseMapInfo.h:51