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