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 add referenced types to the name.
381 if (!HasLinkageName && !HasShortName && !HasDeclFileName) {
382 if (InputUnitEntryPair.CU->find(Die: InputUnitEntryPair.DieEntry,
383 Attrs: getODRAttributes()))
384 if (Error Err = addReferencedODRDies(InputUnitEntryPair, AssignNameToTypeDescriptor: AddParentNames,
385 ODRAttrs: getODRAttributes()))
386 return Err;
387 }
388
389 return Error::success();
390}
391
392Error SyntheticTypeNameBuilder::addDIETypeName(
393 UnitEntryPairTy InputUnitEntryPair,
394 std::optional<std::pair<size_t, size_t>> ChildIndex,
395 bool AssignNameToTypeDescriptor) {
396 std::optional<UnitEntryPairTy> UnitEntryPair =
397 getTypeDeduplicationCandidate(UnitEntryPair: InputUnitEntryPair);
398 if (!UnitEntryPair)
399 return Error::success();
400
401 TypeEntry *TypeEntryPtr =
402 InputUnitEntryPair.CU->getDieTypeEntry(InputDieEntry: InputUnitEntryPair.DieEntry);
403 // Check if DIE already has a name.
404 if (!TypeEntryPtr) {
405 size_t NameStart = SyntheticName.size();
406 if (AssignNameToTypeDescriptor) {
407 if (Error Err = addParentName(InputUnitEntryPair&: *UnitEntryPair))
408 return Err;
409 }
410 addTypePrefix(DieEntry: UnitEntryPair->DieEntry);
411
412 if (ChildIndex) {
413 addOrderedName(ChildIdx: *ChildIndex);
414 } else {
415 if (Error Err = addTypeName(InputUnitEntryPair: *UnitEntryPair, AddParentNames: AssignNameToTypeDescriptor))
416 return Err;
417 }
418
419 if (AssignNameToTypeDescriptor) {
420 // Add built name to the DIE.
421 TypeEntryPtr = TypePoolRef.insert(Name: SyntheticName.substr(Start: NameStart));
422 InputUnitEntryPair.CU->setDieTypeEntry(InputDieEntry: InputUnitEntryPair.DieEntry,
423 Entry: TypeEntryPtr);
424 }
425 } else
426 SyntheticName += TypeEntryPtr->getKey();
427
428 return Error::success();
429}
430
431void SyntheticTypeNameBuilder::addTypePrefix(
432 const DWARFDebugInfoEntry *DieEntry) {
433 switch (DieEntry->getTag()) {
434 case dwarf::DW_TAG_base_type: {
435 SyntheticName += "{0}";
436 } break;
437 case dwarf::DW_TAG_namespace: {
438 SyntheticName += "{1}";
439 } break;
440 case dwarf::DW_TAG_formal_parameter: {
441 SyntheticName += "{2}";
442 } break;
443 // dwarf::DW_TAG_unspecified_parameters have the same prefix as before.
444 case dwarf::DW_TAG_unspecified_parameters: {
445 SyntheticName += "{2}";
446 } break;
447 case dwarf::DW_TAG_template_type_parameter: {
448 SyntheticName += "{3}";
449 } break;
450 // dwarf::DW_TAG_template_value_parameter have the same prefix as before.
451 case dwarf::DW_TAG_template_value_parameter: {
452 SyntheticName += "{3}";
453 } break;
454 case dwarf::DW_TAG_GNU_formal_parameter_pack: {
455 SyntheticName += "{4}";
456 } break;
457 case dwarf::DW_TAG_GNU_template_parameter_pack: {
458 SyntheticName += "{5}";
459 } break;
460 case dwarf::DW_TAG_inheritance: {
461 SyntheticName += "{6}";
462 } break;
463 case dwarf::DW_TAG_array_type: {
464 SyntheticName += "{7}";
465 } break;
466 case dwarf::DW_TAG_class_type: {
467 SyntheticName += "{8}";
468 } break;
469 case dwarf::DW_TAG_enumeration_type: {
470 SyntheticName += "{9}";
471 } break;
472 case dwarf::DW_TAG_imported_declaration: {
473 SyntheticName += "{A}";
474 } break;
475 case dwarf::DW_TAG_member: {
476 SyntheticName += "{B}";
477 } break;
478 case dwarf::DW_TAG_pointer_type: {
479 SyntheticName += "{C}";
480 } break;
481 case dwarf::DW_TAG_reference_type: {
482 SyntheticName += "{D}";
483 } break;
484 case dwarf::DW_TAG_string_type: {
485 SyntheticName += "{E}";
486 } break;
487 case dwarf::DW_TAG_structure_type: {
488 SyntheticName += "{F}";
489 } break;
490 case dwarf::DW_TAG_subroutine_type: {
491 SyntheticName += "{G}";
492 } break;
493 case dwarf::DW_TAG_typedef: {
494 SyntheticName += "{H}";
495 } break;
496 case dwarf::DW_TAG_union_type: {
497 SyntheticName += "{I}";
498 } break;
499 case dwarf::DW_TAG_variant: {
500 SyntheticName += "{J}";
501 } break;
502 case dwarf::DW_TAG_inlined_subroutine: {
503 SyntheticName += "{K}";
504 } break;
505 case dwarf::DW_TAG_module: {
506 SyntheticName += "{L}";
507 } break;
508 case dwarf::DW_TAG_ptr_to_member_type: {
509 SyntheticName += "{M}";
510 } break;
511 case dwarf::DW_TAG_set_type: {
512 SyntheticName += "{N}";
513 } break;
514 case dwarf::DW_TAG_subrange_type: {
515 SyntheticName += "{O}";
516 } break;
517 case dwarf::DW_TAG_with_stmt: {
518 SyntheticName += "{P}";
519 } break;
520 case dwarf::DW_TAG_access_declaration: {
521 SyntheticName += "{Q}";
522 } break;
523 case dwarf::DW_TAG_catch_block: {
524 SyntheticName += "{R}";
525 } break;
526 case dwarf::DW_TAG_const_type: {
527 SyntheticName += "{S}";
528 } break;
529 case dwarf::DW_TAG_constant: {
530 SyntheticName += "{T}";
531 } break;
532 case dwarf::DW_TAG_enumerator: {
533 SyntheticName += "{U}";
534 } break;
535 case dwarf::DW_TAG_file_type: {
536 SyntheticName += "{V}";
537 } break;
538 case dwarf::DW_TAG_friend: {
539 SyntheticName += "{W}";
540 } break;
541 case dwarf::DW_TAG_namelist: {
542 SyntheticName += "{X}";
543 } break;
544 case dwarf::DW_TAG_namelist_item: {
545 SyntheticName += "{Y}";
546 } break;
547 case dwarf::DW_TAG_packed_type: {
548 SyntheticName += "{Z}";
549 } break;
550 case dwarf::DW_TAG_subprogram: {
551 SyntheticName += "{a}";
552 } break;
553 case dwarf::DW_TAG_thrown_type: {
554 SyntheticName += "{b}";
555 } break;
556 case dwarf::DW_TAG_variant_part: {
557 SyntheticName += "{c}";
558 } break;
559 case dwarf::DW_TAG_variable: {
560 SyntheticName += "{d}";
561 } break;
562 case dwarf::DW_TAG_volatile_type: {
563 SyntheticName += "{e}";
564 } break;
565 case dwarf::DW_TAG_dwarf_procedure: {
566 SyntheticName += "{f}";
567 } break;
568 case dwarf::DW_TAG_restrict_type: {
569 SyntheticName += "{g}";
570 } break;
571 case dwarf::DW_TAG_interface_type: {
572 SyntheticName += "{h}";
573 } break;
574 case dwarf::DW_TAG_imported_module: {
575 SyntheticName += "{i}";
576 } break;
577 case dwarf::DW_TAG_unspecified_type: {
578 SyntheticName += "{j}";
579 } break;
580 case dwarf::DW_TAG_imported_unit: {
581 SyntheticName += "{k}";
582 } break;
583 case dwarf::DW_TAG_condition: {
584 SyntheticName += "{l}";
585 } break;
586 case dwarf::DW_TAG_shared_type: {
587 SyntheticName += "{m}";
588 } break;
589 case dwarf::DW_TAG_rvalue_reference_type: {
590 SyntheticName += "{n}";
591 } break;
592 case dwarf::DW_TAG_template_alias: {
593 SyntheticName += "{o}";
594 } break;
595 case dwarf::DW_TAG_coarray_type: {
596 SyntheticName += "{p}";
597 } break;
598 case dwarf::DW_TAG_generic_subrange: {
599 SyntheticName += "{q}";
600 } break;
601 case dwarf::DW_TAG_dynamic_type: {
602 SyntheticName += "{r}";
603 } break;
604 case dwarf::DW_TAG_atomic_type: {
605 SyntheticName += "{s}";
606 } break;
607 case dwarf::DW_TAG_call_site: {
608 SyntheticName += "{t}";
609 } break;
610 case dwarf::DW_TAG_call_site_parameter: {
611 SyntheticName += "{u}";
612 } break;
613 case dwarf::DW_TAG_immutable_type: {
614 SyntheticName += "{v}";
615 } break;
616 case dwarf::DW_TAG_entry_point: {
617 SyntheticName += "{w}";
618 } break;
619 case dwarf::DW_TAG_label: {
620 SyntheticName += "{x}";
621 } break;
622 case dwarf::DW_TAG_lexical_block: {
623 SyntheticName += "{y}";
624 } break;
625 case dwarf::DW_TAG_common_block: {
626 SyntheticName += "{z}";
627 } break;
628 case dwarf::DW_TAG_common_inclusion: {
629 SyntheticName += "{|}";
630 } break;
631 case dwarf::DW_TAG_try_block: {
632 SyntheticName += "{~}";
633 } break;
634
635 case dwarf::DW_TAG_null: {
636 llvm_unreachable("No type prefix for DW_TAG_null");
637 } break;
638 case dwarf::DW_TAG_compile_unit: {
639 llvm_unreachable("No type prefix for DW_TAG_compile_unit");
640 } break;
641 case dwarf::DW_TAG_partial_unit: {
642 llvm_unreachable("No type prefix for DW_TAG_partial_unit");
643 } break;
644 case dwarf::DW_TAG_type_unit: {
645 llvm_unreachable("No type prefix for DW_TAG_type_unit");
646 } break;
647 case dwarf::DW_TAG_skeleton_unit: {
648 llvm_unreachable("No type prefix for DW_TAG_skeleton_unit");
649 } break;
650
651 default: {
652 SyntheticName += "{~~";
653 SyntheticName += utohexstr(X: DieEntry->getTag());
654 SyntheticName += "}";
655 } break;
656 }
657}
658
659OrderedChildrenIndexAssigner::OrderedChildrenIndexAssigner(
660 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
661 switch (DieEntry->getTag()) {
662 case dwarf::DW_TAG_array_type:
663 case dwarf::DW_TAG_coarray_type:
664 case dwarf::DW_TAG_class_type:
665 case dwarf::DW_TAG_common_block:
666 case dwarf::DW_TAG_lexical_block:
667 case dwarf::DW_TAG_structure_type:
668 case dwarf::DW_TAG_subprogram:
669 case dwarf::DW_TAG_subroutine_type:
670 case dwarf::DW_TAG_union_type:
671 case dwarf::DW_TAG_GNU_template_template_param:
672 case dwarf::DW_TAG_GNU_formal_parameter_pack: {
673 NeedCountChildren = true;
674 } break;
675 case dwarf::DW_TAG_enumeration_type: {
676 // TODO : do we need to add condition
677 NeedCountChildren = true;
678 } break;
679 default: {
680 // Nothing to do.
681 }
682 }
683
684 // Calculate maximal index value
685 if (NeedCountChildren) {
686 for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(Die: DieEntry);
687 CurChild && CurChild->getAbbreviationDeclarationPtr();
688 CurChild = CU.getSiblingEntry(Die: CurChild)) {
689 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, DieEntry: CurChild);
690 if (!ArrayIndex)
691 continue;
692
693 assert((*ArrayIndex < ChildIndexesWidth.size()) &&
694 "Wrong index for ChildIndexesWidth");
695 ChildIndexesWidth[*ArrayIndex]++;
696 }
697
698 // Calculate index field width(number of digits in hexadecimal
699 // representation).
700 for (size_t &Width : ChildIndexesWidth) {
701 size_t digitsCounter = 1;
702 size_t NumToCompare = 15;
703
704 while (NumToCompare < Width) {
705 NumToCompare <<= 4;
706 digitsCounter++;
707 }
708
709 Width = digitsCounter;
710 }
711 }
712}
713
714std::optional<size_t> OrderedChildrenIndexAssigner::tagToArrayIndex(
715 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
716 if (!NeedCountChildren)
717 return std::nullopt;
718
719 switch (DieEntry->getTag()) {
720 case dwarf::DW_TAG_unspecified_parameters:
721 case dwarf::DW_TAG_formal_parameter:
722 return 0;
723 case dwarf::DW_TAG_template_value_parameter:
724 case dwarf::DW_TAG_template_type_parameter:
725 return 1;
726 case dwarf::DW_TAG_enumeration_type:
727 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) {
728 if (*ParentIdx && CU.getDebugInfoEntry(Index: *ParentIdx)->getTag() ==
729 dwarf::DW_TAG_array_type)
730 return 2;
731 }
732 return std::nullopt;
733 case dwarf::DW_TAG_subrange_type:
734 return 3;
735 case dwarf::DW_TAG_generic_subrange:
736 return 4;
737 case dwarf::DW_TAG_enumerator:
738 return 5;
739 case dwarf::DW_TAG_namelist_item:
740 return 6;
741 case dwarf::DW_TAG_member:
742 return 7;
743 default:
744 return std::nullopt;
745 };
746}
747
748std::optional<std::pair<size_t, size_t>>
749OrderedChildrenIndexAssigner::getChildIndex(
750 CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
751 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, DieEntry: ChildDieEntry);
752 if (!ArrayIndex)
753 return std::nullopt;
754
755 assert((*ArrayIndex < OrderedChildIdxs.size()) &&
756 "Wrong index for ChildIndexesWidth");
757 assert(ChildIndexesWidth[*ArrayIndex] < 16 &&
758 "Index width exceeds 16 digits.");
759
760 std::pair<size_t, size_t> Result = std::make_pair(
761 x&: OrderedChildIdxs[*ArrayIndex], y&: ChildIndexesWidth[*ArrayIndex]);
762 OrderedChildIdxs[*ArrayIndex]++;
763 return Result;
764}
765