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 DIE *OutDIE, AttributesInfo &AttrInfo,
21 if (GlobalData.getOptions().AccelTables.empty())
22 return;
23
24 DWARFDie InputDIE = InUnit.getDIE(InputDieEntry);
25
26 // Look for short name recursively if short name is not known yet.
27 if (AttrInfo.Name == nullptr)
28 if (const char *ShortName = InputDIE.getShortName())
29 AttrInfo.Name = GlobalData.getStringPool().insert(ShortName).first;
30
31 switch (InputDieEntry->getTag()) {
32 case dwarf::DW_TAG_array_type:
33 case dwarf::DW_TAG_class_type:
34 case dwarf::DW_TAG_enumeration_type:
35 case dwarf::DW_TAG_pointer_type:
36 case dwarf::DW_TAG_reference_type:
37 case dwarf::DW_TAG_string_type:
38 case dwarf::DW_TAG_structure_type:
39 case dwarf::DW_TAG_subroutine_type:
40 case dwarf::DW_TAG_template_alias:
41 case dwarf::DW_TAG_typedef:
42 case dwarf::DW_TAG_union_type:
43 case dwarf::DW_TAG_ptr_to_member_type:
44 case dwarf::DW_TAG_set_type:
45 case dwarf::DW_TAG_subrange_type:
46 case dwarf::DW_TAG_base_type:
47 case dwarf::DW_TAG_const_type:
48 case dwarf::DW_TAG_constant:
49 case dwarf::DW_TAG_file_type:
50 case dwarf::DW_TAG_namelist:
51 case dwarf::DW_TAG_packed_type:
52 case dwarf::DW_TAG_volatile_type:
53 case dwarf::DW_TAG_restrict_type:
54 case dwarf::DW_TAG_atomic_type:
55 case dwarf::DW_TAG_interface_type:
56 case dwarf::DW_TAG_unspecified_type:
57 case dwarf::DW_TAG_shared_type:
58 case dwarf::DW_TAG_immutable_type:
59 case dwarf::DW_TAG_rvalue_reference_type: {
60 if (AttrInfo.IsDeclaration)
61 break;
62
63 // The linkage name may be attached to the declaration rather than to the
64 // definition.
65 if (!AttrInfo.MangledName)
66 if (const char *LinkageName = InputDIE.getLinkageName())
67 AttrInfo.MangledName =
68 GlobalData.getStringPool().insert(LinkageName).first;
69
70 uint64_t RuntimeLang =
71 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
72 .value_or(0);
73
74 bool ObjCClassIsImplementation =
75 (RuntimeLang == dwarf::DW_LANG_ObjC ||
76 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
77 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
78 .value_or(0);
79
80 if (AttrInfo.Name != nullptr && !AttrInfo.Name->getKey().empty()) {
81 // A reference is relative to the unit of the DIE that holds it, which
82 // is the unit of the last DIE resolved.
85 InputDIE, [&](const DWARFDie &Referrer, const DWARFFormValue &Ref) {
86 assert(Referrer.getDwarfUnit() == &CU->getOrigUnit());
87 std::optional<UnitEntryPairTy> RefDie = CU->resolveDIEReference(
89 if (!RefDie || !RefDie->DieEntry)
90 return DWARFDie();
91 CU = RefDie->CU;
92 return CU->getDIE(RefDie->DieEntry);
93 });
94 saveTypeRecord(InputDieEntry, AttrInfo.Name, OutDIE,
95 InputDieEntry->getTag(), Hash, ObjCClassIsImplementation,
96 TypeEntry);
97 }
98
99 // Swift carries a type's mangled name in DW_AT_linkage_name, which a
100 // consumer may look up on its own.
101 if (AttrInfo.MangledName != nullptr &&
102 RuntimeLang == dwarf::DW_LANG_Swift &&
103 !AttrInfo.MangledName->getKey().empty() &&
104 AttrInfo.MangledName != AttrInfo.Name)
105 saveTypeRecord(InputDieEntry, AttrInfo.MangledName, OutDIE,
106 InputDieEntry->getTag(),
107 djbHash(AttrInfo.MangledName->getKey()),
108 ObjCClassIsImplementation, TypeEntry);
109 } break;
110 case dwarf::DW_TAG_namespace: {
111 if (AttrInfo.Name == nullptr)
112 AttrInfo.Name =
113 GlobalData.getStringPool().insert("(anonymous namespace)").first;
114
115 saveNamespaceRecord(InputDieEntry, AttrInfo.Name, OutDIE,
116 InputDieEntry->getTag(), TypeEntry);
117 } break;
118 case dwarf::DW_TAG_imported_declaration: {
119 if (AttrInfo.Name != nullptr)
120 saveNamespaceRecord(InputDieEntry, AttrInfo.Name, OutDIE,
121 InputDieEntry->getTag(), TypeEntry);
122 } break;
123 case dwarf::DW_TAG_compile_unit:
124 case dwarf::DW_TAG_lexical_block: {
125 // Nothing to do.
126 } break;
127 default:
128 // HasLiveAddress / HasRanges below decides whether a DIE carries enough
129 // information of its own to warrant a name record; the output unit is
130 // incidental and routed by the helpers.
131
132 if ((AttrInfo.HasLiveAddress || AttrInfo.HasRanges) &&
133 !(InputDieEntry->getTag() == dwarf::DW_TAG_variable &&
134 hasImplicitAddressLocation(InputDIE))) {
135 if (AttrInfo.Name)
137 InputDieEntry, AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
138 InputDieEntry->getTag() == dwarf::DW_TAG_inlined_subroutine,
139 TypeEntry);
140
141 // Look for mangled name recursively if mangled name is not known yet.
142 if (!AttrInfo.MangledName)
143 if (const char *LinkageName = InputDIE.getLinkageName())
144 AttrInfo.MangledName =
145 GlobalData.getStringPool().insert(LinkageName).first;
146
147 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
148 saveNameRecord(InputDieEntry, AttrInfo.MangledName, OutDIE,
149 InputDieEntry->getTag(),
150 InputDieEntry->getTag() ==
151 dwarf::DW_TAG_inlined_subroutine,
152 TypeEntry);
153
154 // Strip template parameters from the short name.
155 if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&
156 (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
157 if (std::optional<StringRef> Name =
158 StripTemplateParameters(AttrInfo.Name->getKey())) {
159 StringEntry *NameWithoutTemplateParams =
160 GlobalData.getStringPool().insert(*Name).first;
161
162 saveNameRecord(InputDieEntry, NameWithoutTemplateParams, OutDIE,
163 InputDieEntry->getTag(), true, TypeEntry);
164 }
165 }
166
167 if (AttrInfo.Name)
168 saveObjC(InputDieEntry, OutDIE, AttrInfo, TypeEntry);
169 }
170 break;
171 }
172}
173
175 DIE *OutDIE, AttributesInfo &AttrInfo,
177 std::optional<ObjCSelectorNames> Names =
179 if (!Names)
180 return;
181
182 StringEntry *Selector =
183 GlobalData.getStringPool().insert(Names->Selector).first;
184 saveNameRecord(InputDieEntry, Selector, OutDIE, InputDieEntry->getTag(), true,
185 TypeEntry);
186 StringEntry *ClassName =
187 GlobalData.getStringPool().insert(Names->ClassName).first;
188 saveObjCNameRecord(InputDieEntry, ClassName, OutDIE, InputDieEntry->getTag(),
189 TypeEntry);
190 if (Names->ClassNameNoCategory) {
191 StringEntry *ClassNameNoCategory =
192 GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;
193 saveObjCNameRecord(InputDieEntry, ClassNameNoCategory, OutDIE,
194 InputDieEntry->getTag(), TypeEntry);
195 }
196 if (Names->MethodNameNoCategory) {
197 StringEntry *MethodNameNoCategory =
198 GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
199 saveNameRecord(InputDieEntry, MethodNameNoCategory, OutDIE,
200 InputDieEntry->getTag(), true, TypeEntry);
201 }
202}
203
205 const DWARFDebugInfoEntry *InputDieEntry) {
206 // getDieOutOffset returns this for input DIEs that were not cloned into
207 // this CU's plain DWARF (e.g. routed only into the artificial type unit).
208 // OutDieOffsetArray is zero-initialized and a real DIE never lives at
209 // offset 0 (the CU header occupies the first bytes of the unit), so 0 is
210 // an unambiguous "no plain-DWARF copy" sentinel.
211 constexpr uint64_t NotClonedInPlainDWARF = 0;
212
213 std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx();
214 if (!ParentIdx)
215 return std::nullopt;
216 // Skip parents marked as declarations; the name table should only reference
217 // definitions.
218 if (dwarf::toUnsigned(InUnit.find(*ParentIdx, dwarf::DW_AT_declaration), 0))
219 return std::nullopt;
220 uint64_t ParentOutOffset = InUnit.getDieOutOffset(*ParentIdx);
221 if (ParentOutOffset == NotClonedInPlainDWARF)
222 return std::nullopt;
223 return ParentOutOffset;
224}
225
227 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
228 dwarf::Tag Tag, bool AvoidForPubSections, TypeEntry *TypeEntry) {
229 if (OutUnit.isCompileUnit()) {
230 assert(TypeEntry == nullptr);
232
234 Info.String = Name;
235 Info.OutOffset = OutDIE->getOffset();
236 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
237 Info.Tag = Tag;
238 Info.AvoidForPubSections = AvoidForPubSections;
239
240 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
241 return;
242 }
243
244 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
245 // unit (see saveNamespaceRecord).
246
247 assert(TypeEntry != nullptr);
250 Info.String = Name;
251 Info.OutOffset = 0xbaddef;
252 Info.Tag = Tag;
253 Info.AvoidForPubSections = AvoidForPubSections;
254 Info.OutDIE = OutDIE;
255 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
256
257 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
258}
260 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
262 if (OutUnit.isCompileUnit()) {
263 assert(TypeEntry == nullptr);
265
267 Info.String = Name;
268 Info.OutOffset = OutDIE->getOffset();
269 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
270 Info.Tag = Tag;
271
272 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
273 return;
274 }
275
276 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
277 // unit. The parent lookup via the input-side DIE tree is only valid for
278 // DIEs cloned into this CU's plain DWARF.
279
280 assert(TypeEntry != nullptr);
283 Info.String = Name;
284 Info.OutOffset = 0xbaddef;
285 Info.Tag = Tag;
286 Info.OutDIE = OutDIE;
287 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
288
289 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
290}
291
293 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
295 if (OutUnit.isCompileUnit()) {
296 assert(TypeEntry == nullptr);
298
300 Info.String = Name;
301 Info.OutOffset = OutDIE->getOffset();
302 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
303 Info.Tag = Tag;
304 Info.AvoidForPubSections = true;
305
306 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
307 return;
308 }
309
310 // TODO: compute DW_IDX_parent for entries emitted into the artificial type
311 // unit (see saveNamespaceRecord).
312
313 assert(TypeEntry != nullptr);
316 Info.String = Name;
317 Info.OutOffset = 0xbaddef;
318 Info.Tag = Tag;
319 Info.AvoidForPubSections = true;
320 Info.OutDIE = OutDIE;
321 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
322
323 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
324}
325
327 const DWARFDebugInfoEntry *InputDieEntry, StringEntry *Name, DIE *OutDIE,
328 dwarf::Tag Tag, uint32_t QualifiedNameHash, bool ObjcClassImplementation,
330 if (OutUnit.isCompileUnit()) {
331 assert(TypeEntry == nullptr);
333
335 Info.String = Name;
336 Info.OutOffset = OutDIE->getOffset();
337 Info.ParentOffset = getDefiningParentOutOffset(InputDieEntry);
338 Info.Tag = Tag;
339 Info.QualifiedNameHash = QualifiedNameHash;
340 Info.ObjcClassImplementation = ObjcClassImplementation;
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);
351
353 Info.String = Name;
354 Info.OutOffset = 0xbaddef;
355 Info.Tag = Tag;
356 Info.QualifiedNameHash = QualifiedNameHash;
357 Info.ObjcClassImplementation = ObjcClassImplementation;
358 Info.OutDIE = OutDIE;
359 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
360 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
361}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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:882
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 std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:335
DWARFUnit * getDwarfUnit() const
Definition DWARFDie.h:55
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
StringRef getKey() const
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
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)
Stores all information related to a compile unit, be it in its original instance of the object file o...
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:31
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:23
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
LLVM_ABI uint32_t hashFullyQualifiedName(DWARFDie Die, function_ref< DWARFDie(const DWARFDie &, const DWARFFormValue &)> ResolveRef)
Hash the fully qualified name of type Die for the Apple accelerator tables.
Definition Utils.cpp:127
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...
@ Ref
The access may reference the value stored in memory.
Definition ModRef.h:32
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...
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.