LLVM 23.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 && AttrInfo.Name != nullptr &&
106 !AttrInfo.Name->getKey().empty()) {
107 uint32_t Hash = hashFullyQualifiedName(InUnit, InputDIE);
108
109 uint64_t RuntimeLang =
110 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
111 .value_or(0);
112
113 bool ObjCClassIsImplementation =
114 (RuntimeLang == dwarf::DW_LANG_ObjC ||
115 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
117 InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
118 .value_or(0);
119
120 saveTypeRecord(InputDieEntry, AttrInfo.Name, OutDIE,
121 InputDieEntry->getTag(), Hash, ObjCClassIsImplementation,
122 TypeEntry);
123 }
124 } break;
125 case dwarf::DW_TAG_namespace: {
126 if (AttrInfo.Name == nullptr)
127 AttrInfo.Name =
128 GlobalData.getStringPool().insert("(anonymous namespace)").first;
129
130 saveNamespaceRecord(InputDieEntry, AttrInfo.Name, OutDIE,
131 InputDieEntry->getTag(), TypeEntry);
132 } break;
133 case dwarf::DW_TAG_imported_declaration: {
134 if (AttrInfo.Name != nullptr)
135 saveNamespaceRecord(InputDieEntry, AttrInfo.Name, OutDIE,
136 InputDieEntry->getTag(), TypeEntry);
137 } break;
138 case dwarf::DW_TAG_compile_unit:
139 case dwarf::DW_TAG_lexical_block: {
140 // Nothing to do.
141 } break;
142 default:
143 // HasLiveAddress / HasRanges below decides whether a DIE carries enough
144 // information of its own to warrant a name record; the output unit is
145 // incidental and routed by the helpers.
146
147 if (AttrInfo.HasLiveAddress || AttrInfo.HasRanges) {
148 if (AttrInfo.Name)
150 InputDieEntry, AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
151 InputDieEntry->getTag() == dwarf::DW_TAG_inlined_subroutine,
152 TypeEntry);
153
154 // Look for mangled name recursively if mangled name is not known yet.
155 if (!AttrInfo.MangledName)
156 if (const char *LinkageName = InputDIE.getLinkageName())
157 AttrInfo.MangledName =
158 GlobalData.getStringPool().insert(LinkageName).first;
159
160 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
161 saveNameRecord(InputDieEntry, AttrInfo.MangledName, OutDIE,
162 InputDieEntry->getTag(),
163 InputDieEntry->getTag() ==
164 dwarf::DW_TAG_inlined_subroutine,
165 TypeEntry);
166
167 // Strip template parameters from the short name.
168 if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&
169 (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
170 if (std::optional<StringRef> Name =
171 StripTemplateParameters(AttrInfo.Name->getKey())) {
172 StringEntry *NameWithoutTemplateParams =
173 GlobalData.getStringPool().insert(*Name).first;
174
175 saveNameRecord(InputDieEntry, NameWithoutTemplateParams, OutDIE,
176 InputDieEntry->getTag(), true, TypeEntry);
177 }
178 }
179
180 if (AttrInfo.Name)
181 saveObjC(InputDieEntry, OutDIE, AttrInfo, TypeEntry);
182 }
183 break;
184 }
185}
186
188 DIE *OutDIE, AttributesInfo &AttrInfo,
190 std::optional<ObjCSelectorNames> Names =
192 if (!Names)
193 return;
194
195 StringEntry *Selector =
196 GlobalData.getStringPool().insert(Names->Selector).first;
197 saveNameRecord(InputDieEntry, Selector, OutDIE, InputDieEntry->getTag(), true,
198 TypeEntry);
199 StringEntry *ClassName =
200 GlobalData.getStringPool().insert(Names->ClassName).first;
201 saveObjCNameRecord(InputDieEntry, ClassName, OutDIE, InputDieEntry->getTag(),
202 TypeEntry);
203 if (Names->ClassNameNoCategory) {
204 StringEntry *ClassNameNoCategory =
205 GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;
206 saveObjCNameRecord(InputDieEntry, ClassNameNoCategory, OutDIE,
207 InputDieEntry->getTag(), TypeEntry);
208 }
209 if (Names->MethodNameNoCategory) {
210 StringEntry *MethodNameNoCategory =
211 GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
212 saveNameRecord(InputDieEntry, MethodNameNoCategory, OutDIE,
213 InputDieEntry->getTag(), true, TypeEntry);
214 }
215}
216
218 const DWARFDebugInfoEntry *InputDieEntry) {
219 // getDieOutOffset returns this for input DIEs that were not cloned into
220 // this CU's plain DWARF (e.g. routed only into the artificial type unit).
221 // OutDieOffsetArray is zero-initialized and a real DIE never lives at
222 // offset 0 (the CU header occupies the first bytes of the unit), so 0 is
223 // an unambiguous "no plain-DWARF copy" sentinel.
224 constexpr uint64_t NotClonedInPlainDWARF = 0;
225
226 std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx();
227 if (!ParentIdx)
228 return std::nullopt;
229 // Skip parents marked as declarations; the name table should only reference
230 // definitions.
231 if (dwarf::toUnsigned(InUnit.find(*ParentIdx, dwarf::DW_AT_declaration), 0))
232 return std::nullopt;
233 uint64_t ParentOutOffset = InUnit.getDieOutOffset(*ParentIdx);
234 if (ParentOutOffset == NotClonedInPlainDWARF)
235 return std::nullopt;
236 return ParentOutOffset;
237}
238
240 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
241 dwarf::Tag Tag, bool AvoidForPubSections, TypeEntry *TypeEntry) {
242 if (OutUnit.isCompileUnit()) {
243 assert(TypeEntry == nullptr);
245
247 Info.String = Name;
248 Info.OutOffset = OutDIE->getOffset();
249 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
250 Info.Tag = Tag;
251 Info.AvoidForPubSections = AvoidForPubSections;
252
253 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
254 return;
255 }
256
257 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
258 // unit (see saveNamespaceRecord).
259
260 assert(TypeEntry != nullptr);
263 Info.String = Name;
264 Info.OutOffset = 0xbaddef;
265 Info.Tag = Tag;
266 Info.AvoidForPubSections = AvoidForPubSections;
267 Info.OutDIE = OutDIE;
268 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
269
270 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
271}
273 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
275 if (OutUnit.isCompileUnit()) {
276 assert(TypeEntry == nullptr);
278
280 Info.String = Name;
281 Info.OutOffset = OutDIE->getOffset();
282 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
283 Info.Tag = Tag;
284
285 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
286 return;
287 }
288
289 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
290 // unit. The parent lookup via the input-side DIE tree is only valid for
291 // DIEs cloned into this CU's plain DWARF.
292
293 assert(TypeEntry != nullptr);
296 Info.String = Name;
297 Info.OutOffset = 0xbaddef;
298 Info.Tag = Tag;
299 Info.OutDIE = OutDIE;
300 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
301
302 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
303}
304
306 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
308 if (OutUnit.isCompileUnit()) {
309 assert(TypeEntry == nullptr);
311
313 Info.String = Name;
314 Info.OutOffset = OutDIE->getOffset();
315 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
316 Info.Tag = Tag;
317 Info.AvoidForPubSections = true;
318
319 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
320 return;
321 }
322
323 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
324 // unit (see saveNamespaceRecord).
325
326 assert(TypeEntry != nullptr);
329 Info.String = Name;
330 Info.OutOffset = 0xbaddef;
331 Info.Tag = Tag;
332 Info.AvoidForPubSections = true;
333 Info.OutDIE = OutDIE;
334 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
335
336 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
337}
338
340 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
341 dwarf::Tag Tag, uint32_t QualifiedNameHash, bool ObjcClassImplementation,
343 if (OutUnit.isCompileUnit()) {
344 assert(TypeEntry == nullptr);
346
348 Info.String = Name;
349 Info.OutOffset = OutDIE->getOffset();
350 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
351 Info.Tag = Tag;
352 Info.QualifiedNameHash = QualifiedNameHash;
353 Info.ObjcClassImplementation = ObjcClassImplementation;
354
355 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
356 return;
357 }
358
359 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
360 // unit (see saveNamespaceRecord).
361
362 assert(TypeEntry != nullptr);
364
366 Info.String = Name;
367 Info.OutOffset = 0xbaddef;
368 Info.Tag = Tag;
369 Info.QualifiedNameHash = QualifiedNameHash;
370 Info.ObjcClassImplementation = ObjcClassImplementation;
371 Info.OutDIE = OutDIE;
372 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
373 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
374}
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:828
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition DIE.h:866
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:541
LLVM_ABI DWARFDie getParent() const
Get the parent of this DIE object.
Definition DWARFDie.cpp:724
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:317
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:530
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:548
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
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:44
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.