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