Revert " [LoongArch][ISel] Check the number of sign bits in `PatGprGpr_32` (#107432)"
[llvm-project.git] / llvm / lib / DWARFLinker / Parallel / AcceleratorRecordsSaver.cpp
blob9af22235455121d0ecb61756ef92461104f93130
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 //===----------------------------------------------------------------------===//
9 #include "AcceleratorRecordsSaver.h"
10 #include "llvm/DWARFLinker/Utils.h"
11 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
12 #include "llvm/Support/DJB.h"
14 using namespace llvm;
15 using namespace dwarf_linker;
16 using namespace dwarf_linker::parallel;
18 static uint32_t hashFullyQualifiedName(CompileUnit &InputCU, DWARFDie &InputDIE,
19 int ChildRecurseDepth = 0) {
20 const char *Name = nullptr;
21 CompileUnit *CU = &InputCU;
22 std::optional<DWARFFormValue> RefVal;
24 if (Error Err = finiteLoop([&]() -> Expected<bool> {
25 if (const char *CurrentName = InputDIE.getName(DINameKind::ShortName))
26 Name = CurrentName;
28 if (!(RefVal = InputDIE.find(dwarf::DW_AT_specification)) &&
29 !(RefVal = InputDIE.find(dwarf::DW_AT_abstract_origin)))
30 return false;
32 if (!RefVal->isFormClass(DWARFFormValue::FC_Reference))
33 return false;
35 std::optional<UnitEntryPairTy> RefDie = CU->resolveDIEReference(
36 *RefVal, ResolveInterCUReferencesMode::Resolve);
37 if (!RefDie)
38 return false;
40 if (!RefDie->DieEntry)
41 return false;
43 CU = RefDie->CU;
44 InputDIE = RefDie->CU->getDIE(RefDie->DieEntry);
45 return true;
46 })) {
47 consumeError(std::move(Err));
50 if (!Name && InputDIE.getTag() == dwarf::DW_TAG_namespace)
51 Name = "(anonymous namespace)";
53 DWARFDie ParentDie = InputDIE.getParent();
54 if (!ParentDie.isValid() || ParentDie.getTag() == dwarf::DW_TAG_compile_unit)
55 return djbHash(Name ? Name : "", djbHash(ChildRecurseDepth ? "" : "::"));
57 return djbHash(
58 (Name ? Name : ""),
59 djbHash((Name ? "::" : ""),
60 hashFullyQualifiedName(*CU, ParentDie, ++ChildRecurseDepth)));
63 void AcceleratorRecordsSaver::save(const DWARFDebugInfoEntry *InputDieEntry,
64 DIE *OutDIE, AttributesInfo &AttrInfo,
65 TypeEntry *TypeEntry) {
66 if (GlobalData.getOptions().AccelTables.empty())
67 return;
69 DWARFDie InputDIE = InUnit.getDIE(InputDieEntry);
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;
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);
108 uint64_t RuntimeLang =
109 dwarf::toUnsigned(InputDIE.find(dwarf::DW_AT_APPLE_runtime_class))
110 .value_or(0);
112 bool ObjCClassIsImplementation =
113 (RuntimeLang == dwarf::DW_LANG_ObjC ||
114 RuntimeLang == dwarf::DW_LANG_ObjC_plus_plus) &&
115 dwarf::toUnsigned(
116 InputDIE.find(dwarf::DW_AT_APPLE_objc_complete_type))
117 .value_or(0);
119 saveTypeRecord(AttrInfo.Name, OutDIE, InputDieEntry->getTag(), Hash,
120 ObjCClassIsImplementation, TypeEntry);
122 } break;
123 case dwarf::DW_TAG_namespace: {
124 if (AttrInfo.Name == nullptr)
125 AttrInfo.Name =
126 GlobalData.getStringPool().insert("(anonymous namespace)").first;
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;
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);
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;
157 if (AttrInfo.MangledName && AttrInfo.MangledName != AttrInfo.Name)
158 saveNameRecord(AttrInfo.MangledName, OutDIE, InputDieEntry->getTag(),
159 InputDieEntry->getTag() ==
160 dwarf::DW_TAG_inlined_subroutine);
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;
170 saveNameRecord(NameWithoutTemplateParams, OutDIE,
171 InputDieEntry->getTag(), true);
175 if (AttrInfo.Name)
176 saveObjC(InputDieEntry, OutDIE, AttrInfo);
178 break;
182 void AcceleratorRecordsSaver::saveObjC(const DWARFDebugInfoEntry *InputDieEntry,
183 DIE *OutDIE, AttributesInfo &AttrInfo) {
184 std::optional<ObjCSelectorNames> Names =
185 getObjCNamesIfSelector(AttrInfo.Name->getKey());
186 if (!Names)
187 return;
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());
200 if (Names->MethodNameNoCategory) {
201 StringEntry *MethodNameNoCategory =
202 GlobalData.getStringPool().insert(*Names->MethodNameNoCategory).first;
203 saveNameRecord(MethodNameNoCategory, OutDIE, InputDieEntry->getTag(), true);
207 void AcceleratorRecordsSaver::saveNameRecord(StringEntry *Name, DIE *OutDIE,
208 dwarf::Tag Tag,
209 bool AvoidForPubSections) {
210 DwarfUnit::AccelInfo Info;
212 Info.Type = DwarfUnit::AccelType::Name;
213 Info.String = Name;
214 Info.OutOffset = OutDIE->getOffset();
215 Info.Tag = Tag;
216 Info.AvoidForPubSections = AvoidForPubSections;
218 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
220 void AcceleratorRecordsSaver::saveNamespaceRecord(StringEntry *Name,
221 DIE *OutDIE, dwarf::Tag Tag,
222 TypeEntry *TypeEntry) {
223 if (OutUnit.isCompileUnit()) {
224 assert(TypeEntry == nullptr);
225 DwarfUnit::AccelInfo Info;
227 Info.Type = DwarfUnit::AccelType::Namespace;
228 Info.String = Name;
229 Info.OutOffset = OutDIE->getOffset();
230 Info.Tag = Tag;
232 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
233 return;
236 assert(TypeEntry != nullptr);
237 TypeUnit::TypeUnitAccelInfo Info;
238 Info.Type = DwarfUnit::AccelType::Namespace;
239 Info.String = Name;
240 Info.OutOffset = 0xbaddef;
241 Info.Tag = Tag;
242 Info.OutDIE = OutDIE;
243 Info.TypeEntryBodyPtr = TypeEntry->getValue().load();
245 OutUnit.getAsTypeUnit()->saveAcceleratorInfo(Info);
248 void AcceleratorRecordsSaver::saveObjCNameRecord(StringEntry *Name, DIE *OutDIE,
249 dwarf::Tag Tag) {
250 DwarfUnit::AccelInfo Info;
252 Info.Type = DwarfUnit::AccelType::ObjC;
253 Info.String = Name;
254 Info.OutOffset = OutDIE->getOffset();
255 Info.Tag = Tag;
256 Info.AvoidForPubSections = true;
258 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
261 void AcceleratorRecordsSaver::saveTypeRecord(StringEntry *Name, DIE *OutDIE,
262 dwarf::Tag Tag,
263 uint32_t QualifiedNameHash,
264 bool ObjcClassImplementation,
265 TypeEntry *TypeEntry) {
266 if (OutUnit.isCompileUnit()) {
267 assert(TypeEntry == nullptr);
268 DwarfUnit::AccelInfo Info;
270 Info.Type = DwarfUnit::AccelType::Type;
271 Info.String = Name;
272 Info.OutOffset = OutDIE->getOffset();
273 Info.Tag = Tag;
274 Info.QualifiedNameHash = QualifiedNameHash;
275 Info.ObjcClassImplementation = ObjcClassImplementation;
277 OutUnit.getAsCompileUnit()->saveAcceleratorInfo(Info);
278 return;
281 assert(TypeEntry != nullptr);
282 TypeUnit::TypeUnitAccelInfo Info;
284 Info.Type = DwarfUnit::AccelType::Type;
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);