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