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