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#include "llvm/Support/xxhash.h"
16
17using namespace llvm;
18using namespace dwarf_linker;
19using namespace dwarf_linker::parallel;
20
22 UnitEntryPairTy InputUnitEntryPair,
23 std::optional<std::pair<size_t, size_t>> ChildIndex) {
24 [[maybe_unused]] const CompileUnit::DIEInfo &Info =
25 InputUnitEntryPair.CU->getDIEInfo(InputUnitEntryPair.DieEntry);
26 assert(Info.needToPlaceInTypeTable() &&
27 "Cann't assign name for non-type DIE");
28
29 if (InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry) !=
30 nullptr)
31 return Error::success();
32
33 SyntheticName.truncate(0);
35 return addDIETypeName(InputUnitEntryPair, ChildIndex, true);
36}
37
39 UnitEntryPairTy InputUnitEntryPair) {
40 for (const DWARFDebugInfoEntry *CurChild =
41 InputUnitEntryPair.CU->getFirstChildEntry(
42 InputUnitEntryPair.DieEntry);
43 CurChild && CurChild->getAbbreviationDeclarationPtr();
44 CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
45 if (CurChild->getTag() == dwarf::DW_TAG_subrange_type ||
46 CurChild->getTag() == dwarf::DW_TAG_generic_subrange) {
47 SyntheticName += "[";
48 if (std::optional<DWARFFormValue> Val =
49 InputUnitEntryPair.CU->find(CurChild, dwarf::DW_AT_count)) {
50 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
51 SyntheticName += std::to_string(*ConstVal);
52 } else if (std::optional<int64_t> ConstVal =
53 Val->getAsSignedConstant()) {
54 SyntheticName += std::to_string(*ConstVal);
55 }
56 }
57
58 SyntheticName += "]";
59 }
60 }
61}
62
63static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type};
65 bool addTemplateParameters) {
66 // Add entry type.
67 if (Error Err = addReferencedODRDies(InputUnitEntryPair, false, TypeAttr))
68 return Err;
69 SyntheticName += ':';
70
73 for (const DWARFDebugInfoEntry *CurChild =
74 InputUnitEntryPair.CU->getFirstChildEntry(
75 InputUnitEntryPair.DieEntry);
76 CurChild && CurChild->getAbbreviationDeclarationPtr();
77 CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
78 dwarf::Tag ChildTag = CurChild->getTag();
79 if (addTemplateParameters &&
80 (ChildTag == dwarf::DW_TAG_template_type_parameter ||
81 ChildTag == dwarf::DW_TAG_template_value_parameter))
82 TemplateParameters.push_back(CurChild);
83 else if (ChildTag == dwarf::DW_TAG_formal_parameter ||
84 ChildTag == dwarf::DW_TAG_unspecified_parameters)
85 FunctionParameters.push_back(CurChild);
86 else if (addTemplateParameters &&
87 ChildTag == dwarf::DW_TAG_GNU_template_parameter_pack) {
88 for (const DWARFDebugInfoEntry *CurGNUChild =
89 InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
90 CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
91 CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
92 TemplateParameters.push_back(CurGNUChild);
93 } else if (ChildTag == dwarf::DW_TAG_GNU_formal_parameter_pack) {
94 for (const DWARFDebugInfoEntry *CurGNUChild =
95 InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
96 CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
97 CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
98 FunctionParameters.push_back(CurGNUChild);
99 }
100 }
101
102 // Add parameters.
103 if (Error Err = addParamNames(*InputUnitEntryPair.CU, FunctionParameters))
104 return Err;
105
106 // Add template parameters.
107 if (Error Err =
108 addTemplateParamNames(*InputUnitEntryPair.CU, TemplateParameters))
109 return Err;
110
111 return Error::success();
112}
113
117 size_t ParamsStart = SyntheticName.size();
118 SyntheticName += '(';
119 for (const DWARFDebugInfoEntry *FunctionParameter : FunctionParameters) {
120 if (SyntheticName.size() != ParamsStart + 1)
121 SyntheticName += ", ";
122 if (dwarf::toUnsigned(CU.find(FunctionParameter, dwarf::DW_AT_artificial),
123 0))
124 SyntheticName += "^";
125 if (Error Err = addReferencedODRDies(
126 UnitEntryPairTy{&CU, FunctionParameter}, false, TypeAttr))
127 return Err;
128 }
129 SyntheticName += ')';
130 return Error::success();
131}
132
136 if (!TemplateParameters.empty()) {
137 size_t ParamsStart = SyntheticName.size();
138 SyntheticName += '<';
139 for (const DWARFDebugInfoEntry *Parameter : TemplateParameters) {
140 if (SyntheticName.size() != ParamsStart + 1)
141 SyntheticName += ", ";
142
143 if (Parameter->getTag() == dwarf::DW_TAG_template_value_parameter) {
144 if (std::optional<DWARFFormValue> Val =
145 CU.find(Parameter, dwarf::DW_AT_const_value)) {
146 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant())
147 SyntheticName += std::to_string(*ConstVal);
148 else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant())
149 SyntheticName += std::to_string(*ConstVal);
150 }
151 }
152
153 if (Error Err = addReferencedODRDies(UnitEntryPairTy{&CU, Parameter},
154 false, TypeAttr))
155 return Err;
156 }
157 SyntheticName += '>';
158 }
159 return Error::success();
160}
161
163 std::pair<size_t, size_t> ChildIdx) {
164 std::string Name;
165 llvm::raw_string_ostream stream(Name);
166 stream << format_hex_no_prefix(ChildIdx.first, ChildIdx.second);
167 SyntheticName += Name;
168}
169
170// Examine DIE and return type deduplication candidate: some DIEs could not be
171// deduplicated, namespace may refer to another namespace.
172static std::optional<UnitEntryPairTy>
174 switch (UnitEntryPair.DieEntry->getTag()) {
175 case dwarf::DW_TAG_null:
176 case dwarf::DW_TAG_compile_unit:
177 case dwarf::DW_TAG_partial_unit:
178 case dwarf::DW_TAG_type_unit:
179 case dwarf::DW_TAG_skeleton_unit: {
180 return std::nullopt;
181 }
182 case dwarf::DW_TAG_namespace: {
183 // Check if current namespace refers another.
184 if (UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_extension))
185 UnitEntryPair = UnitEntryPair.getNamespaceOrigin();
186
187 // Content of anonimous namespaces should not be deduplicated.
188 if (!UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_name))
189 llvm_unreachable("Cann't deduplicate anonimous namespace");
190
191 return UnitEntryPair;
192 }
193 default:
194 return UnitEntryPair;
195 }
196}
197
199 UnitEntryPairTy &InputUnitEntryPair) {
200 std::optional<UnitEntryPairTy> UnitEntryPair = InputUnitEntryPair.getParent();
201 if (!UnitEntryPair)
202 return Error::success();
203
204 UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
205 if (!UnitEntryPair)
206 return Error::success();
207
208 if (TypeEntry *ImmediateParentName =
209 UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry)) {
210 SyntheticName.appendRef(ImmediateParentName);
211 SyntheticName += ".";
212 return Error::success();
213 }
214
215 // Collect parent entries.
217 do {
218 Parents.push_back(*UnitEntryPair);
219
220 UnitEntryPair = UnitEntryPair->getParent();
221 if (!UnitEntryPair)
222 break;
223
224 UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
225 if (!UnitEntryPair)
226 break;
227
228 } while (!UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry));
229
230 // Assign name for each parent entry.
231 size_t NameStart = SyntheticName.size();
232 for (UnitEntryPairTy Parent : reverse(Parents)) {
233 SyntheticName.truncate(NameStart);
234 if (Error Err = addDIETypeName(Parent, std::nullopt, true))
235 return Err;
236 }
237
238 // Add parents delimiter.
239 SyntheticName += ".";
240 return Error::success();
241}
242
244 UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName) {
245 if (std::optional<DWARFFormValue> DeclFileVal = InputUnitEntryPair.CU->find(
246 InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_file)) {
247 if (std::optional<DWARFFormValue> DeclLineVal = InputUnitEntryPair.CU->find(
248 InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_line)) {
249 if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
250 InputUnitEntryPair.CU->getDirAndFilenameFromLineTable(
251 *DeclFileVal)) {
252 SyntheticName += DirAndFilename->first;
253 SyntheticName += DirAndFilename->second;
254
255 if (std::optional<uint64_t> DeclLineIntVal =
256 dwarf::toUnsigned(*DeclLineVal)) {
257 SyntheticName += " ";
258 SyntheticName += utohexstr(*DeclLineIntVal);
259 }
260
261 HasDeclFileName = true;
262 }
263 }
264 }
265}
266
268 dwarf::Attribute Attr) {
269 if (std::optional<DWARFFormValue> Val =
270 InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
271 if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
272 SyntheticName += " ";
273 SyntheticName += std::to_string(*ConstVal);
274 } else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant()) {
275 SyntheticName += " ";
276 SyntheticName += std::to_string(*ConstVal);
277 }
278 }
279}
280
283 dwarf::Attribute Attr) {
284 std::optional<DWARFFormValue> AttrValue =
285 InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr);
286 if (!AttrValue)
287 return std::nullopt;
288
289 std::optional<UnitEntryPairTy> RefDie =
290 InputUnitEntryPair.CU->resolveDIEReference(
292 if (RefDie && !RefDie->DieEntry)
293 return createStringError(std::errc::invalid_argument,
294 "cannot resolve DIE reference");
295 return RefDie;
296}
297
300 return createStringError(std::errc::invalid_argument,
301 "cannot parse input DWARF: recursive dependence");
302 return Error::success();
303}
304
306 UnitEntryPairTy InputUnitEntryPair, bool AssignNameToTypeDescriptor,
308 bool FirstIteration = true;
309 for (dwarf::Attribute Attr : ODRAttrs) {
311 resolveReference(InputUnitEntryPair, Attr);
312 if (!RefDie)
313 return RefDie.takeError();
314 if (!*RefDie)
315 continue;
316
317 if (!FirstIteration)
318 SyntheticName += ",";
319
320 if (Error Err = incrementRecursionDepth())
321 return Err;
322 if (Error Err =
323 addDIETypeName(**RefDie, std::nullopt, AssignNameToTypeDescriptor))
324 return Err;
326 FirstIteration = false;
327 }
328
329 return Error::success();
330}
331
333 bool AddParentNames) {
334 bool HasLinkageName = false;
335 bool HasShortName = false;
336 bool HasTemplatesInShortName = false;
337 bool HasDeclFileName = false;
338
339 // Try to get name from the DIE.
340 if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
341 InputUnitEntryPair.DieEntry,
342 {dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_AT_linkage_name})) {
343 // Firstly check for linkage name.
345 HasLinkageName = true;
346 } else if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
347 InputUnitEntryPair.DieEntry, dwarf::DW_AT_name)) {
348 // Then check for short name.
349 StringRef Name = dwarf::toStringRef(Val);
350 SyntheticName += Name;
351
352 HasShortName = true;
353 HasTemplatesInShortName =
354 Name.ends_with(">") && Name.count("<") != 0 && !Name.ends_with("<=>");
355 } else {
356 // Finally check for declaration attributes.
357 addDieNameFromDeclFileAndDeclLine(InputUnitEntryPair, HasDeclFileName);
358
359 // Unnamed types declared on one line differ only in their contents.
360 if (HasDeclFileName)
361 if (Error Err = addUnnamedTypeContents(InputUnitEntryPair))
362 return Err;
363 }
364
365 // Add additional name parts for some DIEs.
366 switch (InputUnitEntryPair.DieEntry->getTag()) {
367 case dwarf::DW_TAG_union_type:
368 case dwarf::DW_TAG_interface_type:
369 case dwarf::DW_TAG_class_type:
370 case dwarf::DW_TAG_structure_type:
371 case dwarf::DW_TAG_subroutine_type:
372 case dwarf::DW_TAG_subprogram: {
373 if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
374 dwarf::DW_AT_artificial))
375 SyntheticName += "^";
376
377 // No need to add signature information for linkage name,
378 // also no need to add template parameters name if short name already
379 // includes them.
380 if (!HasLinkageName)
381 if (Error Err =
382 addSignature(InputUnitEntryPair, !HasTemplatesInShortName))
383 return Err;
384 } break;
385 case dwarf::DW_TAG_coarray_type:
386 case dwarf::DW_TAG_array_type: {
387 addArrayDimension(InputUnitEntryPair);
388 } break;
389 case dwarf::DW_TAG_subrange_type: {
390 addValueName(InputUnitEntryPair, dwarf::DW_AT_count);
391 } break;
392 case dwarf::DW_TAG_template_value_parameter: {
393 if (!HasTemplatesInShortName) {
394 // TODO add support for DW_AT_location
395 addValueName(InputUnitEntryPair, dwarf::DW_AT_const_value);
396 }
397 } break;
398 default: {
399 // Nothing to do.
400 } break;
401 }
402
403 // If name for the DIE is not determined yet or if the DIE is a typedef, add
404 // referenced types to the name.
405 if ((!HasLinkageName && !HasShortName && !HasDeclFileName) ||
406 InputUnitEntryPair.DieEntry->getTag() == dwarf::DW_TAG_typedef) {
407 if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
409 if (Error Err = addReferencedODRDies(InputUnitEntryPair, AddParentNames,
411 return Err;
412 }
413
414 return Error::success();
415}
416
418 UnitEntryPairTy InputUnitEntryPair,
419 std::optional<std::pair<size_t, size_t>> ChildIndex,
420 bool AssignNameToTypeDescriptor) {
421 std::optional<UnitEntryPairTy> UnitEntryPair =
422 getTypeDeduplicationCandidate(InputUnitEntryPair);
423 if (!UnitEntryPair)
424 return Error::success();
425
426 TypeEntry *TypeEntryPtr =
427 InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry);
428 // Check if DIE already has a name.
429 if (!TypeEntryPtr) {
430 size_t NameStart = SyntheticName.size();
431 // Prepend the parent scope so this key matches the entry the type is
432 // assigned once it has one. Otherwise the same type gets different keys
433 // depending on whether it already has a pool entry, which races under
434 // parallel assignment and breaks deterministic deduplication.
435 if (Error Err = addParentName(*UnitEntryPair))
436 return Err;
437 addTypePrefix(*UnitEntryPair->CU, UnitEntryPair->DieEntry);
438
439 if (ChildIndex) {
440 addOrderedName(*ChildIndex);
441 } else {
442 if (Error Err = addTypeName(*UnitEntryPair, AssignNameToTypeDescriptor))
443 return Err;
444 }
445
446 // Intern unassigned keys too, since references point at interned entries.
447 TypeEntryPtr = TypePoolRef.insert(SyntheticName.str().substr(NameStart));
448 if (AssignNameToTypeDescriptor)
449 InputUnitEntryPair.CU->setDieTypeEntry(InputUnitEntryPair.DieEntry,
450 TypeEntryPtr);
451 SyntheticName.truncate(NameStart);
452 }
453 SyntheticName.appendRef(TypeEntryPtr);
454
455 return Error::success();
456}
457
459 UnitEntryPairTy InputUnitEntryPair) {
460 if (!isIdentifiedByChildren(InputUnitEntryPair.DieEntry->getTag()))
461 return Error::success();
462
463 auto It = ContentsDigests.find(InputUnitEntryPair.DieEntry);
464 if (It != ContentsDigests.end()) {
465 SyntheticName += It->second;
466 return Error::success();
467 }
468
469 CompileUnit &CU = *InputUnitEntryPair.CU;
470 size_t ContentsStart = SyntheticName.size();
471 SyntheticName += '(';
472 for (const DWARFDebugInfoEntry *CurChild =
473 CU.getFirstChildEntry(InputUnitEntryPair.DieEntry);
474 CurChild && CurChild->getAbbreviationDeclarationPtr();
475 CurChild = CU.getSiblingEntry(CurChild)) {
476 if (!isIdentifyingChild(DWARFDie(&CU.getOrigUnit(), CurChild)))
477 continue;
478
479 if (SyntheticName.size() != ContentsStart + 1)
480 SyntheticName += ", ";
481 addTypePrefix(CU, CurChild);
482 if (std::optional<DWARFFormValue> Val =
483 CU.find(CurChild, dwarf::DW_AT_name))
485 if (Error Err = addUnqualifiedTypeName(UnitEntryPairTy{&CU, CurChild}))
486 return Err;
487 }
488 SyntheticName += ')';
489
490 // Replace the contents with a fixed-size digest, so the names of the types
491 // referring to this one do not grow with its size or nesting depth.
492 StringRef Contents = SyntheticName.str().substr(ContentsStart);
494 std::string Digest = "<" + utohexstr(Hash.high64, true, 16) +
495 utohexstr(Hash.low64, true, 16) + ">";
496 SyntheticName.truncate(ContentsStart);
497 SyntheticName += Digest;
498 ContentsDigests.try_emplace(InputUnitEntryPair.DieEntry, std::move(Digest));
499 return Error::success();
500}
501
503 UnitEntryPairTy InputUnitEntryPair) {
505 resolveReference(InputUnitEntryPair, dwarf::DW_AT_type);
506 if (!RefDie)
507 return RefDie.takeError();
508 if (!*RefDie)
509 return Error::success();
510
511 if (Error Err = incrementRecursionDepth())
512 return Err;
513
514 UnitEntryPairTy Type = **RefDie;
515 SyntheticName += ':';
516 addTypePrefix(*Type.CU, Type.DieEntry);
517 if (std::optional<DWARFFormValue> Val =
518 Type.CU->find(Type.DieEntry, dwarf::DW_AT_name)) {
520 } else {
521 if (Type.DieEntry->getTag() == dwarf::DW_TAG_array_type)
524 return Err;
526 return Err;
527 }
528
530 return Error::success();
531}
532
534 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
535 switch (DieEntry->getTag()) {
536 case dwarf::DW_TAG_base_type: {
537 SyntheticName += "{0}";
538 } break;
539 case dwarf::DW_TAG_namespace: {
540 SyntheticName += "{1}";
541 } break;
542 case dwarf::DW_TAG_formal_parameter: {
543 SyntheticName += "{2}";
544 } break;
545 // dwarf::DW_TAG_unspecified_parameters have the same prefix as before.
546 case dwarf::DW_TAG_unspecified_parameters: {
547 SyntheticName += "{2}";
548 } break;
549 case dwarf::DW_TAG_template_type_parameter: {
550 SyntheticName += "{3}";
551 } break;
552 // dwarf::DW_TAG_template_value_parameter have the same prefix as before.
553 case dwarf::DW_TAG_template_value_parameter: {
554 SyntheticName += "{3}";
555 } break;
556 case dwarf::DW_TAG_GNU_formal_parameter_pack: {
557 SyntheticName += "{4}";
558 } break;
559 case dwarf::DW_TAG_GNU_template_parameter_pack: {
560 SyntheticName += "{5}";
561 } break;
562 case dwarf::DW_TAG_inheritance: {
563 SyntheticName += "{6}";
564 } break;
565 case dwarf::DW_TAG_array_type: {
566 SyntheticName += "{7}";
567 } break;
568 case dwarf::DW_TAG_class_type: {
569 SyntheticName += "{8}";
570 } break;
571 case dwarf::DW_TAG_enumeration_type: {
572 SyntheticName += "{9}";
573 } break;
574 case dwarf::DW_TAG_imported_declaration: {
575 SyntheticName += "{A}";
576 } break;
577 case dwarf::DW_TAG_member: {
578 // Treat a static data member the same way regardless of whether it's
579 // described as a DW_TAG_member or a DW_TAG_variable.
580 if (isStaticDataMember(DWARFDie(&CU.getOrigUnit(), DieEntry)))
581 SyntheticName += "{d}";
582 else
583 SyntheticName += "{B}";
584 } break;
585 case dwarf::DW_TAG_pointer_type: {
586 SyntheticName += "{C}";
587 } break;
588 case dwarf::DW_TAG_reference_type: {
589 SyntheticName += "{D}";
590 } break;
591 case dwarf::DW_TAG_string_type: {
592 SyntheticName += "{E}";
593 } break;
594 case dwarf::DW_TAG_structure_type: {
595 SyntheticName += "{F}";
596 } break;
597 case dwarf::DW_TAG_subroutine_type: {
598 SyntheticName += "{G}";
599 } break;
600 case dwarf::DW_TAG_typedef: {
601 SyntheticName += "{H}";
602 } break;
603 case dwarf::DW_TAG_union_type: {
604 SyntheticName += "{I}";
605 } break;
606 case dwarf::DW_TAG_variant: {
607 SyntheticName += "{J}";
608 } break;
609 case dwarf::DW_TAG_inlined_subroutine: {
610 SyntheticName += "{K}";
611 } break;
612 case dwarf::DW_TAG_module: {
613 SyntheticName += "{L}";
614 } break;
615 case dwarf::DW_TAG_ptr_to_member_type: {
616 SyntheticName += "{M}";
617 } break;
618 case dwarf::DW_TAG_set_type: {
619 SyntheticName += "{N}";
620 } break;
621 case dwarf::DW_TAG_subrange_type: {
622 SyntheticName += "{O}";
623 } break;
624 case dwarf::DW_TAG_with_stmt: {
625 SyntheticName += "{P}";
626 } break;
627 case dwarf::DW_TAG_access_declaration: {
628 SyntheticName += "{Q}";
629 } break;
630 case dwarf::DW_TAG_catch_block: {
631 SyntheticName += "{R}";
632 } break;
633 case dwarf::DW_TAG_const_type: {
634 SyntheticName += "{S}";
635 } break;
636 case dwarf::DW_TAG_constant: {
637 SyntheticName += "{T}";
638 } break;
639 case dwarf::DW_TAG_enumerator: {
640 SyntheticName += "{U}";
641 } break;
642 case dwarf::DW_TAG_file_type: {
643 SyntheticName += "{V}";
644 } break;
645 case dwarf::DW_TAG_friend: {
646 SyntheticName += "{W}";
647 } break;
648 case dwarf::DW_TAG_namelist: {
649 SyntheticName += "{X}";
650 } break;
651 case dwarf::DW_TAG_namelist_item: {
652 SyntheticName += "{Y}";
653 } break;
654 case dwarf::DW_TAG_packed_type: {
655 SyntheticName += "{Z}";
656 } break;
657 case dwarf::DW_TAG_subprogram: {
658 SyntheticName += "{a}";
659 } break;
660 case dwarf::DW_TAG_thrown_type: {
661 SyntheticName += "{b}";
662 } break;
663 case dwarf::DW_TAG_variant_part: {
664 SyntheticName += "{c}";
665 } break;
666 case dwarf::DW_TAG_variable: {
667 SyntheticName += "{d}";
668 } break;
669 case dwarf::DW_TAG_volatile_type: {
670 SyntheticName += "{e}";
671 } break;
672 case dwarf::DW_TAG_dwarf_procedure: {
673 SyntheticName += "{f}";
674 } break;
675 case dwarf::DW_TAG_restrict_type: {
676 SyntheticName += "{g}";
677 } break;
678 case dwarf::DW_TAG_interface_type: {
679 SyntheticName += "{h}";
680 } break;
681 case dwarf::DW_TAG_imported_module: {
682 SyntheticName += "{i}";
683 } break;
684 case dwarf::DW_TAG_unspecified_type: {
685 SyntheticName += "{j}";
686 } break;
687 case dwarf::DW_TAG_imported_unit: {
688 SyntheticName += "{k}";
689 } break;
690 case dwarf::DW_TAG_condition: {
691 SyntheticName += "{l}";
692 } break;
693 case dwarf::DW_TAG_shared_type: {
694 SyntheticName += "{m}";
695 } break;
696 case dwarf::DW_TAG_rvalue_reference_type: {
697 SyntheticName += "{n}";
698 } break;
699 case dwarf::DW_TAG_template_alias: {
700 SyntheticName += "{o}";
701 } break;
702 case dwarf::DW_TAG_coarray_type: {
703 SyntheticName += "{p}";
704 } break;
705 case dwarf::DW_TAG_generic_subrange: {
706 SyntheticName += "{q}";
707 } break;
708 case dwarf::DW_TAG_dynamic_type: {
709 SyntheticName += "{r}";
710 } break;
711 case dwarf::DW_TAG_atomic_type: {
712 SyntheticName += "{s}";
713 } break;
714 case dwarf::DW_TAG_call_site: {
715 SyntheticName += "{t}";
716 } break;
717 case dwarf::DW_TAG_call_site_parameter: {
718 SyntheticName += "{u}";
719 } break;
720 case dwarf::DW_TAG_immutable_type: {
721 SyntheticName += "{v}";
722 } break;
723 case dwarf::DW_TAG_entry_point: {
724 SyntheticName += "{w}";
725 } break;
726 case dwarf::DW_TAG_label: {
727 SyntheticName += "{x}";
728 } break;
729 case dwarf::DW_TAG_lexical_block: {
730 SyntheticName += "{y}";
731 } break;
732 case dwarf::DW_TAG_common_block: {
733 SyntheticName += "{z}";
734 } break;
735 case dwarf::DW_TAG_common_inclusion: {
736 SyntheticName += "{|}";
737 } break;
738 case dwarf::DW_TAG_try_block: {
739 SyntheticName += "{~}";
740 } break;
741
742 case dwarf::DW_TAG_null: {
743 llvm_unreachable("No type prefix for DW_TAG_null");
744 } break;
745 case dwarf::DW_TAG_compile_unit: {
746 llvm_unreachable("No type prefix for DW_TAG_compile_unit");
747 } break;
748 case dwarf::DW_TAG_partial_unit: {
749 llvm_unreachable("No type prefix for DW_TAG_partial_unit");
750 } break;
751 case dwarf::DW_TAG_type_unit: {
752 llvm_unreachable("No type prefix for DW_TAG_type_unit");
753 } break;
754 case dwarf::DW_TAG_skeleton_unit: {
755 llvm_unreachable("No type prefix for DW_TAG_skeleton_unit");
756 } break;
757
758 default: {
759 SyntheticName += "{~~";
760 SyntheticName += utohexstr(DieEntry->getTag());
761 SyntheticName += "}";
762 } break;
763 }
764}
765
767 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
768 switch (DieEntry->getTag()) {
769 case dwarf::DW_TAG_array_type:
770 case dwarf::DW_TAG_coarray_type:
771 case dwarf::DW_TAG_class_type:
772 case dwarf::DW_TAG_common_block:
773 case dwarf::DW_TAG_lexical_block:
774 case dwarf::DW_TAG_structure_type:
775 case dwarf::DW_TAG_subprogram:
776 case dwarf::DW_TAG_subroutine_type:
777 case dwarf::DW_TAG_union_type:
778 case dwarf::DW_TAG_GNU_template_template_param:
779 case dwarf::DW_TAG_GNU_formal_parameter_pack:
780 case dwarf::DW_TAG_GNU_template_parameter_pack: {
781 NeedCountChildren = true;
782 } break;
783 case dwarf::DW_TAG_enumeration_type: {
784 // TODO : do we need to add condition
785 NeedCountChildren = true;
786 } break;
787 default: {
788 // Nothing to do.
789 }
790 }
791
792 // Calculate maximal index value
793 if (NeedCountChildren) {
794 for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(DieEntry);
795 CurChild && CurChild->getAbbreviationDeclarationPtr();
796 CurChild = CU.getSiblingEntry(CurChild)) {
797 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, CurChild);
798 if (!ArrayIndex)
799 continue;
800
801 assert((*ArrayIndex < ChildIndexesWidth.size()) &&
802 "Wrong index for ChildIndexesWidth");
803 ChildIndexesWidth[*ArrayIndex]++;
804 }
805
806 // Calculate index field width(number of digits in hexadecimal
807 // representation).
808 for (size_t &Width : ChildIndexesWidth) {
809 size_t digitsCounter = 1;
810 size_t NumToCompare = 15;
811
812 while (NumToCompare < Width) {
813 NumToCompare <<= 4;
814 digitsCounter++;
815 }
816
817 Width = digitsCounter;
818 }
819 }
820}
821
823 CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
825 return std::nullopt;
826
827 switch (DieEntry->getTag()) {
828 case dwarf::DW_TAG_unspecified_parameters:
829 case dwarf::DW_TAG_formal_parameter:
830 return 0;
831 case dwarf::DW_TAG_template_value_parameter:
832 case dwarf::DW_TAG_template_type_parameter:
833 case dwarf::DW_TAG_GNU_template_template_param:
834 return 1;
835 case dwarf::DW_TAG_enumeration_type:
836 if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) {
837 if (*ParentIdx && CU.getDebugInfoEntry(*ParentIdx)->getTag() ==
838 dwarf::DW_TAG_array_type)
839 return 2;
840 }
841 return std::nullopt;
842 case dwarf::DW_TAG_subrange_type:
843 return 3;
844 case dwarf::DW_TAG_generic_subrange:
845 return 4;
846 case dwarf::DW_TAG_enumerator:
847 return 5;
848 case dwarf::DW_TAG_namelist_item:
849 return 6;
850 case dwarf::DW_TAG_member:
851 // Treat a static data member the same way regardless of whether it's
852 // described as a DW_TAG_member or a DW_TAG_variable.
853 if (isStaticDataMember(DWARFDie(&CU.getOrigUnit(), DieEntry)))
854 return std::nullopt;
855 return 7;
856 default:
857 return std::nullopt;
858 };
859}
860
861std::optional<std::pair<size_t, size_t>>
863 CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
864 std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, ChildDieEntry);
865 if (!ArrayIndex)
866 return std::nullopt;
867
868 assert((*ArrayIndex < OrderedChildIdxs.size()) &&
869 "Wrong index for ChildIndexesWidth");
870 assert(ChildIndexesWidth[*ArrayIndex] < 16 &&
871 "Index width exceeds 16 digits.");
872
873 std::pair<size_t, size_t> Result = std::make_pair(
874 OrderedChildIdxs[*ArrayIndex], ChildIndexesWidth[*ArrayIndex]);
875 OrderedChildIdxs[*ArrayIndex]++;
876 return Result;
877}
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.
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 a fixed-size digest of the contents of the unnamed type InputUnitEntryPair, so the names of the t...
Expected< std::optional< UnitEntryPairTy > > resolveReference(UnitEntryPairTy InputUnitEntryPair, dwarf::Attribute Attr)
Resolve the DIE that Attr of InputUnitEntryPair refers to.
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.
DenseMap< const DWARFDebugInfoEntry *, std::string > ContentsDigests
Digests of the contents of unnamed types, by DIE.
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:31
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.
ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)
Construct an array ref of bytes from a string ref.
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
XXH128_hash_t xxh3_128bits(ArrayRef< uint8_t > data)
Definition ArrayRef.h:561
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
The return value from 128-bit hashes.
Definition xxhash.h:58
uint64_t low64
value & 0xFFFFFFFFFFFFFFFF
Definition xxhash.h:59
uint64_t high64
value >> 64
Definition xxhash.h:60
This is a helper structure which keeps a debug info entry with it's containing compilation unit.