aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp765
1 files changed, 765 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp b/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp
new file mode 100644
index 000000000000..1554946c2c04
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/SyntheticTypeNameBuilder.cpp
@@ -0,0 +1,765 @@
+//===- SyntheticTypeNameBuilder.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntheticTypeNameBuilder.h"
+#include "DWARFLinkerCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace dwarf_linker;
+using namespace dwarf_linker::parallel;
+
+Error SyntheticTypeNameBuilder::assignName(
+ UnitEntryPairTy InputUnitEntryPair,
+ std::optional<std::pair<size_t, size_t>> ChildIndex) {
+ [[maybe_unused]] const CompileUnit::DIEInfo &Info =
+ InputUnitEntryPair.CU->getDIEInfo(InputUnitEntryPair.DieEntry);
+ assert(Info.needToPlaceInTypeTable() &&
+ "Cann't assign name for non-type DIE");
+
+ if (InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry) !=
+ nullptr)
+ return Error::success();
+
+ SyntheticName.resize(0);
+ RecursionDepth = 0;
+ return addDIETypeName(InputUnitEntryPair, ChildIndex, true);
+}
+
+void SyntheticTypeNameBuilder::addArrayDimension(
+ UnitEntryPairTy InputUnitEntryPair) {
+ for (const DWARFDebugInfoEntry *CurChild =
+ InputUnitEntryPair.CU->getFirstChildEntry(
+ InputUnitEntryPair.DieEntry);
+ CurChild && CurChild->getAbbreviationDeclarationPtr();
+ CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
+ if (CurChild->getTag() == dwarf::DW_TAG_subrange_type ||
+ CurChild->getTag() == dwarf::DW_TAG_generic_subrange) {
+ SyntheticName += "[";
+ if (std::optional<DWARFFormValue> Val =
+ InputUnitEntryPair.CU->find(CurChild, dwarf::DW_AT_count)) {
+ if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
+ SyntheticName += std::to_string(*ConstVal);
+ } else if (std::optional<int64_t> ConstVal =
+ Val->getAsSignedConstant()) {
+ SyntheticName += std::to_string(*ConstVal);
+ }
+ }
+
+ SyntheticName += "]";
+ }
+ }
+}
+
+static dwarf::Attribute TypeAttr[] = {dwarf::DW_AT_type};
+Error SyntheticTypeNameBuilder::addSignature(UnitEntryPairTy InputUnitEntryPair,
+ bool addTemplateParameters) {
+ // Add entry type.
+ if (Error Err = addReferencedODRDies(InputUnitEntryPair, false, TypeAttr))
+ return Err;
+ SyntheticName += ':';
+
+ SmallVector<const DWARFDebugInfoEntry *, 10> TemplateParameters;
+ SmallVector<const DWARFDebugInfoEntry *, 20> FunctionParameters;
+ for (const DWARFDebugInfoEntry *CurChild =
+ InputUnitEntryPair.CU->getFirstChildEntry(
+ InputUnitEntryPair.DieEntry);
+ CurChild && CurChild->getAbbreviationDeclarationPtr();
+ CurChild = InputUnitEntryPair.CU->getSiblingEntry(CurChild)) {
+ dwarf::Tag ChildTag = CurChild->getTag();
+ if (addTemplateParameters &&
+ (ChildTag == dwarf::DW_TAG_template_type_parameter ||
+ ChildTag == dwarf::DW_TAG_template_value_parameter))
+ TemplateParameters.push_back(CurChild);
+ else if (ChildTag == dwarf::DW_TAG_formal_parameter ||
+ ChildTag == dwarf::DW_TAG_unspecified_parameters)
+ FunctionParameters.push_back(CurChild);
+ else if (addTemplateParameters &&
+ ChildTag == dwarf::DW_TAG_GNU_template_parameter_pack) {
+ for (const DWARFDebugInfoEntry *CurGNUChild =
+ InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
+ CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
+ CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
+ TemplateParameters.push_back(CurGNUChild);
+ } else if (ChildTag == dwarf::DW_TAG_GNU_formal_parameter_pack) {
+ for (const DWARFDebugInfoEntry *CurGNUChild =
+ InputUnitEntryPair.CU->getFirstChildEntry(CurChild);
+ CurGNUChild && CurGNUChild->getAbbreviationDeclarationPtr();
+ CurGNUChild = InputUnitEntryPair.CU->getSiblingEntry(CurGNUChild))
+ FunctionParameters.push_back(CurGNUChild);
+ }
+ }
+
+ // Add parameters.
+ if (Error Err = addParamNames(*InputUnitEntryPair.CU, FunctionParameters))
+ return Err;
+
+ // Add template parameters.
+ if (Error Err =
+ addTemplateParamNames(*InputUnitEntryPair.CU, TemplateParameters))
+ return Err;
+
+ return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addParamNames(
+ CompileUnit &CU,
+ SmallVector<const DWARFDebugInfoEntry *, 20> &FunctionParameters) {
+ SyntheticName += '(';
+ for (const DWARFDebugInfoEntry *FunctionParameter : FunctionParameters) {
+ if (SyntheticName.back() != '(')
+ SyntheticName += ", ";
+ if (dwarf::toUnsigned(CU.find(FunctionParameter, dwarf::DW_AT_artificial),
+ 0))
+ SyntheticName += "^";
+ if (Error Err = addReferencedODRDies(
+ UnitEntryPairTy{&CU, FunctionParameter}, false, TypeAttr))
+ return Err;
+ }
+ SyntheticName += ')';
+ return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addTemplateParamNames(
+ CompileUnit &CU,
+ SmallVector<const DWARFDebugInfoEntry *, 10> &TemplateParameters) {
+ if (!TemplateParameters.empty()) {
+ SyntheticName += '<';
+ for (const DWARFDebugInfoEntry *Parameter : TemplateParameters) {
+ if (SyntheticName.back() != '<')
+ SyntheticName += ", ";
+
+ if (Parameter->getTag() == dwarf::DW_TAG_template_value_parameter) {
+ if (std::optional<DWARFFormValue> Val =
+ CU.find(Parameter, dwarf::DW_AT_const_value)) {
+ if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant())
+ SyntheticName += std::to_string(*ConstVal);
+ else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant())
+ SyntheticName += std::to_string(*ConstVal);
+ }
+ }
+
+ if (Error Err = addReferencedODRDies(UnitEntryPairTy{&CU, Parameter},
+ false, TypeAttr))
+ return Err;
+ }
+ SyntheticName += '>';
+ }
+ return Error::success();
+}
+
+void SyntheticTypeNameBuilder::addOrderedName(
+ std::pair<size_t, size_t> ChildIdx) {
+ std::string Name;
+ llvm::raw_string_ostream stream(Name);
+ stream << format_hex_no_prefix(ChildIdx.first, ChildIdx.second);
+ SyntheticName += Name;
+}
+
+// Examine DIE and return type deduplication candidate: some DIEs could not be
+// deduplicated, namespace may refer to another namespace.
+static std::optional<UnitEntryPairTy>
+getTypeDeduplicationCandidate(UnitEntryPairTy UnitEntryPair) {
+ switch (UnitEntryPair.DieEntry->getTag()) {
+ case dwarf::DW_TAG_null:
+ case dwarf::DW_TAG_compile_unit:
+ case dwarf::DW_TAG_partial_unit:
+ case dwarf::DW_TAG_type_unit:
+ case dwarf::DW_TAG_skeleton_unit: {
+ return std::nullopt;
+ }
+ case dwarf::DW_TAG_namespace: {
+ // Check if current namespace refers another.
+ if (UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_extension))
+ UnitEntryPair = UnitEntryPair.getNamespaceOrigin();
+
+ // Content of anonimous namespaces should not be deduplicated.
+ if (!UnitEntryPair.CU->find(UnitEntryPair.DieEntry, dwarf::DW_AT_name))
+ llvm_unreachable("Cann't deduplicate anonimous namespace");
+
+ return UnitEntryPair;
+ }
+ default:
+ return UnitEntryPair;
+ }
+}
+
+Error SyntheticTypeNameBuilder::addParentName(
+ UnitEntryPairTy &InputUnitEntryPair) {
+ std::optional<UnitEntryPairTy> UnitEntryPair = InputUnitEntryPair.getParent();
+ if (!UnitEntryPair)
+ return Error::success();
+
+ UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
+ if (!UnitEntryPair)
+ return Error::success();
+
+ if (TypeEntry *ImmediateParentName =
+ UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry)) {
+ SyntheticName += ImmediateParentName->getKey();
+ SyntheticName += ".";
+ return Error::success();
+ }
+
+ // Collect parent entries.
+ SmallVector<UnitEntryPairTy, 10> Parents;
+ do {
+ Parents.push_back(*UnitEntryPair);
+
+ UnitEntryPair = UnitEntryPair->getParent();
+ if (!UnitEntryPair)
+ break;
+
+ UnitEntryPair = getTypeDeduplicationCandidate(*UnitEntryPair);
+ if (!UnitEntryPair)
+ break;
+
+ } while (!UnitEntryPair->CU->getDieTypeEntry(UnitEntryPair->DieEntry));
+
+ // Assign name for each parent entry.
+ size_t NameStart = SyntheticName.size();
+ for (UnitEntryPairTy Parent : reverse(Parents)) {
+ SyntheticName.resize(NameStart);
+ if (Error Err = addDIETypeName(Parent, std::nullopt, true))
+ return Err;
+ }
+
+ // Add parents delimiter.
+ SyntheticName += ".";
+ return Error::success();
+}
+
+void SyntheticTypeNameBuilder::addDieNameFromDeclFileAndDeclLine(
+ UnitEntryPairTy &InputUnitEntryPair, bool &HasDeclFileName) {
+ if (std::optional<DWARFFormValue> DeclFileVal = InputUnitEntryPair.CU->find(
+ InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_file)) {
+ if (std::optional<DWARFFormValue> DeclLineVal = InputUnitEntryPair.CU->find(
+ InputUnitEntryPair.DieEntry, dwarf::DW_AT_decl_line)) {
+ if (std::optional<std::pair<StringRef, StringRef>> DirAndFilename =
+ InputUnitEntryPair.CU->getDirAndFilenameFromLineTable(
+ *DeclFileVal)) {
+ SyntheticName += DirAndFilename->first;
+ SyntheticName += DirAndFilename->second;
+
+ if (std::optional<uint64_t> DeclLineIntVal =
+ dwarf::toUnsigned(*DeclLineVal)) {
+ SyntheticName += " ";
+ SyntheticName += utohexstr(*DeclLineIntVal);
+ }
+
+ HasDeclFileName = true;
+ }
+ }
+ }
+}
+
+void SyntheticTypeNameBuilder::addValueName(UnitEntryPairTy InputUnitEntryPair,
+ dwarf::Attribute Attr) {
+ if (std::optional<DWARFFormValue> Val =
+ InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
+ if (std::optional<uint64_t> ConstVal = Val->getAsUnsignedConstant()) {
+ SyntheticName += " ";
+ SyntheticName += std::to_string(*ConstVal);
+ } else if (std::optional<int64_t> ConstVal = Val->getAsSignedConstant()) {
+ SyntheticName += " ";
+ SyntheticName += std::to_string(*ConstVal);
+ }
+ }
+}
+
+Error SyntheticTypeNameBuilder::addReferencedODRDies(
+ UnitEntryPairTy InputUnitEntryPair, bool AssignNameToTypeDescriptor,
+ ArrayRef<dwarf::Attribute> ODRAttrs) {
+ bool FirstIteration = true;
+ for (dwarf::Attribute Attr : ODRAttrs) {
+ if (std::optional<DWARFFormValue> AttrValue =
+ InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry, Attr)) {
+ std::optional<UnitEntryPairTy> RefDie =
+ InputUnitEntryPair.CU->resolveDIEReference(
+ *AttrValue, ResolveInterCUReferencesMode::Resolve);
+
+ if (!RefDie)
+ continue;
+
+ if (!RefDie->DieEntry)
+ return createStringError(std::errc::invalid_argument,
+ "Cann't resolve DIE reference");
+
+ if (!FirstIteration)
+ SyntheticName += ",";
+
+ RecursionDepth++;
+ if (RecursionDepth > 1000)
+ return createStringError(
+ std::errc::invalid_argument,
+ "Cann't parse input DWARF. Recursive dependence.");
+
+ if (Error Err =
+ addDIETypeName(*RefDie, std::nullopt, AssignNameToTypeDescriptor))
+ return Err;
+ RecursionDepth--;
+ FirstIteration = false;
+ }
+ }
+
+ return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addTypeName(UnitEntryPairTy InputUnitEntryPair,
+ bool AddParentNames) {
+ bool HasLinkageName = false;
+ bool HasShortName = false;
+ bool HasTemplatesInShortName = false;
+ bool HasDeclFileName = false;
+
+ // Try to get name from the DIE.
+ if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
+ InputUnitEntryPair.DieEntry,
+ {dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_AT_linkage_name})) {
+ // Firstly check for linkage name.
+ SyntheticName += dwarf::toStringRef(Val);
+ HasLinkageName = true;
+ } else if (std::optional<DWARFFormValue> Val = InputUnitEntryPair.CU->find(
+ InputUnitEntryPair.DieEntry, dwarf::DW_AT_name)) {
+ // Then check for short name.
+ StringRef Name = dwarf::toStringRef(Val);
+ SyntheticName += Name;
+
+ HasShortName = true;
+ HasTemplatesInShortName =
+ Name.ends_with(">") && Name.count("<") != 0 && !Name.ends_with("<=>");
+ } else {
+ // Finally check for declaration attributes.
+ addDieNameFromDeclFileAndDeclLine(InputUnitEntryPair, HasDeclFileName);
+ }
+
+ // Add additional name parts for some DIEs.
+ switch (InputUnitEntryPair.DieEntry->getTag()) {
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_interface_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_subroutine_type:
+ case dwarf::DW_TAG_subprogram: {
+ if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
+ dwarf::DW_AT_artificial))
+ SyntheticName += "^";
+
+ // No need to add signature information for linkage name,
+ // also no need to add template parameters name if short name already
+ // includes them.
+ if (!HasLinkageName)
+ if (Error Err =
+ addSignature(InputUnitEntryPair, !HasTemplatesInShortName))
+ return Err;
+ } break;
+ case dwarf::DW_TAG_coarray_type:
+ case dwarf::DW_TAG_array_type: {
+ addArrayDimension(InputUnitEntryPair);
+ } break;
+ case dwarf::DW_TAG_subrange_type: {
+ addValueName(InputUnitEntryPair, dwarf::DW_AT_count);
+ } break;
+ case dwarf::DW_TAG_template_value_parameter: {
+ if (!HasTemplatesInShortName) {
+ // TODO add support for DW_AT_location
+ addValueName(InputUnitEntryPair, dwarf::DW_AT_const_value);
+ }
+ } break;
+ default: {
+ // Nothing to do.
+ } break;
+ }
+
+ // If name for the DIE is not determined yet add referenced types to the name.
+ if (!HasLinkageName && !HasShortName && !HasDeclFileName) {
+ if (InputUnitEntryPair.CU->find(InputUnitEntryPair.DieEntry,
+ getODRAttributes()))
+ if (Error Err = addReferencedODRDies(InputUnitEntryPair, AddParentNames,
+ getODRAttributes()))
+ return Err;
+ }
+
+ return Error::success();
+}
+
+Error SyntheticTypeNameBuilder::addDIETypeName(
+ UnitEntryPairTy InputUnitEntryPair,
+ std::optional<std::pair<size_t, size_t>> ChildIndex,
+ bool AssignNameToTypeDescriptor) {
+ std::optional<UnitEntryPairTy> UnitEntryPair =
+ getTypeDeduplicationCandidate(InputUnitEntryPair);
+ if (!UnitEntryPair)
+ return Error::success();
+
+ TypeEntry *TypeEntryPtr =
+ InputUnitEntryPair.CU->getDieTypeEntry(InputUnitEntryPair.DieEntry);
+ // Check if DIE already has a name.
+ if (!TypeEntryPtr) {
+ size_t NameStart = SyntheticName.size();
+ if (AssignNameToTypeDescriptor) {
+ if (Error Err = addParentName(*UnitEntryPair))
+ return Err;
+ }
+ addTypePrefix(UnitEntryPair->DieEntry);
+
+ if (ChildIndex) {
+ addOrderedName(*ChildIndex);
+ } else {
+ if (Error Err = addTypeName(*UnitEntryPair, AssignNameToTypeDescriptor))
+ return Err;
+ }
+
+ if (AssignNameToTypeDescriptor) {
+ // Add built name to the DIE.
+ TypeEntryPtr = TypePoolRef.insert(SyntheticName.substr(NameStart));
+ InputUnitEntryPair.CU->setDieTypeEntry(InputUnitEntryPair.DieEntry,
+ TypeEntryPtr);
+ }
+ } else
+ SyntheticName += TypeEntryPtr->getKey();
+
+ return Error::success();
+}
+
+void SyntheticTypeNameBuilder::addTypePrefix(
+ const DWARFDebugInfoEntry *DieEntry) {
+ switch (DieEntry->getTag()) {
+ case dwarf::DW_TAG_base_type: {
+ SyntheticName += "{0}";
+ } break;
+ case dwarf::DW_TAG_namespace: {
+ SyntheticName += "{1}";
+ } break;
+ case dwarf::DW_TAG_formal_parameter: {
+ SyntheticName += "{2}";
+ } break;
+ // dwarf::DW_TAG_unspecified_parameters have the same prefix as before.
+ case dwarf::DW_TAG_unspecified_parameters: {
+ SyntheticName += "{2}";
+ } break;
+ case dwarf::DW_TAG_template_type_parameter: {
+ SyntheticName += "{3}";
+ } break;
+ // dwarf::DW_TAG_template_value_parameter have the same prefix as before.
+ case dwarf::DW_TAG_template_value_parameter: {
+ SyntheticName += "{3}";
+ } break;
+ case dwarf::DW_TAG_GNU_formal_parameter_pack: {
+ SyntheticName += "{4}";
+ } break;
+ case dwarf::DW_TAG_GNU_template_parameter_pack: {
+ SyntheticName += "{5}";
+ } break;
+ case dwarf::DW_TAG_inheritance: {
+ SyntheticName += "{6}";
+ } break;
+ case dwarf::DW_TAG_array_type: {
+ SyntheticName += "{7}";
+ } break;
+ case dwarf::DW_TAG_class_type: {
+ SyntheticName += "{8}";
+ } break;
+ case dwarf::DW_TAG_enumeration_type: {
+ SyntheticName += "{9}";
+ } break;
+ case dwarf::DW_TAG_imported_declaration: {
+ SyntheticName += "{A}";
+ } break;
+ case dwarf::DW_TAG_member: {
+ SyntheticName += "{B}";
+ } break;
+ case dwarf::DW_TAG_pointer_type: {
+ SyntheticName += "{C}";
+ } break;
+ case dwarf::DW_TAG_reference_type: {
+ SyntheticName += "{D}";
+ } break;
+ case dwarf::DW_TAG_string_type: {
+ SyntheticName += "{E}";
+ } break;
+ case dwarf::DW_TAG_structure_type: {
+ SyntheticName += "{F}";
+ } break;
+ case dwarf::DW_TAG_subroutine_type: {
+ SyntheticName += "{G}";
+ } break;
+ case dwarf::DW_TAG_typedef: {
+ SyntheticName += "{H}";
+ } break;
+ case dwarf::DW_TAG_union_type: {
+ SyntheticName += "{I}";
+ } break;
+ case dwarf::DW_TAG_variant: {
+ SyntheticName += "{J}";
+ } break;
+ case dwarf::DW_TAG_inlined_subroutine: {
+ SyntheticName += "{K}";
+ } break;
+ case dwarf::DW_TAG_module: {
+ SyntheticName += "{L}";
+ } break;
+ case dwarf::DW_TAG_ptr_to_member_type: {
+ SyntheticName += "{M}";
+ } break;
+ case dwarf::DW_TAG_set_type: {
+ SyntheticName += "{N}";
+ } break;
+ case dwarf::DW_TAG_subrange_type: {
+ SyntheticName += "{O}";
+ } break;
+ case dwarf::DW_TAG_with_stmt: {
+ SyntheticName += "{P}";
+ } break;
+ case dwarf::DW_TAG_access_declaration: {
+ SyntheticName += "{Q}";
+ } break;
+ case dwarf::DW_TAG_catch_block: {
+ SyntheticName += "{R}";
+ } break;
+ case dwarf::DW_TAG_const_type: {
+ SyntheticName += "{S}";
+ } break;
+ case dwarf::DW_TAG_constant: {
+ SyntheticName += "{T}";
+ } break;
+ case dwarf::DW_TAG_enumerator: {
+ SyntheticName += "{U}";
+ } break;
+ case dwarf::DW_TAG_file_type: {
+ SyntheticName += "{V}";
+ } break;
+ case dwarf::DW_TAG_friend: {
+ SyntheticName += "{W}";
+ } break;
+ case dwarf::DW_TAG_namelist: {
+ SyntheticName += "{X}";
+ } break;
+ case dwarf::DW_TAG_namelist_item: {
+ SyntheticName += "{Y}";
+ } break;
+ case dwarf::DW_TAG_packed_type: {
+ SyntheticName += "{Z}";
+ } break;
+ case dwarf::DW_TAG_subprogram: {
+ SyntheticName += "{a}";
+ } break;
+ case dwarf::DW_TAG_thrown_type: {
+ SyntheticName += "{b}";
+ } break;
+ case dwarf::DW_TAG_variant_part: {
+ SyntheticName += "{c}";
+ } break;
+ case dwarf::DW_TAG_variable: {
+ SyntheticName += "{d}";
+ } break;
+ case dwarf::DW_TAG_volatile_type: {
+ SyntheticName += "{e}";
+ } break;
+ case dwarf::DW_TAG_dwarf_procedure: {
+ SyntheticName += "{f}";
+ } break;
+ case dwarf::DW_TAG_restrict_type: {
+ SyntheticName += "{g}";
+ } break;
+ case dwarf::DW_TAG_interface_type: {
+ SyntheticName += "{h}";
+ } break;
+ case dwarf::DW_TAG_imported_module: {
+ SyntheticName += "{i}";
+ } break;
+ case dwarf::DW_TAG_unspecified_type: {
+ SyntheticName += "{j}";
+ } break;
+ case dwarf::DW_TAG_imported_unit: {
+ SyntheticName += "{k}";
+ } break;
+ case dwarf::DW_TAG_condition: {
+ SyntheticName += "{l}";
+ } break;
+ case dwarf::DW_TAG_shared_type: {
+ SyntheticName += "{m}";
+ } break;
+ case dwarf::DW_TAG_rvalue_reference_type: {
+ SyntheticName += "{n}";
+ } break;
+ case dwarf::DW_TAG_template_alias: {
+ SyntheticName += "{o}";
+ } break;
+ case dwarf::DW_TAG_coarray_type: {
+ SyntheticName += "{p}";
+ } break;
+ case dwarf::DW_TAG_generic_subrange: {
+ SyntheticName += "{q}";
+ } break;
+ case dwarf::DW_TAG_dynamic_type: {
+ SyntheticName += "{r}";
+ } break;
+ case dwarf::DW_TAG_atomic_type: {
+ SyntheticName += "{s}";
+ } break;
+ case dwarf::DW_TAG_call_site: {
+ SyntheticName += "{t}";
+ } break;
+ case dwarf::DW_TAG_call_site_parameter: {
+ SyntheticName += "{u}";
+ } break;
+ case dwarf::DW_TAG_immutable_type: {
+ SyntheticName += "{v}";
+ } break;
+ case dwarf::DW_TAG_entry_point: {
+ SyntheticName += "{w}";
+ } break;
+ case dwarf::DW_TAG_label: {
+ SyntheticName += "{x}";
+ } break;
+ case dwarf::DW_TAG_lexical_block: {
+ SyntheticName += "{y}";
+ } break;
+ case dwarf::DW_TAG_common_block: {
+ SyntheticName += "{z}";
+ } break;
+ case dwarf::DW_TAG_common_inclusion: {
+ SyntheticName += "{|}";
+ } break;
+ case dwarf::DW_TAG_try_block: {
+ SyntheticName += "{~}";
+ } break;
+
+ case dwarf::DW_TAG_null: {
+ llvm_unreachable("No type prefix for DW_TAG_null");
+ } break;
+ case dwarf::DW_TAG_compile_unit: {
+ llvm_unreachable("No type prefix for DW_TAG_compile_unit");
+ } break;
+ case dwarf::DW_TAG_partial_unit: {
+ llvm_unreachable("No type prefix for DW_TAG_partial_unit");
+ } break;
+ case dwarf::DW_TAG_type_unit: {
+ llvm_unreachable("No type prefix for DW_TAG_type_unit");
+ } break;
+ case dwarf::DW_TAG_skeleton_unit: {
+ llvm_unreachable("No type prefix for DW_TAG_skeleton_unit");
+ } break;
+
+ default: {
+ SyntheticName += "{~~";
+ SyntheticName += utohexstr(DieEntry->getTag());
+ SyntheticName += "}";
+ } break;
+ }
+}
+
+OrderedChildrenIndexAssigner::OrderedChildrenIndexAssigner(
+ CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
+ switch (DieEntry->getTag()) {
+ case dwarf::DW_TAG_array_type:
+ case dwarf::DW_TAG_coarray_type:
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_common_block:
+ case dwarf::DW_TAG_lexical_block:
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_subprogram:
+ case dwarf::DW_TAG_subroutine_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_GNU_template_template_param:
+ case dwarf::DW_TAG_GNU_formal_parameter_pack: {
+ NeedCountChildren = true;
+ } break;
+ case dwarf::DW_TAG_enumeration_type: {
+ // TODO : do we need to add condition
+ NeedCountChildren = true;
+ } break;
+ default: {
+ // Nothing to do.
+ }
+ }
+
+ // Calculate maximal index value
+ if (NeedCountChildren) {
+ for (const DWARFDebugInfoEntry *CurChild = CU.getFirstChildEntry(DieEntry);
+ CurChild && CurChild->getAbbreviationDeclarationPtr();
+ CurChild = CU.getSiblingEntry(CurChild)) {
+ std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, CurChild);
+ if (!ArrayIndex)
+ continue;
+
+ assert((*ArrayIndex < ChildIndexesWidth.size()) &&
+ "Wrong index for ChildIndexesWidth");
+ ChildIndexesWidth[*ArrayIndex]++;
+ }
+
+ // Calculate index field width(number of digits in hexadecimal
+ // representation).
+ for (size_t &Width : ChildIndexesWidth) {
+ size_t digitsCounter = 1;
+ size_t NumToCompare = 15;
+
+ while (NumToCompare < Width) {
+ NumToCompare <<= 4;
+ digitsCounter++;
+ }
+
+ Width = digitsCounter;
+ }
+ }
+}
+
+std::optional<size_t> OrderedChildrenIndexAssigner::tagToArrayIndex(
+ CompileUnit &CU, const DWARFDebugInfoEntry *DieEntry) {
+ if (!NeedCountChildren)
+ return std::nullopt;
+
+ switch (DieEntry->getTag()) {
+ case dwarf::DW_TAG_unspecified_parameters:
+ case dwarf::DW_TAG_formal_parameter:
+ return 0;
+ case dwarf::DW_TAG_template_value_parameter:
+ case dwarf::DW_TAG_template_type_parameter:
+ return 1;
+ case dwarf::DW_TAG_enumeration_type:
+ if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx()) {
+ if (*ParentIdx && CU.getDebugInfoEntry(*ParentIdx)->getTag() ==
+ dwarf::DW_TAG_array_type)
+ return 2;
+ }
+ return std::nullopt;
+ case dwarf::DW_TAG_subrange_type:
+ return 3;
+ case dwarf::DW_TAG_generic_subrange:
+ return 4;
+ case dwarf::DW_TAG_enumerator:
+ return 5;
+ case dwarf::DW_TAG_namelist_item:
+ return 6;
+ case dwarf::DW_TAG_member:
+ return 7;
+ default:
+ return std::nullopt;
+ };
+}
+
+std::optional<std::pair<size_t, size_t>>
+OrderedChildrenIndexAssigner::getChildIndex(
+ CompileUnit &CU, const DWARFDebugInfoEntry *ChildDieEntry) {
+ std::optional<size_t> ArrayIndex = tagToArrayIndex(CU, ChildDieEntry);
+ if (!ArrayIndex)
+ return std::nullopt;
+
+ assert((*ArrayIndex < OrderedChildIdxs.size()) &&
+ "Wrong index for ChildIndexesWidth");
+ assert(ChildIndexesWidth[*ArrayIndex] < 16 &&
+ "Index width exceeds 16 digits.");
+
+ std::pair<size_t, size_t> Result = std::make_pair(
+ OrderedChildIdxs[*ArrayIndex], ChildIndexesWidth[*ArrayIndex]);
+ OrderedChildIdxs[*ArrayIndex]++;
+ return Result;
+}