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