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 if (TypeEntry)
144 // Do not store this kind of accelerator entries for type entries.
145 return;
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
153 // Look for mangled name recursively if mangled name is not known yet.
154 if (!AttrInfo.MangledName)
155 if (const char *LinkageName = InputDIE.getLinkageName())
156 AttrInfo.MangledName =
157 GlobalData.getStringPool().insert(LinkageName).first;
158
159 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
160 saveNameRecord(InputDieEntry, AttrInfo.MangledName, OutDIE,
161 InputDieEntry->getTag(),
162 InputDieEntry->getTag() ==
163 dwarf::DW_TAG_inlined_subroutine);
164
165 // Strip template parameters from the short name.
166 if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&
167 (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
168 if (std::optional<StringRef> Name =
169 StripTemplateParameters(AttrInfo.Name->getKey())) {
170 StringEntry *NameWithoutTemplateParams =
171 GlobalData.getStringPool().insert(*Name).first;
172
173 saveNameRecord(InputDieEntry, NameWithoutTemplateParams, OutDIE,
174 InputDieEntry->getTag(), true);
175 }
176 }
177
178 if (AttrInfo.Name)
179 saveObjC(InputDieEntry, OutDIE, AttrInfo);
180 }
181 break;
182 }
183}
184
186 DIE *OutDIE, AttributesInfo &AttrInfo) {
187 std::optional<ObjCSelectorNames> Names =
189 if (!Names)
190 return;
191
192 StringEntry *Selector =
193 GlobalData.getStringPool().insert(Names->Selector).first;
194 saveNameRecord(InputDieEntry, Selector, OutDIE, InputDieEntry->getTag(),
195 true);
196 StringEntry *ClassName =
197 GlobalData.getStringPool().insert(Names->ClassName).first;
198 saveObjCNameRecord(InputDieEntry, ClassName, OutDIE, InputDieEntry->getTag());
199 if (Names->ClassNameNoCategory) {
200 StringEntry *ClassNameNoCategory =
201 GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;
202 saveObjCNameRecord(InputDieEntry, ClassNameNoCategory, OutDIE,
203 InputDieEntry->getTag());
204 }
205 if (Names->MethodNameNoCategory) {
206 StringEntry *MethodNameNoCategory =
207 GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
208 saveNameRecord(InputDieEntry, MethodNameNoCategory, OutDIE,
209 InputDieEntry->getTag(), true);
210 }
211}
212
214 const DWARFDebugInfoEntry *InputDieEntry) {
215 // getDieOutOffset returns this for input DIEs that were not cloned into
216 // this CU's plain DWARF (e.g. routed only into the artificial type unit).
217 // OutDieOffsetArray is zero-initialized and a real DIE never lives at
218 // offset 0 (the CU header occupies the first bytes of the unit), so 0 is
219 // an unambiguous "no plain-DWARF copy" sentinel.
220 constexpr uint64_t NotClonedInPlainDWARF = 0;
221
222 std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx();
223 if (!ParentIdx)
224 return std::nullopt;
225 // Skip parents marked as declarations; the name table should only reference
226 // definitions.
227 if (dwarf::toUnsigned(InUnit.find(*ParentIdx, dwarf::DW_AT_declaration), 0))
228 return std::nullopt;
229 uint64_t ParentOutOffset = InUnit.getDieOutOffset(*ParentIdx);
230 if (ParentOutOffset == NotClonedInPlainDWARF)
231 return std::nullopt;
232 return ParentOutOffset;
233}
234
236 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
237 dwarf::Tag Tag, bool AvoidForPubSections) {
239
241 Info.String = Name;
242 Info.OutOffset = OutDIE->getOffset();
243 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
244 Info.Tag = Tag;
245 Info.AvoidForPubSections = AvoidForPubSections;
246
247 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
248}
250 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
252 if (OutUnit.isCompileUnit()) {
253 assert(TypeEntry == nullptr);
255
257 Info.String = Name;
258 Info.OutOffset = OutDIE->getOffset();
259 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
260 Info.Tag = Tag;
261
262 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
263 return;
264 }
265
266 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
267 // unit. The parent lookup via the input-side DIE tree is only valid for
268 // DIEs cloned into this CU's plain DWARF.
269
270 assert(TypeEntry != nullptr);
273 Info.String = Name;
274 Info.OutOffset = 0xbaddef;
275 Info.Tag = Tag;
276 Info.OutDIE = OutDIE;
277 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
278
279 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
280}
281
283 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
284 dwarf::Tag Tag) {
286
288 Info.String = Name;
289 Info.OutOffset = OutDIE->getOffset();
290 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
291 Info.Tag = Tag;
292 Info.AvoidForPubSections = true;
293
294 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
295}
296
298 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
299 dwarf::Tag Tag, uint32_t QualifiedNameHash, bool ObjcClassImplementation,
301 if (OutUnit.isCompileUnit()) {
302 assert(TypeEntry == nullptr);
304
306 Info.String = Name;
307 Info.OutOffset = OutDIE->getOffset();
308 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
309 Info.Tag = Tag;
310 Info.QualifiedNameHash = QualifiedNameHash;
311 Info.ObjcClassImplementation = ObjcClassImplementation;
312
313 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
314 return;
315 }
316
317 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
318 // unit (see saveNamespaceRecord).
319
320 assert(TypeEntry != nullptr);
322
324 Info.String = Name;
325 Info.OutOffset = 0xbaddef;
326 Info.Tag = Tag;
327 Info.QualifiedNameHash = QualifiedNameHash;
328 Info.ObjcClassImplementation = ObjcClassImplementation;
329 Info.OutDIE = OutDIE;
330 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
331 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
332}
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 saveNameRecord(const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, bool AvoidForPubSections)
void saveObjC(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE, AttributesInfo &AttrInfo)
void saveObjCNameRecord(const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag)
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)
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.