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