1//===- SyntheticTypeNameBuilder.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
9#include "SyntheticTypeNameBuilder.h"
10#include "DWARFLinkerCompileUnit.h"
11#include "llvm/DWARFLinker/Utils.h"
12#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
13#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
14#include "llvm/DebugInfo/DWARF/DWARFDie.h"
15
16using namespace llvm;
17using namespace dwarf_linker;
18using namespace dwarf_linker::parallel;
19
20Error SyntheticTypeNameBuilder::assignName(
21 UnitEntryPairTy InputUnitEntryPair,
22 std::optional<std::pair<size_t, size_t>> ChildIndex) {
23 [[maybe_unused]] const CompileUnit::DIEInfo &Info =
24 InputUnitEntryPair.CU->getDIEInfo(Entry: InputUnitEntryPair.DieEntry);
25 assert(Info.needToPlaceInTypeTable() &&
26 "Cann't assign name for non-type DIE");
27
28 if (InputUnitEntryPair.CU->getDieTypeEntry(InputDieEntry: InputUnitEntryPair.DieEntry) !=
29 nullptr)
30 return Error::success();
31
32 SyntheticName.resize(N: 0);
33 RecursionDepth = 0;
34 return addDIETypeName(InputUnitEntryPair, ChildIndex, AssignNameToTypeDescriptor: true);
35}
36
37void SyntheticTypeNameBuilder::addArrayDimension(
38 UnitEntryPairTy InputUnitEntryPair) {
39 for (const DWARFDebugInfoEntry *CurChild =
40 InputUnitEntryPair.CU->getFirstChildEntry(
41 Die: InputUnitEntryPair.DieEntry);
42 CurChild && CurChild->getAbbreviationDeclarationPtr();
43 CurChild = InputUnitEntryPair.CU->getSiblingEntry(Die: CurChild)) {
44 if (CurChild->getTag() == dwarf::DW_TAG_subrange_type ||
45 CurChild->getTag() == dwarf::DW_TAG_generic_subrange) {
46 SyntheticName += "[";
47 if (std::optional<DWARFFormValue> Val =
48 InputUnitEntryPair.CU->find(Die: CurChild, Attrs: dwarf::DW_AT_count)) {
49 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
50 SyntheticName += std::to_string(val: *ConstVal);
51 } else if (std::optional<int64_t> ConstVal =
52 Val->getAsSignedConstant()) {
53 SyntheticName += std::to_string(val: *ConstVal);
54 }
55 }
56
57 SyntheticName += "]";
58 }
59 }
60}
61
62static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type};
63Error SyntheticTypeNameBuilder::addSignature(UnitEntryPairTy InputUnitEntryPair,
64 bool addTemplateParameters) {
65 // Add entry type.
66 if (Error Err = addReferencedODRDies(InputUnitEntryPair, AssignNameToTypeDescriptor: false, ODRAttrs: TypeAttr))
67 return Err;
68 SyntheticName += ':';
69
70 SmallVector<const DWARFDebugInfoEntry *, 10> TemplateParameters;
71 SmallVector<const DWARFDebugInfoEntry *, 20> FunctionParameters;
72 for (const DWARFDebugInfoEntry *CurChild =
73 InputUnitEntryPair.CU->getFirstChildEntry(
74 Die: InputUnitEntryPair.DieEntry);
75 CurChild && CurChild->getAbbreviationDeclarationPtr();
76 CurChild = InputUnitEntryPair.CU->getSiblingEntry(Die: CurChild)) {
77 dwarf::Tag ChildTag = CurChild->getTag();
78 if (addTemplateParameters &&
79 (ChildTag == dwarf::DW_TAG_template_type_parameter ||
80 ChildTag == dwarf::DW_TAG_template_value_parameter))
81 TemplateParameters.push_back(Elt: CurChild);
82 else if (ChildTag == dwarf::DW_TAG_formal_parameter ||
83 ChildTag == dwarf::DW_TAG_unspecified_parameters)
84 FunctionParameters.push_back(Elt: CurChild);
85 else if (addTemplateParameters &&
86 ChildTag == dwarf::DW_TAG_GNU_template_parameter_pack) {
87 for (const DWARFDebugInfoEntry *CurGNUChild =
88 InputUnitEntryPair.CU->getFirstChildEntry(Die: CurChild);
89 CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
90 CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(Die: CurGNUChild))
91 TemplateParameters.push_back(Elt: CurGNUChild);
92 } else if (ChildTag == dwarf::DW_TAG_GNU_formal_parameter_pack) {
93 for (const DWARFDebugInfoEntry *CurGNUChild =
94 InputUnitEntryPair.CU->getFirstChildEntry(Die: CurChild);
95 CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
96 CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(Die: CurGNUChild))
97 FunctionParameters.push_back(Elt: CurGNUChild);
98 }
99 }
100
101 // Add parameters.
102 if (Error Err = addParamNames(CU&: *InputUnitEntryPair.CU, FunctionParameters))
103 return Err;
104
105 // Add template parameters.
106 if (Error Err =
107 addTemplateParamNames(CU&: *InputUnitEntryPair.CU, TemplateParameters))
108 return Err;
109
110 return Error::success();
111}
112
113Error SyntheticTypeNameBuilder::addParamNames(
114 CompileUnit &CU,
115 SmallVector<const DWARFDebugInfoEntry *, 20> &FunctionParameters) {
116 SyntheticName += '(';
117 for (const DWARFDebugInfoEntry *FunctionParameter : FunctionParameters) {
118 if (SyntheticName.back() != '(')
119 SyntheticName += ", ";
120 if (dwarf::toUnsigned(V: CU.find(Die: FunctionParameter, Attrs: dwarf::DW_AT_artificial),
121 Default: 0))
122 SyntheticName += "^";
123 if (Error Err = addReferencedODRDies(
124 InputUnitEntryPair: UnitEntryPairTy{&CU, FunctionParameter}, AssignNameToTypeDescriptor: false, ODRAttrs: TypeAttr))
125 return Err;
126 }
127 SyntheticName += ')';
128 return Error::success();
129}
130
131Error SyntheticTypeNameBuilder::addTemplateParamNames(
132 CompileUnit &CU,
133 SmallVector<const DWARFDebugInfoEntry *, 10> &TemplateParameters) {
134 if (!TemplateParameters.empty()) {
135 SyntheticName += '<';
136 for (const DWARFDebugInfoEntry *Parameter : TemplateParameters) {
137 if (SyntheticName.back() != '<')
138 SyntheticName += ", ";
139
140 if (Parameter->getTag() == dwarf::DW_TAG_template_value_parameter) {
141 if (std::optional<DWARFFormValue> Val =
142 CU.find(Die: Parameter, Attrs: dwarf::DW_AT_const_value)) {
143 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant())
144 SyntheticName += std::to_string(val: *ConstVal);
145 else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant())
146 SyntheticName += std::to_string(val: *ConstVal);
147 }
148 }
149
150 if (Error Err = addReferencedODRDies(InputUnitEntryPair: UnitEntryPairTy{&CU, Parameter},
151 AssignNameToTypeDescriptor: false, ODRAttrs: TypeAttr))
152 return Err;
153 }
154 SyntheticName += '>';
155 }
156 return Error::success();
157}
158
159void SyntheticTypeNameBuilder::addOrderedName(
160 std::pair<size_t, size_t> ChildIdx) {
161 std::string Name;
162 llvm::raw_string_ostream stream(Name);
163 stream << format_hex_no_prefix(N: ChildIdx.first, Width: ChildIdx.second);
164 SyntheticName += Name;
165}
166
167// Examine DIE and return type deduplication candidate: some DIEs could not be
168// deduplicated, namespace may refer to another namespace.
169static std::optional<UnitEntryPairTy>
170getTypeDeduplicationCandidate(UnitEntryPairTy UnitEntryPair) {
171 switch (UnitEntryPair.DieEntry->getTag()) {
172 case dwarf::DW_TAG_null:
173 case dwarf::DW_TAG_compile_unit:
174 case dwarf::DW_TAG_partial_unit:
175 case dwarf::DW_TAG_type_unit:
176 case dwarf::DW_TAG_skeleton_unit: {
177 return std::nullopt;
178 }
179 case dwarf::DW_TAG_namespace: {
180 // Check if current namespace refers another.
181 if (UnitEntryPair.CU->find(Die: UnitEntryPair.DieEntry, Attrs: dwarf::DW_AT_extension))
182 UnitEntryPair = UnitEntryPair.getNamespaceOrigin();
183
184 // Content of anonimous namespaces should not be deduplicated.
185 if (!UnitEntryPair.CU->find(Die: UnitEntryPair.DieEntry, Attrs: dwarf::DW_AT_name))
186 llvm_unreachable("Cann't deduplicate anonimous namespace");
187
188 return UnitEntryPair;
189 }
190 default:
191 return UnitEntryPair;
192 }
193}
194
195Error SyntheticTypeNameBuilder::addParentName(
196 UnitEntryPairTy &InputUnitEntryPair) {
197 std::optional<UnitEntryPairTy> UnitEntryPair = InputUnitEntryPair.getParent();
198 if (!UnitEntryPair)
199 return Error::success();
200
201 UnitEntryPair = getTypeDeduplicationCandidate(UnitEntryPair: *UnitEntryPair);
202 if (!UnitEntryPair)
203 return Error::success();
204
205 if (TypeEntry *ImmediateParentName =
206 UnitEntryPair->CU->getDieTypeEntry(InputDieEntry: UnitEntryPair->DieEntry)) {
207 SyntheticName += ImmediateParentName->getKey();
208 SyntheticName += ".";
209 return Error::success();
210 }
211
212 // Collect parent entries.
213 SmallVector<UnitEntryPairTy, 10> Parents;
214 do {
215 Parents.push_back(Elt: *UnitEntryPair);
216
217 UnitEntryPair = UnitEntryPair->getParent();
218 if (!UnitEntryPair)
219 break;
220
221 UnitEntryPair = getTypeDeduplicationCandidate(UnitEntryPair: *UnitEntryPair);
222 if (!UnitEntryPair)
223 break;
224
225 } while (!UnitEntryPair->CU->getDieTypeEntry(InputDieEntry: UnitEntryPair->DieEntry));
226
227 // Assign name for each parent entry.
228 size_t NameStart = SyntheticName.size();
229 for (UnitEntryPairTy Parent : reverse(C&: Parents)) {
230 SyntheticName.resize(N: NameStart);
231 if (Error Err = addDIETypeName(InputUnitEntryPair: Parent, ChildIndex: std::nullopt, AssignNameToTypeDescriptor: true))
232 return Err;
233 }
234
235 // Add parents delimiter.
236 SyntheticName += ".";
237 return Error::success();
238}
239
240void SyntheticTypeNameBuilder::addDieNameFromDeclFileAndDeclLine(
241 UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName) {
242 if (std::optional<DWARFFormValue> DeclFileVal = InputUnitEntryPair.CU->find(
243 Die: InputUnitEntryPair.DieEntry, Attrs: dwarf::DW_AT_decl_file)) {
244 if (std::optional<DWARFFormValue> DeclLineVal = InputUnitEntryPair.CU->find(
245 Die: InputUnitEntryPair.DieEntry, Attrs: dwarf::DW_AT_decl_line)) {
246 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
247 InputUnitEntryPair.CU->getDirAndFilenameFromLineTable(
248 FileIdxValue: *DeclFileVal)) {
249 SyntheticName += DirAndFilename->first;
250 SyntheticName += DirAndFilename->second;
251
252 if (std::optional<uint64_t> DeclLineIntVal =
253 dwarf::toUnsigned(V: *DeclLineVal)) {
254 SyntheticName += " ";
255 SyntheticName += utohexstr(X: *DeclLineIntVal);
256 }
257
258 HasDeclFileName = true;
259 }
260 }
261 }
262}
263
264void SyntheticTypeNameBuilder::addValueName(UnitEntryPairTy InputUnitEntryPair,
265 dwarf::Attribute Attr) {
266 if (std::optional<DWARFFormValue> Val =
267 InputUnitEntryPair.CU->find(Die: InputUnitEntryPair.DieEntry, Attrs: Attr)) {
268 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
269 SyntheticName += " ";
270 SyntheticName += std::to_string(val: *ConstVal);
271 } else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant()) {
272 SyntheticName += " ";
273 SyntheticName += std::to_string(val: *ConstVal);
274 }
275 }
276}
277
278Expected<std::optional<UnitEntryPairTy>>
279SyntheticTypeNameBuilder::resolveReference(UnitEntryPairTy InputUnitEntryPair,
280 dwarf::Attribute Attr) {
281 std::optional<DWARFFormValue> AttrValue =
282 InputUnitEntryPair.CU->find(Die: InputUnitEntryPair.DieEntry, Attrs: Attr);
283 if (!AttrValue)
284 return std::nullopt;
285
286 std::optional<UnitEntryPairTy> RefDie =
287 InputUnitEntryPair.CU->resolveDIEReference(
288 RefValue: *AttrValue, CanResolveInterCUReferences: ResolveInterCUReferencesMode::Resolve);
289 if (RefDie && !RefDie->DieEntry)
290 return createStringError(EC: std::errc::invalid_argument,
291 Fmt: "cannot resolve DIE reference");
292 return RefDie;
293}
294
295Error SyntheticTypeNameBuilder::incrementRecursionDepth() {
296 if (++RecursionDepth > MaxRecursionDepth)
297 return createStringError(EC: std::errc::invalid_argument,
298 Fmt: "cannot parse input DWARF: recursive dependence");
299 return Error::success();
300}
301
302Error SyntheticTypeNameBuilder::addReferencedODRDies(
303 UnitEntryPairTy InputUnitEntryPair, bool AssignNameToTypeDescriptor,
304 ArrayRef<dwarf::Attribute> ODRAttrs) {
305 bool FirstIteration = true;
306 for (dwarf::Attribute Attr : ODRAttrs) {
307 Expected<std::optional<UnitEntryPairTy>> RefDie =
308 resolveReference(InputUnitEntryPair, Attr);
309 if (!RefDie)
310 return RefDie.takeError();
311 if (!*RefDie)
312 continue;
313
314 if (!FirstIteration)
315 SyntheticName += ",";
316
317 if (Error Err = incrementRecursionDepth())
318 return Err;
319 if (Error Err =
320 addDIETypeName(InputUnitEntryPair: **RefDie, ChildIndex: std::nullopt, AssignNameToTypeDescriptor))
321 return Err;
322 RecursionDepth--;
323 FirstIteration = false;
324 }
325
326 return Error::success();
327}
328
329Error SyntheticTypeNameBuilder::addTypeName(UnitEntryPairTy InputUnitEntryPair,
330 bool AddParentNames) {
331 bool HasLinkageName = false;
332 bool HasShortName = false;
333 bool HasTemplatesInShortName = false;
334 bool HasDeclFileName = false;
335
336 // Try to get name from the DIE.
337 if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
338 Die: InputUnitEntryPair.DieEntry,
339 Attrs: {dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_AT_linkage_name})) {
340 // Firstly check for linkage name.
341 SyntheticName += dwarf::toStringRef(V: Val);
342 HasLinkageName = true;
343 } else if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
344 Die: InputUnitEntryPair.DieEntry, Attrs: dwarf::DW_AT_name)) {
345 // Then check for short name.
346 StringRef Name = dwarf::toStringRef(V: Val);
347 SyntheticName += Name;
348
349 HasShortName = true;
350 HasTemplatesInShortName =
351 Name.ends_with(Suffix: ">") && Name.count(Str: "<") != 0 && !Name.ends_with(Suffix: "<=>");
352 } else {
353 // Finally check for declaration attributes.
354 addDieNameFromDeclFileAndDeclLine(InputUnitEntryPair, HasDeclFileName);
355
356 // Unnamed types declared on one line differ only in their contents.
357 if (HasDeclFileName)
358 if (Error Err = addUnnamedTypeContents(InputUnitEntryPair))
359 return Err;
360 }
361
362 // Add additional name parts for some DIEs.
363 switch (InputUnitEntryPair.DieEntry->getTag()) {
364 case dwarf::DW_TAG_union_type:
365 case dwarf::DW_TAG_interface_type:
366 case dwarf::DW_TAG_class_type:
367 case dwarf::DW_TAG_structure_type:
368 case dwarf::DW_TAG_subroutine_type:
369 case dwarf::DW_TAG_subprogram: {
370 if (InputUnitEntryPair.CU->find(Die: InputUnitEntryPair.DieEntry,
371 Attrs: dwarf::DW_AT_artificial))
372 SyntheticName += "^";
373
374 // No need to add signature information for linkage name,
375 // also no need to add template parameters name if short name already
376 // includes them.
377 if (!HasLinkageName)
378 if (Error Err =
379 addSignature(InputUnitEntryPair, addTemplateParameters: !HasTemplatesInShortName))
380 return Err;
381 } break;
382 case dwarf::DW_TAG_coarray_type:
383 case dwarf::DW_TAG_array_type: {
384 addArrayDimension(InputUnitEntryPair);
385 } break;
386 case dwarf::DW_TAG_subrange_type: {
387 addValueName(InputUnitEntryPair, Attr: dwarf::DW_AT_count);
388 } break;
389 case dwarf::DW_TAG_template_value_parameter: {
390 if (!HasTemplatesInShortName) {
391 // TODO add support for DW_AT_location
392 addValueName(InputUnitEntryPair, Attr: dwarf::DW_AT_const_value);
393 }
394 } break;
395 default: {
396 // Nothing to do.
397 } break;
398 }
399
400 // If name for the DIE is not determined yet or if the DIE is a typedef, add
401 // referenced types to the name.
402 if ((!HasLinkageName && !HasShortName && !HasDeclFileName) ||
403 InputUnitEntryPair.DieEntry->getTag() == dwarf::DW_TAG_typedef) {
404 if (InputUnitEntryPair.CU->find(Die: InputUnitEntryPair.DieEntry,
405 Attrs: getODRAttributes()))
406 if (Error Err = addReferencedODRDies(InputUnitEntryPair, AssignNameToTypeDescriptor: AddParentNames,
407 ODRAttrs: getODRAttributes()))
408 return Err;
409 }
410
411 return Error::success();
412}
413
414Error SyntheticTypeNameBuilder::addDIETypeName(
415 UnitEntryPairTy InputUnitEntryPair,
416 std::optional<std::pair<size_t, size_t>> ChildIndex,
417 bool AssignNameToTypeDescriptor) {
418 std::optional<UnitEntryPairTy> UnitEntryPair =
419 getTypeDeduplicationCandidate(UnitEntryPair: InputUnitEntryPair);
420 if (!UnitEntryPair)
421 return Error::success();
422
423 TypeEntry *TypeEntryPtr =
424 InputUnitEntryPair.CU->getDieTypeEntry(InputDieEntry: InputUnitEntryPair.DieEntry);
425 // Check if DIE already has a name.
426 if (!TypeEntryPtr) {
427 size_t NameStart = SyntheticName.size();
428 // Prepend the parent scope so this name matches the key the type is
429 // stored under in the pool (the getKey() branch below). Otherwise the
430 // same type gets different names depending on whether it already has a
431 // pool entry, which races under parallel assignment and breaks
432 // deterministic deduplication.
433 if (Error Err = addParentName(InputUnitEntryPair&: *UnitEntryPair))
434 return Err;
435 addTypePrefix(CU&: *UnitEntryPair->CU, DieEntry: UnitEntryPair->DieEntry);
436
437 if (ChildIndex) {
438 addOrderedName(ChildIdx: *ChildIndex);
439 } else {
440 if (Error Err = addTypeName(InputUnitEntryPair: *UnitEntryPair, AddParentNames: AssignNameToTypeDescriptor))
441 return Err;
442 }
443
444 if (AssignNameToTypeDescriptor) {
445 // Add built name to the DIE.
446 TypeEntryPtr = TypePoolRef.insert(Name: SyntheticName.substr(Start: NameStart));
447 InputUnitEntryPair.CU->setDieTypeEntry(InputDieEntry: InputUnitEntryPair.DieEntry,
448 Entry: TypeEntryPtr);
449 }
450 } else
451 SyntheticName += TypeEntryPtr->getKey();
452
453 return Error::success();
454}
455
456Error SyntheticTypeNameBuilder::addUnnamedTypeContents(
457 UnitEntryPairTy InputUnitEntryPair) {
458 if (!isIdentifiedByChildren(Tag: InputUnitEntryPair.DieEntry->getTag()))
459 return Error::success();
460
461 CompileUnit &CU = *InputUnitEntryPair.CU;
462 SyntheticName += '(';
463 for (const DWARFDebugInfoEntry *CurChild =
464 CU.getFirstChildEntry(Die: InputUnitEntryPair.DieEntry);
465 CurChild && CurChild->getAbbreviationDeclarationPtr();
466 CurChild = CU.getSiblingEntry(Die: CurChild)) {
467 if (!isIdentifyingChild(Die: DWARFDie(&CU.getOrigUnit(), CurChild)))
468 continue;
469
470 if (SyntheticName.back() != '(')
471 SyntheticName += ", ";
472 addTypePrefix(CU, DieEntry: CurChild);
473 if (std::optional<DWARFFormValue> Val =
474 CU.find(Die: CurChild, Attrs: dwarf::DW_AT_name))
475 SyntheticName += dwarf::toStringRef(V: Val);
476 if (Error Err = addUnqualifiedTypeName(InputUnitEntryPair: UnitEntryPairTy{&CU, CurChild}))
477 return Err;
478 }
479 SyntheticName += ')';
480 return Error::success();
481}
482
483Error SyntheticTypeNameBuilder::addUnqualifiedTypeName(
484 UnitEntryPairTy InputUnitEntryPair) {
485 Expected<std::optional<UnitEntryPairTy>> RefDie =
486 resolveReference(InputUnitEntryPair, Attr: dwarf::DW_AT_type);
487 if (!RefDie)
488 return RefDie.takeError();
489 if (!*RefDie)
490 return Error::success();
491
492 if (Error Err = incrementRecursionDepth())
493 return Err;
494
495 UnitEntryPairTy Type = **RefDie;
496 SyntheticName += ':';
497 addTypePrefix(CU&: *Type.CU, DieEntry: Type.DieEntry);
498 if (std::optional<DWARFFormValue> Val =
499 Type.CU->find(Die: Type.DieEntry, Attrs: dwarf::DW_AT_name)) {
500 SyntheticName += dwarf::toStringRef(V: Val);
501 } else {
502 if (Type.DieEntry->getTag() == dwarf::DW_TAG_array_type)
503 addArrayDimension(InputUnitEntryPair: Type);
504 if (Error Err = addUnnamedTypeContents(InputUnitEntryPair: Type))
505 return Err;
506 if (Error Err = addUnqualifiedTypeName(InputUnitEntryPair: Type))
507 return Err;
508 }
509
510 RecursionDepth--;
511 return Error::success();
512}
513
514void SyntheticTypeNameBuilder::addTypePrefix(
515 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
516 switch (DieEntry->getTag()) {
517 case dwarf::DW_TAG_base_type: {
518 SyntheticName += "{0}";
519 } break;
520 case dwarf::DW_TAG_namespace: {
521 SyntheticName += "{1}";
522 } break;
523 case dwarf::DW_TAG_formal_parameter: {
524 SyntheticName += "{2}";
525 } break;
526 // dwarf::DW_TAG_unspecified_parameters have the same prefix as before.
527 case dwarf::DW_TAG_unspecified_parameters: {
528 SyntheticName += "{2}";
529 } break;
530 case dwarf::DW_TAG_template_type_parameter: {
531 SyntheticName += "{3}";
532 } break;
533 // dwarf::DW_TAG_template_value_parameter have the same prefix as before.
534 case dwarf::DW_TAG_template_value_parameter: {
535 SyntheticName += "{3}";
536 } break;
537 case dwarf::DW_TAG_GNU_formal_parameter_pack: {
538 SyntheticName += "{4}";
539 } break;
540 case dwarf::DW_TAG_GNU_template_parameter_pack: {
541 SyntheticName += "{5}";
542 } break;
543 case dwarf::DW_TAG_inheritance: {
544 SyntheticName += "{6}";
545 } break;
546 case dwarf::DW_TAG_array_type: {
547 SyntheticName += "{7}";
548 } break;
549 case dwarf::DW_TAG_class_type: {
550 SyntheticName += "{8}";
551 } break;
552 case dwarf::DW_TAG_enumeration_type: {
553 SyntheticName += "{9}";
554 } break;
555 case dwarf::DW_TAG_imported_declaration: {
556 SyntheticName += "{A}";
557 } break;
558 case dwarf::DW_TAG_member: {
559 // Treat a static data member the same way regardless of whether it's
560 // described as a DW_TAG_member or a DW_TAG_variable.
561 if (isStaticDataMember(Die: DWARFDie(&CU.getOrigUnit(), DieEntry)))
562 SyntheticName += "{d}";
563 else
564 SyntheticName += "{B}";
565 } break;
566 case dwarf::DW_TAG_pointer_type: {
567 SyntheticName += "{C}";
568 } break;
569 case dwarf::DW_TAG_reference_type: {
570 SyntheticName += "{D}";
571 } break;
572 case dwarf::DW_TAG_string_type: {
573 SyntheticName += "{E}";
574 } break;
575 case dwarf::DW_TAG_structure_type: {
576 SyntheticName += "{F}";
577 } break;
578 case dwarf::DW_TAG_subroutine_type: {
579 SyntheticName += "{G}";
580 } break;
581 case dwarf::DW_TAG_typedef: {
582 SyntheticName += "{H}";
583 } break;
584 case dwarf::DW_TAG_union_type: {
585 SyntheticName += "{I}";
586 } break;
587 case dwarf::DW_TAG_variant: {
588 SyntheticName += "{J}";
589 } break;
590 case dwarf::DW_TAG_inlined_subroutine: {
591 SyntheticName += "{K}";
592 } break;
593 case dwarf::DW_TAG_module: {
594 SyntheticName += "{L}";
595 } break;
596 case dwarf::DW_TAG_ptr_to_member_type: {
597 SyntheticName += "{M}";
598 } break;
599 case dwarf::DW_TAG_set_type: {
600 SyntheticName += "{N}";
601 } break;
602 case dwarf::DW_TAG_subrange_type: {
603 SyntheticName += "{O}";
604 } break;
605 case dwarf::DW_TAG_with_stmt: {
606 SyntheticName += "{P}";
607 } break;
608 case dwarf::DW_TAG_access_declaration: {
609 SyntheticName += "{Q}";
610 } break;
611 case dwarf::DW_TAG_catch_block: {
612 SyntheticName += "{R}";
613 } break;
614 case dwarf::DW_TAG_const_type: {
615 SyntheticName += "{S}";
616 } break;
617 case dwarf::DW_TAG_constant: {
618 SyntheticName += "{T}";
619 } break;
620 case dwarf::DW_TAG_enumerator: {
621 SyntheticName += "{U}";
622 } break;
623 case dwarf::DW_TAG_file_type: {
624 SyntheticName += "{V}";
625 } break;
626 case dwarf::DW_TAG_friend: {
627 SyntheticName += "{W}";
628 } break;
629 case dwarf::DW_TAG_namelist: {
630 SyntheticName += "{X}";
631 } break;
632 case dwarf::DW_TAG_namelist_item: {
633 SyntheticName += "{Y}";
634 } break;
635 case dwarf::DW_TAG_packed_type: {
636 SyntheticName += "{Z}";
637 } break;
638 case dwarf::DW_TAG_subprogram: {
639 SyntheticName += "{a}";
640 } break;
641 case dwarf::DW_TAG_thrown_type: {
642 SyntheticName += "{b}";
643 } break;
644 case dwarf::DW_TAG_variant_part: {
645 SyntheticName += "{c}";
646 } break;
647 case dwarf::DW_TAG_variable: {
648 SyntheticName += "{d}";
649 } break;
650 case dwarf::DW_TAG_volatile_type: {
651 SyntheticName += "{e}";
652 } break;
653 case dwarf::DW_TAG_dwarf_procedure: {
654 SyntheticName += "{f}";
655 } break;
656 case dwarf::DW_TAG_restrict_type: {
657 SyntheticName += "{g}";
658 } break;
659 case dwarf::DW_TAG_interface_type: {
660 SyntheticName += "{h}";
661 } break;
662 case dwarf::DW_TAG_imported_module: {
663 SyntheticName += "{i}";
664 } break;
665 case dwarf::DW_TAG_unspecified_type: {
666 SyntheticName += "{j}";
667 } break;
668 case dwarf::DW_TAG_imported_unit: {
669 SyntheticName += "{k}";
670 } break;
671 case dwarf::DW_TAG_condition: {
672 SyntheticName += "{l}";
673 } break;
674 case dwarf::DW_TAG_shared_type: {
675 SyntheticName += "{m}";
676 } break;
677 case dwarf::DW_TAG_rvalue_reference_type: {
678 SyntheticName += "{n}";
679 } break;
680 case dwarf::DW_TAG_template_alias: {
681 SyntheticName += "{o}";
682 } break;
683 case dwarf::DW_TAG_coarray_type: {
684 SyntheticName += "{p}";
685 } break;
686 case dwarf::DW_TAG_generic_subrange: {
687 SyntheticName += "{q}";
688 } break;
689 case dwarf::DW_TAG_dynamic_type: {
690 SyntheticName += "{r}";
691 } break;
692 case dwarf::DW_TAG_atomic_type: {
693 SyntheticName += "{s}";
694 } break;
695 case dwarf::DW_TAG_call_site: {
696 SyntheticName += "{t}";
697 } break;
698 case dwarf::DW_TAG_call_site_parameter: {
699 SyntheticName += "{u}";
700 } break;
701 case dwarf::DW_TAG_immutable_type: {
702 SyntheticName += "{v}";
703 } break;
704 case dwarf::DW_TAG_entry_point: {
705 SyntheticName += "{w}";
706 } break;
707 case dwarf::DW_TAG_label: {
708 SyntheticName += "{x}";
709 } break;
710 case dwarf::DW_TAG_lexical_block: {
711 SyntheticName += "{y}";
712 } break;
713 case dwarf::DW_TAG_common_block: {
714 SyntheticName += "{z}";
715 } break;
716 case dwarf::DW_TAG_common_inclusion: {
717 SyntheticName += "{|}";
718 } break;
719 case dwarf::DW_TAG_try_block: {
720 SyntheticName += "{~}";
721 } break;
722
723 case dwarf::DW_TAG_null: {
724 llvm_unreachable("No type prefix for DW_TAG_null");
725 } break;
726 case dwarf::DW_TAG_compile_unit: {
727 llvm_unreachable("No type prefix for DW_TAG_compile_unit");
728 } break;
729 case dwarf::DW_TAG_partial_unit: {
730 llvm_unreachable("No type prefix for DW_TAG_partial_unit");
731 } break;
732 case dwarf::DW_TAG_type_unit: {
733 llvm_unreachable("No type prefix for DW_TAG_type_unit");
734 } break;
735 case dwarf::DW_TAG_skeleton_unit: {
736 llvm_unreachable("No type prefix for DW_TAG_skeleton_unit");
737 } break;
738
739 default: {
740 SyntheticName += "{~~";
741 SyntheticName += utohexstr(X: DieEntry->getTag());
742 SyntheticName += "}";
743 } break;
744 }
745}
746
747OrderedChildrenIndexAssigner::OrderedChildrenIndexAssigner(
748 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
749 switch (DieEntry->getTag()) {
750 case dwarf::DW_TAG_array_type:
751 case dwarf::DW_TAG_coarray_type:
752 case dwarf::DW_TAG_class_type:
753 case dwarf::DW_TAG_common_block:
754 case dwarf::DW_TAG_lexical_block:
755 case dwarf::DW_TAG_structure_type:
756 case dwarf::DW_TAG_subprogram:
757 case dwarf::DW_TAG_subroutine_type:
758 case dwarf::DW_TAG_union_type:
759 case dwarf::DW_TAG_GNU_template_template_param:
760 case dwarf::DW_TAG_GNU_formal_parameter_pack:
761 case dwarf::DW_TAG_GNU_template_parameter_pack: {
762 NeedCountChildren = true;
763 } break;
764 case dwarf::DW_TAG_enumeration_type: {
765 // TODO : do we need to add condition
766 NeedCountChildren = true;
767 } break;
768 default: {
769 // Nothing to do.
770 }
771 }
772
773 // Calculate maximal index value
774 if (NeedCountChildren) {
775 for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(Die: DieEntry);
776 CurChild && CurChild->getAbbreviationDeclarationPtr();
777 CurChild = CU.getSiblingEntry(Die: CurChild)) {
778 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, DieEntry: CurChild);
779 if (!ArrayIndex)
780 continue;
781
782 assert((*ArrayIndex < ChildIndexesWidth.size()) &&
783 "Wrong index for ChildIndexesWidth");
784 ChildIndexesWidth[*ArrayIndex]++;
785 }
786
787 // Calculate index field width(number of digits in hexadecimal
788 // representation).
789 for (size_t &Width : ChildIndexesWidth) {
790 size_t digitsCounter = 1;
791 size_t NumToCompare = 15;
792
793 while (NumToCompare < Width) {
794 NumToCompare <<= 4;
795 digitsCounter++;
796 }
797
798 Width = digitsCounter;
799 }
800 }
801}
802
803std::optional<size_t> OrderedChildrenIndexAssigner::tagToArrayIndex(
804 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
805 if (!NeedCountChildren)
806 return std::nullopt;
807
808 switch (DieEntry->getTag()) {
809 case dwarf::DW_TAG_unspecified_parameters:
810 case dwarf::DW_TAG_formal_parameter:
811 return 0;
812 case dwarf::DW_TAG_template_value_parameter:
813 case dwarf::DW_TAG_template_type_parameter:
814 case dwarf::DW_TAG_GNU_template_template_param:
815 return 1;
816 case dwarf::DW_TAG_enumeration_type:
817 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) {
818 if (*ParentIdx && CU.getDebugInfoEntry(Index: *ParentIdx)->getTag() ==
819 dwarf::DW_TAG_array_type)
820 return 2;
821 }
822 return std::nullopt;
823 case dwarf::DW_TAG_subrange_type:
824 return 3;
825 case dwarf::DW_TAG_generic_subrange:
826 return 4;
827 case dwarf::DW_TAG_enumerator:
828 return 5;
829 case dwarf::DW_TAG_namelist_item:
830 return 6;
831 case dwarf::DW_TAG_member:
832 // Treat a static data member the same way regardless of whether it's
833 // described as a DW_TAG_member or a DW_TAG_variable.
834 if (isStaticDataMember(Die: DWARFDie(&CU.getOrigUnit(), DieEntry)))
835 return std::nullopt;
836 return 7;
837 default:
838 return std::nullopt;
839 };
840}
841
842std::optional<std::pair<size_t, size_t>>
843OrderedChildrenIndexAssigner::getChildIndex(
844 CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
845 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, DieEntry: ChildDieEntry);
846 if (!ArrayIndex)
847 return std::nullopt;
848
849 assert((*ArrayIndex < OrderedChildIdxs.size()) &&
850 "Wrong index for ChildIndexesWidth");
851 assert(ChildIndexesWidth[*ArrayIndex] < 16 &&
852 "Index width exceeds 16 digits.");
853
854 std::pair<size_t, size_t> Result = std::make_pair(
855 x&: OrderedChildIdxs[*ArrayIndex], y&: ChildIndexesWidth[*ArrayIndex]);
856 OrderedChildIdxs[*ArrayIndex]++;
857 return Result;
858}
859