LLVM 24.0.0git
AcceleratorRecordsSaver.cpp
Go to the documentation of this file.
1//=== AcceleratorRecordsSaver.cpp -----------------------------------------===//
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
12#include "llvm/Support/DJB.h"
13
14using namespace llvm;
15using namespace dwarf_linker;
16using namespace dwarf_linker::parallel;
17
19 int ChildRecurseDepth = 0) {
20 const char *Name = nullptr;
21 CompileUnit *CU = &InputCU;
22 std::optional<DWARFFormValue> RefVal;
23
24 if (Error Err = finiteLoop([&]() -> Expected<bool> {
25 if (const char *CurrentName = InputDIE.getName(DINameKind::ShortName))
26 Name = CurrentName;
27
28 if (!(RefVal = InputDIE.find(dwarf::DW_AT_specification)) &&
29 !(RefVal = InputDIE.find(dwarf::DW_AT_abstract_origin)))
30 return false;
31
32 if (!RefVal->isFormClass(DWARFFormValue::FC_Reference))
33 return false;
34
35 std::optional<UnitEntryPairTy> RefDie = CU->resolveDIEReference(
36 *RefVal, ResolveInterCUReferencesMode::Resolve);
37 if (!RefDie)
38 return false;
39
40 if (!RefDie->DieEntry)
41 return false;
42
43 CU = RefDie->CU;
44 InputDIE = RefDie->CU->getDIE(RefDie->DieEntry);
45 return true;
46 })) {
47 consumeError(std::move(Err));
48 }
49
50 if (!Name && InputDIE.getTag() == dwarf::DW_TAG_namespace)
51 Name = "(anonymous namespace)";
52
53 DWARFDie ParentDie = InputDIE.getParent();
54 if (!ParentDie.isValid() || ParentDie.getTag() == dwarf::DW_TAG_compile_unit)
55 return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));
56
57 return djbHash(
58 (Name ? Name : ""),
59 djbHash((Name ? "::" : ""),
60 hashFullyQualifiedName(*CU, ParentDie, ++ChildRecurseDepth)));
61}
62
64 DIE *OutDIE, AttributesInfo &AttrInfo,
66 if (GlobalData.getOptions().AccelTables.empty())
67 return;
68
69 DWARFDie InputDIE = InUnit.getDIE(InputDieEntry);
70
71 // Look for short name recursively if short name is not known yet.
72 if (AttrInfo.Name == nullptr)
73 if (const char *ShortName = InputDIE.getShortName())
74 AttrInfo.Name = GlobalData.getStringPool().insert(ShortName).first;
75
76 switch (InputDieEntry->getTag()) {
77 case dwarf::DW_TAG_array_type:
78 case dwarf::DW_TAG_class_type:
79 case dwarf::DW_TAG_enumeration_type:
80 case dwarf::DW_TAG_pointer_type:
81 case dwarf::DW_TAG_reference_type:
82 case dwarf::DW_TAG_string_type:
83 case dwarf::DW_TAG_structure_type:
84 case dwarf::DW_TAG_subroutine_type:
85 case dwarf::DW_TAG_template_alias:
86 case dwarf::DW_TAG_typedef:
87 case dwarf::DW_TAG_union_type:
88 case dwarf::DW_TAG_ptr_to_member_type:
89 case dwarf::DW_TAG_set_type:
90 case dwarf::DW_TAG_subrange_type:
91 case dwarf::DW_TAG_base_type:
92 case dwarf::DW_TAG_const_type:
93 case dwarf::DW_TAG_constant:
94 case dwarf::DW_TAG_file_type:
95 case dwarf::DW_TAG_namelist:
96 case dwarf::DW_TAG_packed_type:
97 case dwarf::DW_TAG_volatile_type:
98 case dwarf::DW_TAG_restrict_type:
99 case dwarf::DW_TAG_atomic_type:
100 case dwarf::DW_TAG_interface_type:
101 case dwarf::DW_TAG_unspecified_type:
102 case dwarf::DW_TAG_shared_type:
103 case dwarf::DW_TAG_immutable_type:
104 case dwarf::DW_TAG_rvalue_reference_type: {
105 if (AttrInfo.IsDeclaration)
106 break;
107
108 // hashFullyQualifiedName() advances InputDIE along the specification and
109 // abstract origin chain, so the DIE's own attributes have to be read first.
110
111 // The linkage name may be attached to the declaration rather than to the
112 // definition.
113 if (!AttrInfo.MangledName)
114 if (const char *LinkageName = InputDIE.getLinkageName())
115 AttrInfo.MangledName =
116 GlobalData.getStringPool().insert(LinkageName).first;
117
118 uint64_t RuntimeLang =
119 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
120 .value_or(0);
121
122 bool ObjCClassIsImplementation =
123 (RuntimeLang == dwarf::DW_LANG_ObjC ||
124 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
125 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
126 .value_or(0);
127
128 if (AttrInfo.Name != nullptr && !AttrInfo.Name->getKey().empty()) {
129 uint32_t Hash = hashFullyQualifiedName(InUnit, InputDIE);
130 saveTypeRecord(InputDieEntry, AttrInfo.Name, OutDIE,
131 InputDieEntry->getTag(), Hash, ObjCClassIsImplementation,
132 TypeEntry);
133 }
134
135 // Swift carries a type's mangled name in DW_AT_linkage_name, which a
136 // consumer may look up on its own.
137 if (AttrInfo.MangledName != nullptr &&
138 RuntimeLang == dwarf::DW_LANG_Swift &&
139 !AttrInfo.MangledName->getKey().empty() &&
140 AttrInfo.MangledName != AttrInfo.Name)
141 saveTypeRecord(InputDieEntry, AttrInfo.MangledName, OutDIE,
142 InputDieEntry->getTag(),
143 djbHash(AttrInfo.MangledName->getKey()),
144 ObjCClassIsImplementation, TypeEntry);
145 } break;
146 case dwarf::DW_TAG_namespace: {
147 if (AttrInfo.Name == nullptr)
148 AttrInfo.Name =
149 GlobalData.getStringPool().insert("(anonymous namespace)").first;
150
151 saveNamespaceRecord(InputDieEntry, AttrInfo.Name, OutDIE,
152 InputDieEntry->getTag(), TypeEntry);
153 } break;
154 case dwarf::DW_TAG_imported_declaration: {
155 if (AttrInfo.Name != nullptr)
156 saveNamespaceRecord(InputDieEntry, AttrInfo.Name, OutDIE,
157 InputDieEntry->getTag(), TypeEntry);
158 } break;
159 case dwarf::DW_TAG_compile_unit:
160 case dwarf::DW_TAG_lexical_block: {
161 // Nothing to do.
162 } break;
163 default:
164 // HasLiveAddress / HasRanges below decides whether a DIE carries enough
165 // information of its own to warrant a name record; the output unit is
166 // incidental and routed by the helpers.
167
168 if ((AttrInfo.HasLiveAddress || AttrInfo.HasRanges) &&
169 !(InputDieEntry->getTag() == dwarf::DW_TAG_variable &&
170 hasImplicitAddressLocation(InputDIE))) {
171 if (AttrInfo.Name)
173 InputDieEntry, AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
174 InputDieEntry->getTag() == dwarf::DW_TAG_inlined_subroutine,
175 TypeEntry);
176
177 // Look for mangled name recursively if mangled name is not known yet.
178 if (!AttrInfo.MangledName)
179 if (const char *LinkageName = InputDIE.getLinkageName())
180 AttrInfo.MangledName =
181 GlobalData.getStringPool().insert(LinkageName).first;
182
183 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
184 saveNameRecord(InputDieEntry, AttrInfo.MangledName, OutDIE,
185 InputDieEntry->getTag(),
186 InputDieEntry->getTag() ==
187 dwarf::DW_TAG_inlined_subroutine,
188 TypeEntry);
189
190 // Strip template parameters from the short name.
191 if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&
192 (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
193 if (std::optional<StringRef> Name =
194 StripTemplateParameters(AttrInfo.Name->getKey())) {
195 StringEntry *NameWithoutTemplateParams =
196 GlobalData.getStringPool().insert(*Name).first;
197
198 saveNameRecord(InputDieEntry, NameWithoutTemplateParams, OutDIE,
199 InputDieEntry->getTag(), true, TypeEntry);
200 }
201 }
202
203 if (AttrInfo.Name)
204 saveObjC(InputDieEntry, OutDIE, AttrInfo, TypeEntry);
205 }
206 break;
207 }
208}
209
211 DIE *OutDIE, AttributesInfo &AttrInfo,
213 std::optional<ObjCSelectorNames> Names =
215 if (!Names)
216 return;
217
218 StringEntry *Selector =
219 GlobalData.getStringPool().insert(Names->Selector).first;
220 saveNameRecord(InputDieEntry, Selector, OutDIE, InputDieEntry->getTag(), true,
221 TypeEntry);
222 StringEntry *ClassName =
223 GlobalData.getStringPool().insert(Names->ClassName).first;
224 saveObjCNameRecord(InputDieEntry, ClassName, OutDIE, InputDieEntry->getTag(),
225 TypeEntry);
226 if (Names->ClassNameNoCategory) {
227 StringEntry *ClassNameNoCategory =
228 GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;
229 saveObjCNameRecord(InputDieEntry, ClassNameNoCategory, OutDIE,
230 InputDieEntry->getTag(), TypeEntry);
231 }
232 if (Names->MethodNameNoCategory) {
233 StringEntry *MethodNameNoCategory =
234 GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
235 saveNameRecord(InputDieEntry, MethodNameNoCategory, OutDIE,
236 InputDieEntry->getTag(), true, TypeEntry);
237 }
238}
239
241 const DWARFDebugInfoEntry *InputDieEntry) {
242 // getDieOutOffset returns this for input DIEs that were not cloned into
243 // this CU's plain DWARF (e.g. routed only into the artificial type unit).
244 // OutDieOffsetArray is zero-initialized and a real DIE never lives at
245 // offset 0 (the CU header occupies the first bytes of the unit), so 0 is
246 // an unambiguous "no plain-DWARF copy" sentinel.
247 constexpr uint64_t NotClonedInPlainDWARF = 0;
248
249 std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx();
250 if (!ParentIdx)
251 return std::nullopt;
252 // Skip parents marked as declarations; the name table should only reference
253 // definitions.
254 if (dwarf::toUnsigned(InUnit.find(*ParentIdx, dwarf::DW_AT_declaration), 0))
255 return std::nullopt;
256 uint64_t ParentOutOffset = InUnit.getDieOutOffset(*ParentIdx);
257 if (ParentOutOffset == NotClonedInPlainDWARF)
258 return std::nullopt;
259 return ParentOutOffset;
260}
261
263 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
264 dwarf::Tag Tag, bool AvoidForPubSections, TypeEntry *TypeEntry) {
265 if (OutUnit.isCompileUnit()) {
266 assert(TypeEntry == nullptr);
268
270 Info.String = Name;
271 Info.OutOffset = OutDIE->getOffset();
272 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
273 Info.Tag = Tag;
274 Info.AvoidForPubSections = AvoidForPubSections;
275
276 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
277 return;
278 }
279
280 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
281 // unit (see saveNamespaceRecord).
282
283 assert(TypeEntry != nullptr);
286 Info.String = Name;
287 Info.OutOffset = 0xbaddef;
288 Info.Tag = Tag;
289 Info.AvoidForPubSections = AvoidForPubSections;
290 Info.OutDIE = OutDIE;
291 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
292
293 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
294}
296 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
298 if (OutUnit.isCompileUnit()) {
299 assert(TypeEntry == nullptr);
301
303 Info.String = Name;
304 Info.OutOffset = OutDIE->getOffset();
305 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
306 Info.Tag = Tag;
307
308 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
309 return;
310 }
311
312 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
313 // unit. The parent lookup via the input-side DIE tree is only valid for
314 // DIEs cloned into this CU's plain DWARF.
315
316 assert(TypeEntry != nullptr);
319 Info.String = Name;
320 Info.OutOffset = 0xbaddef;
321 Info.Tag = Tag;
322 Info.OutDIE = OutDIE;
323 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
324
325 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
326}
327
329 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
331 if (OutUnit.isCompileUnit()) {
332 assert(TypeEntry == nullptr);
334
336 Info.String = Name;
337 Info.OutOffset = OutDIE->getOffset();
338 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
339 Info.Tag = Tag;
340 Info.AvoidForPubSections = true;
341
342 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
343 return;
344 }
345
346 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
347 // unit (see saveNamespaceRecord).
348
349 assert(TypeEntry != nullptr);
352 Info.String = Name;
353 Info.OutOffset = 0xbaddef;
354 Info.Tag = Tag;
355 Info.AvoidForPubSections = true;
356 Info.OutDIE = OutDIE;
357 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
358
359 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
360}
361
363 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
364 dwarf::Tag Tag, uint32_t QualifiedNameHash, bool ObjcClassImplementation,
366 if (OutUnit.isCompileUnit()) {
367 assert(TypeEntry == nullptr);
369
371 Info.String = Name;
372 Info.OutOffset = OutDIE->getOffset();
373 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
374 Info.Tag = Tag;
375 Info.QualifiedNameHash = QualifiedNameHash;
376 Info.ObjcClassImplementation = ObjcClassImplementation;
377
378 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
379 return;
380 }
381
382 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
383 // unit (see saveNamespaceRecord).
384
385 assert(TypeEntry != nullptr);
387
389 Info.String = Name;
390 Info.OutOffset = 0xbaddef;
391 Info.Tag = Tag;
392 Info.QualifiedNameHash = QualifiedNameHash;
393 Info.ObjcClassImplementation = ObjcClassImplementation;
394 Info.OutDIE = OutDIE;
395 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
396 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
397}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)
A structured debug information entry.
Definition DIE.h:835
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:870
DWARFDebugInfoEntry - A DIE with only the minimum required data.
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
LLVM_ABI const char * getShortName() const
Return the DIE short name resolving DW_AT_specification or DW_AT_abstract_origin references if necess...
Definition DWARFDie.cpp:571
LLVM_ABI DWARFDie getParent() const
Get the parent of this DIE object.
Definition DWARFDie.cpp:754
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:335
LLVM_ABI const char * getName(DINameKind Kind) const
Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin references if necessary.
Definition DWARFDie.cpp:560
dwarf::Tag getTag() const
Definition DWARFDie.h:73
LLVM_ABI const char * getLinkageName() const
Return the DIE linkage name resolving DW_AT_specification or DW_AT_abstract_origin references if nece...
Definition DWARFDie.cpp:578
bool isValid() const
Definition DWARFDie.h:52
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
StringRef getKey() const
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
Stores all information relating to a compile unit, be it in its original instance in the object file ...
CompileUnit & InUnit
Comiple unit corresponding to input DWARF.
void saveObjCNameRecord(const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, TypeEntry *TypeEntry)
void saveNameRecord(const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, bool AvoidForPubSections, TypeEntry *TypeEntry)
CompileUnit::OutputUnitVariantPtr OutUnit
Compile unit or Artificial type unit corresponding to the output DWARF.
std::optional< uint64_t > getDefiningParentOutOffset(const DWARFDebugInfoEntry *InputDieEntry)
Return the output offset of InputDieEntry's immediate non-declaration parent, for use as the DW_IDX_p...
void saveTypeRecord(const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, uint32_t QualifiedNameHash, bool ObjcClassImplementation, TypeEntry *TypeEntry)
void save(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE, AttributesInfo &AttrInfo, TypeEntry *TypeEntry)
Save accelerator info for the specified OutDIE inside OutUnit.
void saveNamespaceRecord(const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, TypeEntry *TypeEntry)
void saveObjC(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE, AttributesInfo &AttrInfo, TypeEntry *TypeEntry)
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:28
LLVM_ABI bool hasImplicitAddressLocation(const DWARFDie &Die)
Test if the location of variable Die contains a global address but only uses to compute the variable'...
Definition Utils.cpp:21
StringMapEntry< EmptyStringSetTag > StringEntry
StringEntry keeps data of the string: the length, external offset and a string body which is placed r...
Definition StringPool.h:23
Error finiteLoop(function_ref< Expected< bool >()> Iteration, size_t MaxCounter=100000)
This function calls Iteration() until it returns false.
Definition Utils.h:51
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::optional< StringRef > StripTemplateParameters(StringRef Name)
If Name is the name of a templated function that includes template parameters, returns a substring of...
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
Definition DJB.h:22
LLVM_ABI std::optional< ObjCSelectorNames > getObjCNamesIfSelector(StringRef Name)
If Name is the AT_name of a DIE which refers to an Objective-C selector, returns an instance of ObjCS...
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Information gathered and exchanged between the various clone*Attr helpers about the attributes of a p...
bool IsDeclaration
Is this DIE only a declaration?
bool HasRanges
Does the DIE have a ranges attribute?
bool HasLiveAddress
Does the DIE have an address pointing to live code section?
This structure keeps fields which would be used for creating accelerator table.
AccelType Type
Type of this accelerator record.
TypeUnitAccelInfo extends AccelInfo structure with type specific fields.