LLVM 22.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_typedef:
86 case dwarf::DW_TAG_union_type:
87 case dwarf::DW_TAG_ptr_to_member_type:
88 case dwarf::DW_TAG_set_type:
89 case dwarf::DW_TAG_subrange_type:
90 case dwarf::DW_TAG_base_type:
91 case dwarf::DW_TAG_const_type:
92 case dwarf::DW_TAG_constant:
93 case dwarf::DW_TAG_file_type:
94 case dwarf::DW_TAG_namelist:
95 case dwarf::DW_TAG_packed_type:
96 case dwarf::DW_TAG_volatile_type:
97 case dwarf::DW_TAG_restrict_type:
98 case dwarf::DW_TAG_atomic_type:
99 case dwarf::DW_TAG_interface_type:
100 case dwarf::DW_TAG_unspecified_type:
101 case dwarf::DW_TAG_shared_type:
102 case dwarf::DW_TAG_immutable_type:
103 case dwarf::DW_TAG_rvalue_reference_type: {
104 if (!AttrInfo.IsDeclaration && AttrInfo.Name != nullptr &&
105 !AttrInfo.Name->getKey().empty()) {
106 uint32_t Hash = hashFullyQualifiedName(InUnit, InputDIE);
107
108 uint64_t RuntimeLang =
109 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
110 .value_or(0);
111
112 bool ObjCClassIsImplementation =
113 (RuntimeLang == dwarf::DW_LANG_ObjC ||
114 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
116 InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
117 .value_or(0);
118
119 saveTypeRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(), Hash,
120 ObjCClassIsImplementation, TypeEntry);
121 }
122 } break;
123 case dwarf::DW_TAG_namespace: {
124 if (AttrInfo.Name == nullptr)
125 AttrInfo.Name =
126 GlobalData.getStringPool().insert("(anonymous namespace)").first;
127
128 saveNamespaceRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
129 TypeEntry);
130 } break;
131 case dwarf::DW_TAG_imported_declaration: {
132 if (AttrInfo.Name != nullptr)
133 saveNamespaceRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
134 TypeEntry);
135 } break;
136 case dwarf::DW_TAG_compile_unit:
137 case dwarf::DW_TAG_lexical_block: {
138 // Nothing to do.
139 } break;
140 default:
141 if (TypeEntry)
142 // Do not store this kind of accelerator entries for type entries.
143 return;
144
145 if (AttrInfo.HasLiveAddress || AttrInfo.HasRanges) {
146 if (AttrInfo.Name)
147 saveNameRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(),
148 InputDieEntry->getTag() ==
149 dwarf::DW_TAG_inlined_subroutine);
150
151 // Look for mangled name recursively if mangled name is not known yet.
152 if (!AttrInfo.MangledName)
153 if (const char *LinkageName = InputDIE.getLinkageName())
154 AttrInfo.MangledName =
155 GlobalData.getStringPool().insert(LinkageName).first;
156
157 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
158 saveNameRecord(AttrInfo.MangledName, OutDIE, InputDieEntry->getTag(),
159 InputDieEntry->getTag() ==
160 dwarf::DW_TAG_inlined_subroutine);
161
162 // Strip template parameters from the short name.
163 if (AttrInfo.Name && AttrInfo.MangledName != AttrInfo.Name &&
164 (InputDieEntry->getTag() != dwarf::DW_TAG_inlined_subroutine)) {
165 if (std::optional<StringRef> Name =
166 StripTemplateParameters(AttrInfo.Name->getKey())) {
167 StringEntry *NameWithoutTemplateParams =
168 GlobalData.getStringPool().insert(*Name).first;
169
170 saveNameRecord(NameWithoutTemplateParams, OutDIE,
171 InputDieEntry->getTag(), true);
172 }
173 }
174
175 if (AttrInfo.Name)
176 saveObjC(InputDieEntry, OutDIE, AttrInfo);
177 }
178 break;
179 }
180}
181
183 DIE *OutDIE, AttributesInfo &AttrInfo) {
184 std::optional<ObjCSelectorNames> Names =
186 if (!Names)
187 return;
188
189 StringEntry *Selector =
190 GlobalData.getStringPool().insert(Names->Selector).first;
191 saveNameRecord(Selector, OutDIE, InputDieEntry->getTag(), true);
192 StringEntry *ClassName =
193 GlobalData.getStringPool().insert(Names->ClassName).first;
194 saveObjCNameRecord(ClassName, OutDIE, InputDieEntry->getTag());
195 if (Names->ClassNameNoCategory) {
196 StringEntry *ClassNameNoCategory =
197 GlobalData.getStringPool().insert(*Names->ClassNameNoCategory).first;
198 saveObjCNameRecord(ClassNameNoCategory, OutDIE, InputDieEntry->getTag());
199 }
200 if (Names->MethodNameNoCategory) {
201 StringEntry *MethodNameNoCategory =
202 GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
203 saveNameRecord(MethodNameNoCategory, OutDIE, InputDieEntry->getTag(), true);
204 }
205}
206
209 bool AvoidForPubSections) {
211
213 Info.String = Name;
214 Info.OutOffset = OutDIE->getOffset();
215 Info.Tag = Tag;
216 Info.AvoidForPubSections = AvoidForPubSections;
217
218 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
219}
221 DIE *OutDIE, dwarf::Tag Tag,
223 if (OutUnit.isCompileUnit()) {
224 assert(TypeEntry == nullptr);
226
228 Info.String = Name;
229 Info.OutOffset = OutDIE->getOffset();
230 Info.Tag = Tag;
231
232 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
233 return;
234 }
235
236 assert(TypeEntry != nullptr);
239 Info.String = Name;
240 Info.OutOffset = 0xbaddef;
241 Info.Tag = Tag;
242 Info.OutDIE = OutDIE;
243 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
244
245 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
246}
247
249 dwarf::Tag Tag) {
251
253 Info.String = Name;
254 Info.OutOffset = OutDIE->getOffset();
255 Info.Tag = Tag;
256 Info.AvoidForPubSections = true;
257
258 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
259}
260
263 uint32_t QualifiedNameHash,
264 bool ObjcClassImplementation,
266 if (OutUnit.isCompileUnit()) {
267 assert(TypeEntry == nullptr);
269
271 Info.String = Name;
272 Info.OutOffset = OutDIE->getOffset();
273 Info.Tag = Tag;
274 Info.QualifiedNameHash = QualifiedNameHash;
275 Info.ObjcClassImplementation = ObjcClassImplementation;
276
277 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
278 return;
279 }
280
281 assert(TypeEntry != nullptr);
283
285 Info.String = Name;
286 Info.OutOffset = 0xbaddef;
287 Info.Tag = Tag;
288 Info.QualifiedNameHash = QualifiedNameHash;
289 Info.ObjcClassImplementation = ObjcClassImplementation;
290 Info.OutDIE = OutDIE;
291 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
292 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
293}
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.
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:474
LLVM_ABI DWARFDie getParent() const
Get the parent of this DIE object.
Definition DWARFDie.cpp:655
LLVM_ABI std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition DWARFDie.cpp:250
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:463
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:481
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
empty - Check if the string is empty.
Definition StringRef.h:151
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 saveTypeRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, uint32_t QualifiedNameHash, bool ObjcClassImplementation, TypeEntry *TypeEntry)
void saveObjC(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE, AttributesInfo &AttrInfo)
void saveNamespaceRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, TypeEntry *TypeEntry)
void saveObjCNameRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag)
CompileUnit::OutputUnitVariantPtr OutUnit
Compile unit or Artificial type unit corresponding to the output DWARF.
void save(const DWARFDebugInfoEntry *InputDieEntry, DIE *OutDIE, AttributesInfo &AttrInfo, TypeEntry *TypeEntry)
Save accelerator info for the specified OutDIE inside OutUnit.
void saveNameRecord(StringEntry *Name, DIE *OutDIE, dwarf::Tag Tag, bool AvoidForPubSections)
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:27
StringMapEntry< std::nullopt_t > 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:26
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:1083
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 fileds.