xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
14 using namespace llvm;
15 using namespace dwarf_linker;
16 using namespace dwarf_linker::parallel;
17 
assignName(UnitEntryPairTy InputUnitEntryPair,std::optional<std::pair<size_t,size_t>> ChildIndex)18 Error 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(InputUnitEntryPair.DieEntry);
23   assert(Info.needToPlaceInTypeTable() &&
24          "Cann't assign name for non-type DIE");
25 
26   if (InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry) !=
27       nullptr)
28     return Error::success();
29 
30   SyntheticName.resize(0);
31   RecursionDepth = 0;
32   return addDIETypeName(InputUnitEntryPair, ChildIndex, true);
33 }
34 
addArrayDimension(UnitEntryPairTy InputUnitEntryPair)35 void SyntheticTypeNameBuilder::addArrayDimension(
36     UnitEntryPairTy InputUnitEntryPair) {
37   for (const DWARFDebugInfoEntry *CurChild =
38            InputUnitEntryPair.CU->getFirstChildEntry(
39                InputUnitEntryPair.DieEntry);
40        CurChild && CurChild->getAbbreviationDeclarationPtr();
41        CurChild = InputUnitEntryPair.CU->getSiblingEntry(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(CurChild, dwarf::DW_AT_count)) {
47         if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
48           SyntheticName += std::to_string(*ConstVal);
49         } else if (std::optional<int64_t> ConstVal =
50                        Val->getAsSignedConstant()) {
51           SyntheticName += std::to_string(*ConstVal);
52         }
53       }
54 
55       SyntheticName += "]";
56     }
57   }
58 }
59 
60 static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type};
addSignature(UnitEntryPairTy InputUnitEntryPair,bool addTemplateParameters)61 Error SyntheticTypeNameBuilder::addSignature(UnitEntryPairTy InputUnitEntryPair,
62                                              bool addTemplateParameters) {
63   // Add entry type.
64   if (Error Err = addReferencedODRDies(InputUnitEntryPair, false, 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                InputUnitEntryPair.DieEntry);
73        CurChild && CurChild->getAbbreviationDeclarationPtr();
74        CurChild = InputUnitEntryPair.CU->getSiblingEntry(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(CurChild);
80     else if (ChildTag == dwarf::DW_TAG_formal_parameter ||
81              ChildTag == dwarf::DW_TAG_unspecified_parameters)
82       FunctionParameters.push_back(CurChild);
83     else if (addTemplateParameters &&
84              ChildTag == dwarf::DW_TAG_GNU_template_parameter_pack) {
85       for (const DWARFDebugInfoEntry *CurGNUChild =
86                InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
87            CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
88            CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
89         TemplateParameters.push_back(CurGNUChild);
90     } else if (ChildTag == dwarf::DW_TAG_GNU_formal_parameter_pack) {
91       for (const DWARFDebugInfoEntry *CurGNUChild =
92                InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
93            CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
94            CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
95         FunctionParameters.push_back(CurGNUChild);
96     }
97   }
98 
99   // Add parameters.
100   if (Error Err = addParamNames(*InputUnitEntryPair.CU, FunctionParameters))
101     return Err;
102 
103   // Add template parameters.
104   if (Error Err =
105           addTemplateParamNames(*InputUnitEntryPair.CU, TemplateParameters))
106     return Err;
107 
108   return Error::success();
109 }
110 
addParamNames(CompileUnit & CU,SmallVector<const DWARFDebugInfoEntry *,20> & FunctionParameters)111 Error 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(CU.find(FunctionParameter, dwarf::DW_AT_artificial),
119                           0))
120       SyntheticName += "^";
121     if (Error Err = addReferencedODRDies(
122             UnitEntryPairTy{&CU, FunctionParameter}, false, TypeAttr))
123       return Err;
124   }
125   SyntheticName += ')';
126   return Error::success();
127 }
128 
addTemplateParamNames(CompileUnit & CU,SmallVector<const DWARFDebugInfoEntry *,10> & TemplateParameters)129 Error 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(Parameter, dwarf::DW_AT_const_value)) {
141           if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant())
142             SyntheticName += std::to_string(*ConstVal);
143           else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant())
144             SyntheticName += std::to_string(*ConstVal);
145         }
146       }
147 
148       if (Error Err = addReferencedODRDies(UnitEntryPairTy{&CU, Parameter},
149                                            false, TypeAttr))
150         return Err;
151     }
152     SyntheticName += '>';
153   }
154   return Error::success();
155 }
156 
addOrderedName(std::pair<size_t,size_t> ChildIdx)157 void 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(ChildIdx.first, 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.
167 static std::optional<UnitEntryPairTy>
getTypeDeduplicationCandidate(UnitEntryPairTy UnitEntryPair)168 getTypeDeduplicationCandidate(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(UnitEntryPair.DieEntry, dwarf::DW_AT_extension))
180       UnitEntryPair = UnitEntryPair.getNamespaceOrigin();
181 
182     // Content of anonimous namespaces should not be deduplicated.
183     if (!UnitEntryPair.CU->find(UnitEntryPair.DieEntry, 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 
addParentName(UnitEntryPairTy & InputUnitEntryPair)193 Error SyntheticTypeNameBuilder::addParentName(
194     UnitEntryPairTy &InputUnitEntryPair) {
195   std::optional<UnitEntryPairTy> UnitEntryPair = InputUnitEntryPair.getParent();
196   if (!UnitEntryPair)
197     return Error::success();
198 
199   UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
200   if (!UnitEntryPair)
201     return Error::success();
202 
203   if (TypeEntry *ImmediateParentName =
204           UnitEntryPair->CU->getDieTypeEntry(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(*UnitEntryPair);
214 
215     UnitEntryPair = UnitEntryPair->getParent();
216     if (!UnitEntryPair)
217       break;
218 
219     UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
220     if (!UnitEntryPair)
221       break;
222 
223   } while (!UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry));
224 
225   // Assign name for each parent entry.
226   size_t NameStart = SyntheticName.size();
227   for (UnitEntryPairTy Parent : reverse(Parents)) {
228     SyntheticName.resize(NameStart);
229     if (Error Err = addDIETypeName(Parent, std::nullopt, true))
230       return Err;
231   }
232 
233   // Add parents delimiter.
234   SyntheticName += ".";
235   return Error::success();
236 }
237 
addDieNameFromDeclFileAndDeclLine(UnitEntryPairTy & InputUnitEntryPair,bool & HasDeclFileName)238 void SyntheticTypeNameBuilder::addDieNameFromDeclFileAndDeclLine(
239     UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName) {
240   if (std::optional<DWARFFormValue> DeclFileVal = InputUnitEntryPair.CU->find(
241           InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_file)) {
242     if (std::optional<DWARFFormValue> DeclLineVal = InputUnitEntryPair.CU->find(
243             InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_line)) {
244       if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
245               InputUnitEntryPair.CU->getDirAndFilenameFromLineTable(
246                   *DeclFileVal)) {
247         SyntheticName += DirAndFilename->first;
248         SyntheticName += DirAndFilename->second;
249 
250         if (std::optional<uint64_t> DeclLineIntVal =
251                 dwarf::toUnsigned(*DeclLineVal)) {
252           SyntheticName += " ";
253           SyntheticName += utohexstr(*DeclLineIntVal);
254         }
255 
256         HasDeclFileName = true;
257       }
258     }
259   }
260 }
261 
addValueName(UnitEntryPairTy InputUnitEntryPair,dwarf::Attribute Attr)262 void SyntheticTypeNameBuilder::addValueName(UnitEntryPairTy InputUnitEntryPair,
263                                             dwarf::Attribute Attr) {
264   if (std::optional<DWARFFormValue> Val =
265           InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
266     if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
267       SyntheticName += " ";
268       SyntheticName += std::to_string(*ConstVal);
269     } else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant()) {
270       SyntheticName += " ";
271       SyntheticName += std::to_string(*ConstVal);
272     }
273   }
274 }
275 
addReferencedODRDies(UnitEntryPairTy InputUnitEntryPair,bool AssignNameToTypeDescriptor,ArrayRef<dwarf::Attribute> ODRAttrs)276 Error 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(InputUnitEntryPair.DieEntry, Attr)) {
283       std::optional<UnitEntryPairTy> RefDie =
284           InputUnitEntryPair.CU->resolveDIEReference(
285               *AttrValue, ResolveInterCUReferencesMode::Resolve);
286 
287       if (!RefDie)
288         continue;
289 
290       if (!RefDie->DieEntry)
291         return createStringError(std::errc::invalid_argument,
292                                  "Cann't resolve DIE reference");
293 
294       if (!FirstIteration)
295         SyntheticName += ",";
296 
297       RecursionDepth++;
298       if (RecursionDepth > 1000)
299         return createStringError(
300             std::errc::invalid_argument,
301             "Cann't parse input DWARF. Recursive dependence.");
302 
303       if (Error Err =
304               addDIETypeName(*RefDie, std::nullopt, AssignNameToTypeDescriptor))
305         return Err;
306       RecursionDepth--;
307       FirstIteration = false;
308     }
309   }
310 
311   return Error::success();
312 }
313 
addTypeName(UnitEntryPairTy InputUnitEntryPair,bool AddParentNames)314 Error 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           InputUnitEntryPair.DieEntry,
324           {dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_AT_linkage_name})) {
325     // Firstly check for linkage name.
326     SyntheticName += dwarf::toStringRef(Val);
327     HasLinkageName = true;
328   } else if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
329                  InputUnitEntryPair.DieEntry, dwarf::DW_AT_name)) {
330     // Then check for short name.
331     StringRef Name = dwarf::toStringRef(Val);
332     SyntheticName += Name;
333 
334     HasShortName = true;
335     HasTemplatesInShortName =
336         Name.ends_with(">") && Name.count("<") != 0 && !Name.ends_with("<=>");
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(InputUnitEntryPair.DieEntry,
351                                     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, !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, 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, 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(InputUnitEntryPair.DieEntry,
383                                     getODRAttributes()))
384       if (Error Err = addReferencedODRDies(InputUnitEntryPair, AddParentNames,
385                                            getODRAttributes()))
386         return Err;
387   }
388 
389   return Error::success();
390 }
391 
addDIETypeName(UnitEntryPairTy InputUnitEntryPair,std::optional<std::pair<size_t,size_t>> ChildIndex,bool AssignNameToTypeDescriptor)392 Error 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(InputUnitEntryPair);
398   if (!UnitEntryPair)
399     return Error::success();
400 
401   TypeEntry *TypeEntryPtr =
402       InputUnitEntryPair.CU->getDieTypeEntry(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(*UnitEntryPair))
408         return Err;
409     }
410     addTypePrefix(UnitEntryPair->DieEntry);
411 
412     if (ChildIndex) {
413       addOrderedName(*ChildIndex);
414     } else {
415       if (Error Err = addTypeName(*UnitEntryPair, AssignNameToTypeDescriptor))
416         return Err;
417     }
418 
419     if (AssignNameToTypeDescriptor) {
420       // Add built name to the DIE.
421       TypeEntryPtr = TypePoolRef.insert(SyntheticName.substr(NameStart));
422       InputUnitEntryPair.CU->setDieTypeEntry(InputUnitEntryPair.DieEntry,
423                                              TypeEntryPtr);
424     }
425   } else
426     SyntheticName += TypeEntryPtr->getKey();
427 
428   return Error::success();
429 }
430 
addTypePrefix(const DWARFDebugInfoEntry * DieEntry)431 void 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(DieEntry->getTag());
654     SyntheticName += "}";
655   } break;
656   }
657 }
658 
OrderedChildrenIndexAssigner(CompileUnit & CU,const DWARFDebugInfoEntry * DieEntry)659 OrderedChildrenIndexAssigner::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(DieEntry);
687          CurChild && CurChild->getAbbreviationDeclarationPtr();
688          CurChild = CU.getSiblingEntry(CurChild)) {
689       std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, 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 
tagToArrayIndex(CompileUnit & CU,const DWARFDebugInfoEntry * DieEntry)714 std::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(*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 
748 std::optional<std::pair<size_t, size_t>>
getChildIndex(CompileUnit & CU,const DWARFDebugInfoEntry * ChildDieEntry)749 OrderedChildrenIndexAssigner::getChildIndex(
750     CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
751   std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, 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       OrderedChildIdxs[*ArrayIndex], ChildIndexesWidth[*ArrayIndex]);
762   OrderedChildIdxs[*ArrayIndex]++;
763   return Result;
764 }
765