LLVM 19.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,
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 =
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
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
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
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
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
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();
293}
static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE, int ChildRecurseDepth=0)
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
std::string Name
if(VerifyEach)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::pair< KeyDataTy *, bool > insert(const KeyTy &NewValue)
Insert new value NewValue or return already existing entry.
A structured debug information entry.
Definition: DIE.h:819
unsigned getOffset() const
Get the compile/type unit relative offset of this DIE.
Definition: DIE.h:857
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:42
const char * getShortName() const
Return the DIE short name resolving DW_AT_specification or DW_AT_abstract_origin references if necess...
Definition: DWARFDie.cpp:456
DWARFDie getParent() const
Get the parent of this DIE object.
Definition: DWARFDie.cpp:637
std::optional< DWARFFormValue > find(dwarf::Attribute Attr) const
Extract the specified attribute from this DIE.
Definition: DWARFDie.cpp:250
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:445
dwarf::Tag getTag() const
Definition: DWARFDie.h:71
const char * getLinkageName() const
Return the DIE linkage name resolving DW_AT_specification or DW_AT_abstract_origin references if nece...
Definition: DWARFDie.cpp:463
bool isValid() const
Definition: DWARFDie.h:50
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Tagged union holding either a T or a Error.
Definition: Error.h:474
bool empty() const
Definition: SmallVector.h:94
const ValueTy & getValue() const
StringMapEntry - This is used to represent one value that is inserted into a StringMap.
StringRef getKey() const
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
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.
LinkingGlobalData & GlobalData
Global linking data.
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)
CompileUnit * getAsCompileUnit()
Returns CompileUnit if applicable.
void saveAcceleratorInfo(const DwarfUnit::AccelInfo &Info)
Save specified accelerator info Info.
const DWARFLinkerOptions & getOptions() const
Returns linking options.
StringPool & getStringPool()
Returns global string pool.
void saveAcceleratorInfo(const TypeUnitAccelInfo &Info)
Adds Info to the unit's accelerator records.
DWARFDie getDIE(const DWARFDebugInfoEntry *Die)
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.
Definition: AddressRanges.h:18
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:21
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:1041
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?
SmallVector< DWARFLinkerBase::AccelTableKind, 1 > AccelTables
The accelerator table kinds.
This structure keeps fields which would be used for creating accelerator table.
TypeUnitAccelInfo extends AccelInfo structure with type specific fileds.