LLVM 24.0.0git
SyntheticTypeNameBuilder.cpp
Go to the documentation of this file.
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
15
16using namespace llvm;
17using namespace dwarf_linker;
18using namespace dwarf_linker::parallel;
19
21 UnitEntryPairTy InputUnitEntryPair,
22 std::optional<std::pair<size_t, size_t>> ChildIndex) {
23 [[maybe_unused]] const CompileUnit::DIEInfo &Info =
24 InputUnitEntryPair.CU->getDIEInfo(InputUnitEntryPair.DieEntry);
25 assert(Info.needToPlaceInTypeTable() &&
26 "Cann't assign name for non-type DIE");
27
28 if (InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry) !=
29 nullptr)
30 return Error::success();
31
32 SyntheticName.resize(0);
34 return addDIETypeName(InputUnitEntryPair, ChildIndex, true);
35}
36
38 UnitEntryPairTy InputUnitEntryPair) {
39 for (const DWARFDebugInfoEntry *CurChild =
40 InputUnitEntryPair.CU->getFirstChildEntry(
41 InputUnitEntryPair.DieEntry);
42 CurChild && CurChild->getAbbreviationDeclarationPtr();
43 CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
44 if (CurChild->getTag() == dwarf::DW_TAG_subrange_type ||
45 CurChild->getTag() == dwarf::DW_TAG_generic_subrange) {
46 SyntheticName += "[";
47 if (std::optional<DWARFFormValue> Val =
48 InputUnitEntryPair.CU->find(CurChild, dwarf::DW_AT_count)) {
49 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
50 SyntheticName += std::to_string(*ConstVal);
51 } else if (std::optional<int64_t> ConstVal =
52 Val->getAsSignedConstant()) {
53 SyntheticName += std::to_string(*ConstVal);
54 }
55 }
56
57 SyntheticName += "]";
58 }
59 }
60}
61
62static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type};
64 bool addTemplateParameters) {
65 // Add entry type.
66 if (Error Err = addReferencedODRDies(InputUnitEntryPair, false, TypeAttr))
67 return Err;
68 SyntheticName += ':';
69
72 for (const DWARFDebugInfoEntry *CurChild =
73 InputUnitEntryPair.CU->getFirstChildEntry(
74 InputUnitEntryPair.DieEntry);
75 CurChild && CurChild->getAbbreviationDeclarationPtr();
76 CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
77 dwarf::Tag ChildTag = CurChild->getTag();
78 if (addTemplateParameters &&
79 (ChildTag == dwarf::DW_TAG_template_type_parameter ||
80 ChildTag == dwarf::DW_TAG_template_value_parameter))
81 TemplateParameters.push_back(CurChild);
82 else if (ChildTag == dwarf::DW_TAG_formal_parameter ||
83 ChildTag == dwarf::DW_TAG_unspecified_parameters)
84 FunctionParameters.push_back(CurChild);
85 else if (addTemplateParameters &&
86 ChildTag == dwarf::DW_TAG_GNU_template_parameter_pack) {
87 for (const DWARFDebugInfoEntry *CurGNUChild =
88 InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
89 CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
90 CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
91 TemplateParameters.push_back(CurGNUChild);
92 } else if (ChildTag == dwarf::DW_TAG_GNU_formal_parameter_pack) {
93 for (const DWARFDebugInfoEntry *CurGNUChild =
94 InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
95 CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
96 CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
97 FunctionParameters.push_back(CurGNUChild);
98 }
99 }
100
101 // Add parameters.
102 if (Error Err = addParamNames(*InputUnitEntryPair.CU, FunctionParameters))
103 return Err;
104
105 // Add template parameters.
106 if (Error Err =
107 addTemplateParamNames(*InputUnitEntryPair.CU, TemplateParameters))
108 return Err;
109
110 return Error::success();
111}
112
116 SyntheticName += '(';
117 for (const DWARFDebugInfoEntry *FunctionParameter : FunctionParameters) {
118 if (SyntheticName.back() != '(')
119 SyntheticName += ", ";
120 if (dwarf::toUnsigned(CU.find(FunctionParameter, dwarf::DW_AT_artificial),
121 0))
122 SyntheticName += "^";
123 if (Error Err = addReferencedODRDies(
124 UnitEntryPairTy{&CU, FunctionParameter}, false, TypeAttr))
125 return Err;
126 }
127 SyntheticName += ')';
128 return Error::success();
129}
130
134 if (!TemplateParameters.empty()) {
135 SyntheticName += '<';
136 for (const DWARFDebugInfoEntry *Parameter : TemplateParameters) {
137 if (SyntheticName.back() != '<')
138 SyntheticName += ", ";
139
140 if (Parameter->getTag() == dwarf::DW_TAG_template_value_parameter) {
141 if (std::optional<DWARFFormValue> Val =
142 CU.find(Parameter, dwarf::DW_AT_const_value)) {
143 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant())
144 SyntheticName += std::to_string(*ConstVal);
145 else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant())
146 SyntheticName += std::to_string(*ConstVal);
147 }
148 }
149
150 if (Error Err = addReferencedODRDies(UnitEntryPairTy{&CU, Parameter},
151 false, TypeAttr))
152 return Err;
153 }
154 SyntheticName += '>';
155 }
156 return Error::success();
157}
158
160 std::pair<size_t, size_t> ChildIdx) {
161 std::string Name;
162 llvm::raw_string_ostream stream(Name);
163 stream << format_hex_no_prefix(ChildIdx.first, ChildIdx.second);
164 SyntheticName += Name;
165}
166
167// Examine DIE and return type deduplication candidate: some DIEs could not be
168// deduplicated, namespace may refer to another namespace.
169static std::optional<UnitEntryPairTy>
171 switch (UnitEntryPair.DieEntry->getTag()) {
172 case dwarf::DW_TAG_null:
173 case dwarf::DW_TAG_compile_unit:
174 case dwarf::DW_TAG_partial_unit:
175 case dwarf::DW_TAG_type_unit:
176 case dwarf::DW_TAG_skeleton_unit: {
177 return std::nullopt;
178 }
179 case dwarf::DW_TAG_namespace: {
180 // Check if current namespace refers another.
181 if (UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_extension))
182 UnitEntryPair = UnitEntryPair.getNamespaceOrigin();
183
184 // Content of anonimous namespaces should not be deduplicated.
185 if (!UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_name))
186 llvm_unreachable("Cann't deduplicate anonimous namespace");
187
188 return UnitEntryPair;
189 }
190 default:
191 return UnitEntryPair;
192 }
193}
194
196 UnitEntryPairTy &InputUnitEntryPair) {
197 std::optional<UnitEntryPairTy> UnitEntryPair = InputUnitEntryPair.getParent();
198 if (!UnitEntryPair)
199 return Error::success();
200
201 UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
202 if (!UnitEntryPair)
203 return Error::success();
204
205 if (TypeEntry *ImmediateParentName =
206 UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry)) {
207 SyntheticName += ImmediateParentName->getKey();
208 SyntheticName += ".";
209 return Error::success();
210 }
211
212 // Collect parent entries.
214 do {
215 Parents.push_back(*UnitEntryPair);
216
217 UnitEntryPair = UnitEntryPair->getParent();
218 if (!UnitEntryPair)
219 break;
220
221 UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
222 if (!UnitEntryPair)
223 break;
224
225 } while (!UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry));
226
227 // Assign name for each parent entry.
228 size_t NameStart = SyntheticName.size();
229 for (UnitEntryPairTy Parent : reverse(Parents)) {
230 SyntheticName.resize(NameStart);
231 if (Error Err = addDIETypeName(Parent, std::nullopt, true))
232 return Err;
233 }
234
235 // Add parents delimiter.
236 SyntheticName += ".";
237 return Error::success();
238}
239
241 UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName) {
242 if (std::optional<DWARFFormValue> DeclFileVal = InputUnitEntryPair.CU->find(
243 InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_file)) {
244 if (std::optional<DWARFFormValue> DeclLineVal = InputUnitEntryPair.CU->find(
245 InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_line)) {
246 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
247 InputUnitEntryPair.CU->getDirAndFilenameFromLineTable(
248 *DeclFileVal)) {
249 SyntheticName += DirAndFilename->first;
250 SyntheticName += DirAndFilename->second;
251
252 if (std::optional<uint64_t> DeclLineIntVal =
253 dwarf::toUnsigned(*DeclLineVal)) {
254 SyntheticName += " ";
255 SyntheticName += utohexstr(*DeclLineIntVal);
256 }
257
258 HasDeclFileName = true;
259 }
260 }
261 }
262}
263
265 dwarf::Attribute Attr) {
266 if (std::optional<DWARFFormValue> Val =
267 InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
268 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
269 SyntheticName += " ";
270 SyntheticName += std::to_string(*ConstVal);
271 } else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant()) {
272 SyntheticName += " ";
273 SyntheticName += std::to_string(*ConstVal);
274 }
275 }
276}
277
280 dwarf::Attribute Attr) {
281 std::optional<DWARFFormValue> AttrValue =
282 InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr);
283 if (!AttrValue)
284 return std::nullopt;
285
286 std::optional<UnitEntryPairTy> RefDie =
287 InputUnitEntryPair.CU->resolveDIEReference(
289 if (RefDie && !RefDie->DieEntry)
290 return createStringError(std::errc::invalid_argument,
291 "cannot resolve DIE reference");
292 return RefDie;
293}
294
297 return createStringError(std::errc::invalid_argument,
298 "cannot parse input DWARF: recursive dependence");
299 return Error::success();
300}
301
303 UnitEntryPairTy InputUnitEntryPair, bool AssignNameToTypeDescriptor,
305 bool FirstIteration = true;
306 for (dwarf::Attribute Attr : ODRAttrs) {
308 resolveReference(InputUnitEntryPair, Attr);
309 if (!RefDie)
310 return RefDie.takeError();
311 if (!*RefDie)
312 continue;
313
314 if (!FirstIteration)
315 SyntheticName += ",";
316
317 if (Error Err = incrementRecursionDepth())
318 return Err;
319 if (Error Err =
320 addDIETypeName(**RefDie, std::nullopt, AssignNameToTypeDescriptor))
321 return Err;
323 FirstIteration = false;
324 }
325
326 return Error::success();
327}
328
330 bool AddParentNames) {
331 bool HasLinkageName = false;
332 bool HasShortName = false;
333 bool HasTemplatesInShortName = false;
334 bool HasDeclFileName = false;
335
336 // Try to get name from the DIE.
337 if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
338 InputUnitEntryPair.DieEntry,
339 {dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_AT_linkage_name})) {
340 // Firstly check for linkage name.
342 HasLinkageName = true;
343 } else if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
344 InputUnitEntryPair.DieEntry, dwarf::DW_AT_name)) {
345 // Then check for short name.
346 StringRef Name = dwarf::toStringRef(Val);
347 SyntheticName += Name;
348
349 HasShortName = true;
350 HasTemplatesInShortName =
351 Name.ends_with(">") && Name.count("<") != 0 && !Name.ends_with("<=>");
352 } else {
353 // Finally check for declaration attributes.
354 addDieNameFromDeclFileAndDeclLine(InputUnitEntryPair, HasDeclFileName);
355
356 // Unnamed types declared on one line differ only in their contents.
357 if (HasDeclFileName)
358 if (Error Err = addUnnamedTypeContents(InputUnitEntryPair))
359 return Err;
360 }
361
362 // Add additional name parts for some DIEs.
363 switch (InputUnitEntryPair.DieEntry->getTag()) {
364 case dwarf::DW_TAG_union_type:
365 case dwarf::DW_TAG_interface_type:
366 case dwarf::DW_TAG_class_type:
367 case dwarf::DW_TAG_structure_type:
368 case dwarf::DW_TAG_subroutine_type:
369 case dwarf::DW_TAG_subprogram: {
370 if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
371 dwarf::DW_AT_artificial))
372 SyntheticName += "^";
373
374 // No need to add signature information for linkage name,
375 // also no need to add template parameters name if short name already
376 // includes them.
377 if (!HasLinkageName)
378 if (Error Err =
379 addSignature(InputUnitEntryPair, !HasTemplatesInShortName))
380 return Err;
381 } break;
382 case dwarf::DW_TAG_coarray_type:
383 case dwarf::DW_TAG_array_type: {
384 addArrayDimension(InputUnitEntryPair);
385 } break;
386 case dwarf::DW_TAG_subrange_type: {
387 addValueName(InputUnitEntryPair, dwarf::DW_AT_count);
388 } break;
389 case dwarf::DW_TAG_template_value_parameter: {
390 if (!HasTemplatesInShortName) {
391 // TODO add support for DW_AT_location
392 addValueName(InputUnitEntryPair, dwarf::DW_AT_const_value);
393 }
394 } break;
395 default: {
396 // Nothing to do.
397 } break;
398 }
399
400 // If name for the DIE is not determined yet or if the DIE is a typedef, add
401 // referenced types to the name.
402 if ((!HasLinkageName && !HasShortName && !HasDeclFileName) ||
403 InputUnitEntryPair.DieEntry->getTag() == dwarf::DW_TAG_typedef) {
404 if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
406 if (Error Err = addReferencedODRDies(InputUnitEntryPair, AddParentNames,
408 return Err;
409 }
410
411 return Error::success();
412}
413
415 UnitEntryPairTy InputUnitEntryPair,
416 std::optional<std::pair<size_t, size_t>> ChildIndex,
417 bool AssignNameToTypeDescriptor) {
418 std::optional<UnitEntryPairTy> UnitEntryPair =
419 getTypeDeduplicationCandidate(InputUnitEntryPair);
420 if (!UnitEntryPair)
421 return Error::success();
422
423 TypeEntry *TypeEntryPtr =
424 InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry);
425 // Check if DIE already has a name.
426 if (!TypeEntryPtr) {
427 size_t NameStart = SyntheticName.size();
428 // Prepend the parent scope so this name matches the key the type is
429 // stored under in the pool (the getKey() branch below). Otherwise the
430 // same type gets different names depending on whether it already has a
431 // pool entry, which races under parallel assignment and breaks
432 // deterministic deduplication.
433 if (Error Err = addParentName(*UnitEntryPair))
434 return Err;
435 addTypePrefix(*UnitEntryPair->CU, UnitEntryPair->DieEntry);
436
437 if (ChildIndex) {
438 addOrderedName(*ChildIndex);
439 } else {
440 if (Error Err = addTypeName(*UnitEntryPair, AssignNameToTypeDescriptor))
441 return Err;
442 }
443
444 if (AssignNameToTypeDescriptor) {
445 // Add built name to the DIE.
446 TypeEntryPtr = TypePoolRef.insert(SyntheticName.substr(NameStart));
447 InputUnitEntryPair.CU->setDieTypeEntry(InputUnitEntryPair.DieEntry,
448 TypeEntryPtr);
449 }
450 } else
451 SyntheticName += TypeEntryPtr->getKey();
452
453 return Error::success();
454}
455
457 UnitEntryPairTy InputUnitEntryPair) {
458 if (!isIdentifiedByChildren(InputUnitEntryPair.DieEntry->getTag()))
459 return Error::success();
460
461 CompileUnit &CU = *InputUnitEntryPair.CU;
462 SyntheticName += '(';
463 for (const DWARFDebugInfoEntry *CurChild =
464 CU.getFirstChildEntry(InputUnitEntryPair.DieEntry);
465 CurChild && CurChild->getAbbreviationDeclarationPtr();
466 CurChild = CU.getSiblingEntry(CurChild)) {
467 if (!isIdentifyingChild(DWARFDie(&CU.getOrigUnit(), CurChild)))
468 continue;
469
470 if (SyntheticName.back() != '(')
471 SyntheticName += ", ";
472 addTypePrefix(CU, CurChild);
473 if (std::optional<DWARFFormValue> Val =
474 CU.find(CurChild, dwarf::DW_AT_name))
476 if (Error Err = addUnqualifiedTypeName(UnitEntryPairTy{&CU, CurChild}))
477 return Err;
478 }
479 SyntheticName += ')';
480 return Error::success();
481}
482
484 UnitEntryPairTy InputUnitEntryPair) {
486 resolveReference(InputUnitEntryPair, dwarf::DW_AT_type);
487 if (!RefDie)
488 return RefDie.takeError();
489 if (!*RefDie)
490 return Error::success();
491
492 if (Error Err = incrementRecursionDepth())
493 return Err;
494
495 UnitEntryPairTy Type = **RefDie;
496 SyntheticName += ':';
497 addTypePrefix(*Type.CU, Type.DieEntry);
498 if (std::optional<DWARFFormValue> Val =
499 Type.CU->find(Type.DieEntry, dwarf::DW_AT_name)) {
501 } else {
502 if (Type.DieEntry->getTag() == dwarf::DW_TAG_array_type)
505 return Err;
507 return Err;
508 }
509
511 return Error::success();
512}
513
515 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
516 switch (DieEntry->getTag()) {
517 case dwarf::DW_TAG_base_type: {
518 SyntheticName += "{0}";
519 } break;
520 case dwarf::DW_TAG_namespace: {
521 SyntheticName += "{1}";
522 } break;
523 case dwarf::DW_TAG_formal_parameter: {
524 SyntheticName += "{2}";
525 } break;
526 // dwarf::DW_TAG_unspecified_parameters have the same prefix as before.
527 case dwarf::DW_TAG_unspecified_parameters: {
528 SyntheticName += "{2}";
529 } break;
530 case dwarf::DW_TAG_template_type_parameter: {
531 SyntheticName += "{3}";
532 } break;
533 // dwarf::DW_TAG_template_value_parameter have the same prefix as before.
534 case dwarf::DW_TAG_template_value_parameter: {
535 SyntheticName += "{3}";
536 } break;
537 case dwarf::DW_TAG_GNU_formal_parameter_pack: {
538 SyntheticName += "{4}";
539 } break;
540 case dwarf::DW_TAG_GNU_template_parameter_pack: {
541 SyntheticName += "{5}";
542 } break;
543 case dwarf::DW_TAG_inheritance: {
544 SyntheticName += "{6}";
545 } break;
546 case dwarf::DW_TAG_array_type: {
547 SyntheticName += "{7}";
548 } break;
549 case dwarf::DW_TAG_class_type: {
550 SyntheticName += "{8}";
551 } break;
552 case dwarf::DW_TAG_enumeration_type: {
553 SyntheticName += "{9}";
554 } break;
555 case dwarf::DW_TAG_imported_declaration: {
556 SyntheticName += "{A}";
557 } break;
558 case dwarf::DW_TAG_member: {
559 // Treat a static data member the same way regardless of whether it's
560 // described as a DW_TAG_member or a DW_TAG_variable.
561 if (isStaticDataMember(DWARFDie(&CU.getOrigUnit(), DieEntry)))
562 SyntheticName += "{d}";
563 else
564 SyntheticName += "{B}";
565 } break;
566 case dwarf::DW_TAG_pointer_type: {
567 SyntheticName += "{C}";
568 } break;
569 case dwarf::DW_TAG_reference_type: {
570 SyntheticName += "{D}";
571 } break;
572 case dwarf::DW_TAG_string_type: {
573 SyntheticName += "{E}";
574 } break;
575 case dwarf::DW_TAG_structure_type: {
576 SyntheticName += "{F}";
577 } break;
578 case dwarf::DW_TAG_subroutine_type: {
579 SyntheticName += "{G}";
580 } break;
581 case dwarf::DW_TAG_typedef: {
582 SyntheticName += "{H}";
583 } break;
584 case dwarf::DW_TAG_union_type: {
585 SyntheticName += "{I}";
586 } break;
587 case dwarf::DW_TAG_variant: {
588 SyntheticName += "{J}";
589 } break;
590 case dwarf::DW_TAG_inlined_subroutine: {
591 SyntheticName += "{K}";
592 } break;
593 case dwarf::DW_TAG_module: {
594 SyntheticName += "{L}";
595 } break;
596 case dwarf::DW_TAG_ptr_to_member_type: {
597 SyntheticName += "{M}";
598 } break;
599 case dwarf::DW_TAG_set_type: {
600 SyntheticName += "{N}";
601 } break;
602 case dwarf::DW_TAG_subrange_type: {
603 SyntheticName += "{O}";
604 } break;
605 case dwarf::DW_TAG_with_stmt: {
606 SyntheticName += "{P}";
607 } break;
608 case dwarf::DW_TAG_access_declaration: {
609 SyntheticName += "{Q}";
610 } break;
611 case dwarf::DW_TAG_catch_block: {
612 SyntheticName += "{R}";
613 } break;
614 case dwarf::DW_TAG_const_type: {
615 SyntheticName += "{S}";
616 } break;
617 case dwarf::DW_TAG_constant: {
618 SyntheticName += "{T}";
619 } break;
620 case dwarf::DW_TAG_enumerator: {
621 SyntheticName += "{U}";
622 } break;
623 case dwarf::DW_TAG_file_type: {
624 SyntheticName += "{V}";
625 } break;
626 case dwarf::DW_TAG_friend: {
627 SyntheticName += "{W}";
628 } break;
629 case dwarf::DW_TAG_namelist: {
630 SyntheticName += "{X}";
631 } break;
632 case dwarf::DW_TAG_namelist_item: {
633 SyntheticName += "{Y}";
634 } break;
635 case dwarf::DW_TAG_packed_type: {
636 SyntheticName += "{Z}";
637 } break;
638 case dwarf::DW_TAG_subprogram: {
639 SyntheticName += "{a}";
640 } break;
641 case dwarf::DW_TAG_thrown_type: {
642 SyntheticName += "{b}";
643 } break;
644 case dwarf::DW_TAG_variant_part: {
645 SyntheticName += "{c}";
646 } break;
647 case dwarf::DW_TAG_variable: {
648 SyntheticName += "{d}";
649 } break;
650 case dwarf::DW_TAG_volatile_type: {
651 SyntheticName += "{e}";
652 } break;
653 case dwarf::DW_TAG_dwarf_procedure: {
654 SyntheticName += "{f}";
655 } break;
656 case dwarf::DW_TAG_restrict_type: {
657 SyntheticName += "{g}";
658 } break;
659 case dwarf::DW_TAG_interface_type: {
660 SyntheticName += "{h}";
661 } break;
662 case dwarf::DW_TAG_imported_module: {
663 SyntheticName += "{i}";
664 } break;
665 case dwarf::DW_TAG_unspecified_type: {
666 SyntheticName += "{j}";
667 } break;
668 case dwarf::DW_TAG_imported_unit: {
669 SyntheticName += "{k}";
670 } break;
671 case dwarf::DW_TAG_condition: {
672 SyntheticName += "{l}";
673 } break;
674 case dwarf::DW_TAG_shared_type: {
675 SyntheticName += "{m}";
676 } break;
677 case dwarf::DW_TAG_rvalue_reference_type: {
678 SyntheticName += "{n}";
679 } break;
680 case dwarf::DW_TAG_template_alias: {
681 SyntheticName += "{o}";
682 } break;
683 case dwarf::DW_TAG_coarray_type: {
684 SyntheticName += "{p}";
685 } break;
686 case dwarf::DW_TAG_generic_subrange: {
687 SyntheticName += "{q}";
688 } break;
689 case dwarf::DW_TAG_dynamic_type: {
690 SyntheticName += "{r}";
691 } break;
692 case dwarf::DW_TAG_atomic_type: {
693 SyntheticName += "{s}";
694 } break;
695 case dwarf::DW_TAG_call_site: {
696 SyntheticName += "{t}";
697 } break;
698 case dwarf::DW_TAG_call_site_parameter: {
699 SyntheticName += "{u}";
700 } break;
701 case dwarf::DW_TAG_immutable_type: {
702 SyntheticName += "{v}";
703 } break;
704 case dwarf::DW_TAG_entry_point: {
705 SyntheticName += "{w}";
706 } break;
707 case dwarf::DW_TAG_label: {
708 SyntheticName += "{x}";
709 } break;
710 case dwarf::DW_TAG_lexical_block: {
711 SyntheticName += "{y}";
712 } break;
713 case dwarf::DW_TAG_common_block: {
714 SyntheticName += "{z}";
715 } break;
716 case dwarf::DW_TAG_common_inclusion: {
717 SyntheticName += "{|}";
718 } break;
719 case dwarf::DW_TAG_try_block: {
720 SyntheticName += "{~}";
721 } break;
722
723 case dwarf::DW_TAG_null: {
724 llvm_unreachable("No type prefix for DW_TAG_null");
725 } break;
726 case dwarf::DW_TAG_compile_unit: {
727 llvm_unreachable("No type prefix for DW_TAG_compile_unit");
728 } break;
729 case dwarf::DW_TAG_partial_unit: {
730 llvm_unreachable("No type prefix for DW_TAG_partial_unit");
731 } break;
732 case dwarf::DW_TAG_type_unit: {
733 llvm_unreachable("No type prefix for DW_TAG_type_unit");
734 } break;
735 case dwarf::DW_TAG_skeleton_unit: {
736 llvm_unreachable("No type prefix for DW_TAG_skeleton_unit");
737 } break;
738
739 default: {
740 SyntheticName += "{~~";
741 SyntheticName += utohexstr(DieEntry->getTag());
742 SyntheticName += "}";
743 } break;
744 }
745}
746
748 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
749 switch (DieEntry->getTag()) {
750 case dwarf::DW_TAG_array_type:
751 case dwarf::DW_TAG_coarray_type:
752 case dwarf::DW_TAG_class_type:
753 case dwarf::DW_TAG_common_block:
754 case dwarf::DW_TAG_lexical_block:
755 case dwarf::DW_TAG_structure_type:
756 case dwarf::DW_TAG_subprogram:
757 case dwarf::DW_TAG_subroutine_type:
758 case dwarf::DW_TAG_union_type:
759 case dwarf::DW_TAG_GNU_template_template_param:
760 case dwarf::DW_TAG_GNU_formal_parameter_pack:
761 case dwarf::DW_TAG_GNU_template_parameter_pack: {
762 NeedCountChildren = true;
763 } break;
764 case dwarf::DW_TAG_enumeration_type: {
765 // TODO : do we need to add condition
766 NeedCountChildren = true;
767 } break;
768 default: {
769 // Nothing to do.
770 }
771 }
772
773 // Calculate maximal index value
774 if (NeedCountChildren) {
775 for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(DieEntry);
776 CurChild && CurChild->getAbbreviationDeclarationPtr();
777 CurChild = CU.getSiblingEntry(CurChild)) {
778 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, CurChild);
779 if (!ArrayIndex)
780 continue;
781
782 assert((*ArrayIndex < ChildIndexesWidth.size()) &&
783 "Wrong index for ChildIndexesWidth");
784 ChildIndexesWidth[*ArrayIndex]++;
785 }
786
787 // Calculate index field width(number of digits in hexadecimal
788 // representation).
789 for (size_t &Width : ChildIndexesWidth) {
790 size_t digitsCounter = 1;
791 size_t NumToCompare = 15;
792
793 while (NumToCompare < Width) {
794 NumToCompare <<= 4;
795 digitsCounter++;
796 }
797
798 Width = digitsCounter;
799 }
800 }
801}
802
804 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
806 return std::nullopt;
807
808 switch (DieEntry->getTag()) {
809 case dwarf::DW_TAG_unspecified_parameters:
810 case dwarf::DW_TAG_formal_parameter:
811 return 0;
812 case dwarf::DW_TAG_template_value_parameter:
813 case dwarf::DW_TAG_template_type_parameter:
814 case dwarf::DW_TAG_GNU_template_template_param:
815 return 1;
816 case dwarf::DW_TAG_enumeration_type:
817 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) {
818 if (*ParentIdx && CU.getDebugInfoEntry(*ParentIdx)->getTag() ==
819 dwarf::DW_TAG_array_type)
820 return 2;
821 }
822 return std::nullopt;
823 case dwarf::DW_TAG_subrange_type:
824 return 3;
825 case dwarf::DW_TAG_generic_subrange:
826 return 4;
827 case dwarf::DW_TAG_enumerator:
828 return 5;
829 case dwarf::DW_TAG_namelist_item:
830 return 6;
831 case dwarf::DW_TAG_member:
832 // Treat a static data member the same way regardless of whether it's
833 // described as a DW_TAG_member or a DW_TAG_variable.
834 if (isStaticDataMember(DWARFDie(&CU.getOrigUnit(), DieEntry)))
835 return std::nullopt;
836 return 7;
837 default:
838 return std::nullopt;
839 };
840}
841
842std::optional<std::pair<size_t, size_t>>
844 CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
845 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, ChildDieEntry);
846 if (!ArrayIndex)
847 return std::nullopt;
848
849 assert((*ArrayIndex < OrderedChildIdxs.size()) &&
850 "Wrong index for ChildIndexesWidth");
851 assert(ChildIndexesWidth[*ArrayIndex] < 16 &&
852 "Index width exceeds 16 digits.");
853
854 std::pair<size_t, size_t> Result = std::make_pair(
855 OrderedChildIdxs[*ArrayIndex], ChildIndexesWidth[*ArrayIndex]);
856 OrderedChildIdxs[*ArrayIndex]++;
857 return Result;
858}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static std::optional< UnitEntryPairTy > getTypeDeduplicationCandidate(UnitEntryPairTy UnitEntryPair)
static dwarf::Attribute TypeAttr[]
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
DWARFDebugInfoEntry - A DIE with only the minimum required data.
std::optional< uint32_t > getParentIdx() const
Returns index of the parent die.
const DWARFAbbreviationDeclaration * getAbbreviationDeclarationPtr() const
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Definition DWARFDie.h:43
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
Tagged union holding either a T or a Error.
Definition Error.h:485
Error takeError()
Take ownership of the stored error.
Definition Error.h:612
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef getKey() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
Stores all information related to a compile unit, be it in its original instance of the object file o...
std::optional< std::pair< StringRef, StringRef > > getDirAndFilenameFromLineTable(const DWARFFormValue &FileIdxValue)
Returns directory and file from the line table by index.
std::optional< UnitEntryPairTy > resolveDIEReference(const DWARFFormValue &RefValue, ResolveInterCUReferencesMode CanResolveInterCUReferences)
Resolve the DIE attribute reference that has been extracted in RefValue.
OrderedChildrenIndexAssigner(CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry)
std::optional< size_t > tagToArrayIndex(CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry)
std::optional< std::pair< size_t, size_t > > getChildIndex(CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry)
Returns index of the specified child and width of hexadecimal representation.
Error addReferencedODRDies(UnitEntryPairTy InputUnitEntryPair, bool AssignNameToTypeDescriptor, ArrayRef< dwarf::Attribute > ODRAttrs)
Analyze InputUnitEntryPair's ODR attributes and put names of the referenced type dies to the built na...
Error addTemplateParamNames(CompileUnit &CU, SmallVector< const DWARFDebugInfoEntry *, 10 > &TemplateParameters)
Add specified TemplateParameters to the built name.
Error incrementRecursionDepth()
Count a referenced DIE toward the recursion limit.
Error addParentName(UnitEntryPairTy &InputUnitEntryPair)
Add names of parent dies to the built name.
Error addUnqualifiedTypeName(UnitEntryPairTy InputUnitEntryPair)
Add the type InputUnitEntryPair refers to, without parent scopes.
Error addSignature(UnitEntryPairTy InputUnitEntryPair, bool addTemplateParameters)
Add signature( entry type plus type of parameters plus type of template parameters(if addTemplatePara...
Error addParamNames(CompileUnit &CU, SmallVector< const DWARFDebugInfoEntry *, 20 > &FunctionParameters)
Add specified FunctionParameters to the built name.
void addDieNameFromDeclFileAndDeclLine(UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName)
Error addUnnamedTypeContents(UnitEntryPairTy InputUnitEntryPair)
Add contents of the unnamed type InputUnitEntryPair.
Expected< std::optional< UnitEntryPairTy > > resolveReference(UnitEntryPairTy InputUnitEntryPair, dwarf::Attribute Attr)
Resolve the DIE that Attr of InputUnitEntryPair refers to.
SmallString< 1000 > SyntheticName
Buffer keeping bult name.
void addOrderedName(std::pair< size_t, size_t > ChildIdx)
Add ordered name to the built name.
Error assignName(UnitEntryPairTy InputUnitEntryPair, std::optional< std::pair< size_t, size_t > > ChildIndex)
Create synthetic name for the specified DIE InputUnitEntryPair and assign created name to the DIE typ...
Error addDIETypeName(UnitEntryPairTy InputUnitEntryPair, std::optional< std::pair< size_t, size_t > > ChildIndex, bool AssignNameToTypeDescriptor)
Analyze InputUnitEntryPair for the type name and possibly assign built type name to the DIE's type in...
static constexpr size_t MaxRecursionDepth
Bounds RecursionDepth, which malformed input can make unbounded.
Error addTypeName(UnitEntryPairTy InputUnitEntryPair, bool AddParentNames)
Add type name to the built name.
void addArrayDimension(UnitEntryPairTy InputUnitEntryPair)
Add array type dimension.
void addValueName(UnitEntryPairTy InputUnitEntryPair, dwarf::Attribute Attr)
Add value name to the built name.
void addTypePrefix(CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry)
Add type prefix to the built name.
A raw_ostream that writes to an std::string.
TypeEntry * getDieTypeEntry(uint32_t Idx)
Idx index of the DIE.
DIEInfo & getDIEInfo(unsigned Idx)
Idx index of the DIE.
void setDieTypeEntry(uint32_t Idx, TypeEntry *Entry)
Idx index of the DIE.
const DWARFDebugInfoEntry * getSiblingEntry(const DWARFDebugInfoEntry *Die) const
const DWARFDebugInfoEntry * getFirstChildEntry(const DWARFDebugInfoEntry *Die) const
std::optional< DWARFFormValue > find(uint32_t DieIdx, ArrayRef< dwarf::Attribute > Attrs) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
Definition TypePool.h:28
ArrayRef< dwarf::Attribute > getODRAttributes()
LLVM_ABI bool isIdentifiedByChildren(dwarf::Tag Tag)
Test if an unnamed type with tag Tag is identified by its children, which tell it apart from other un...
Definition Utils.cpp:55
LLVM_ABI bool isStaticDataMember(const DWARFDie &Die)
Test if the DW_TAG_member Die is a DWARF 2-4 style static data member: a declaration with no storage ...
Definition Utils.cpp:41
LLVM_ABI bool isIdentifyingChild(const DWARFDie &Die)
Test if Die is a child that identifies its unnamed parent type.
Definition Utils.cpp:68
Attribute
Attributes.
Definition Dwarf.h:125
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
std::optional< uint64_t > toUnsigned(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract an unsigned constant.
This is an optimization pass for GlobalISel generic memory operations.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, bool Upper=false)
format_hex_no_prefix - Output N as a fixed width hexadecimal.
Definition Format.h:177
This is a helper structure which keeps a debug info entry with it's containing compilation unit.