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 | |
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(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 | |
35 | void 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 | |
60 | static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type}; |
61 | Error 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 | |
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(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 | |
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(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 | |
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(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. |
167 | static std::optional<UnitEntryPairTy> |
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(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 | |
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: *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 | |
238 | void 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 | |
262 | void 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 | |
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(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 | |
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 | 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 | |
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(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 | |
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(X: DieEntry->getTag()); |
654 | SyntheticName += "}" ; |
655 | } break; |
656 | } |
657 | } |
658 | |
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(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 | |
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(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 | |
748 | std::optional<std::pair<size_t, size_t>> |
749 | OrderedChildrenIndexAssigner::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 | |