Skip to content

Commit 58b1b64

Browse files
committed
llvm-dwarfdump: Lookup type units when prettyprinting types
This handles DWARFv4 and DWARFv5 type units, but not Split DWARF type units. That'll come in a follow-up patch.
1 parent f30a8a6 commit 58b1b64

File tree

6 files changed

+479
-31
lines changed

6 files changed

+479
-31
lines changed

cross-project-tests/debuginfo-tests/clang_llvm_roundtrip/simplified_template_names.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -g -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 \
1+
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -gdwarf-4 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 \
2+
// RUN: | llvm-dwarfdump --verify -
3+
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -gdwarf-4 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 -fdebug-types-section \
4+
// RUN: | llvm-dwarfdump --verify -
5+
// RUN: %clang %target_itanium_abi_host_triple %s -c -o - -gdwarf-5 -Xclang -gsimple-template-names=mangled -Xclang -debug-forward-template-params -std=c++20 -fdebug-types-section \
26
// RUN: | llvm-dwarfdump --verify -
37
#include <cstdint>
48
template<typename ...Ts>

llvm/include/llvm/DebugInfo/DWARF/DWARFContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ class DWARFContext : public DIContext {
243243
}
244244

245245
DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
246+
DWARFTypeUnit *getTypeUnitForHash(uint16_t Version, uint64_t Hash);
246247

247248
/// Return the compile unit that includes an offset (relative to .debug_info).
248249
DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);

llvm/include/llvm/DebugInfo/DWARF/DWARFDie.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ class DWARFDie {
182182
DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const;
183183
DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const;
184184

185+
DWARFDie resolveTypeUnitReference() const;
186+
185187
/// Extract the range base attribute from this DIE as absolute section offset.
186188
///
187189
/// This is a utility function that checks for either the DW_AT_rnglists_base

llvm/lib/DebugInfo/DWARF/DWARFContext.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,27 @@ void DWARFContext::dump(
693693
getDebugNames().dump(OS);
694694
}
695695

696+
DWARFTypeUnit *DWARFContext::getTypeUnitForHash(uint16_t Version,
697+
uint64_t Hash) {
698+
// FIXME: Include support for Split DWARF here
699+
parseNormalUnits();
700+
701+
auto IsTypeWithHash = [&](const std::unique_ptr<DWARFUnit> &Unit) {
702+
DWARFTypeUnit *TU = dyn_cast<DWARFTypeUnit>(Unit.get());
703+
if (!TU)
704+
return false;
705+
return TU->getTypeHash() == Hash;
706+
};
707+
auto I = llvm::find_if(types_section_units(), IsTypeWithHash);
708+
if (I != types_section_units().end())
709+
return cast<DWARFTypeUnit>(I->get());
710+
// Search normal .debug_info units in case it's a DWARFv5 type unit.
711+
I = llvm::find_if(normal_units(), IsTypeWithHash);
712+
if (I != types_section_units().end())
713+
return cast<DWARFTypeUnit>(I->get());
714+
return nullptr;
715+
}
716+
696717
DWARFCompileUnit *DWARFContext::getDWOCompileUnitForHash(uint64_t Hash) {
697718
parseDWOUnits(LazyParse);
698719

llvm/lib/DebugInfo/DWARF/DWARFDie.cpp

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue,
108108
return;
109109
}
110110

111+
static DWARFDie resolveReferencedType(DWARFDie D,
112+
dwarf::Attribute Attr = DW_AT_type) {
113+
return D.getAttributeValueAsReferencedDie(Attr).resolveTypeUnitReference();
114+
}
115+
static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
116+
return D.getAttributeValueAsReferencedDie(F).resolveTypeUnitReference();
117+
}
118+
111119
namespace {
112120

113121
// FIXME: We should have pretty printers per language. Currently we print
@@ -181,7 +189,7 @@ struct DWARFTypePrinter {
181189
DWARFDie skipQualifiers(DWARFDie D) {
182190
while (D && (D.getTag() == DW_TAG_const_type ||
183191
D.getTag() == DW_TAG_volatile_type))
184-
D = D.getAttributeValueAsReferencedDie(DW_AT_type);
192+
D = resolveReferencedType(D);
185193
return D;
186194
}
187195

@@ -209,7 +217,7 @@ struct DWARFTypePrinter {
209217
OS << "void";
210218
return DWARFDie();
211219
}
212-
DWARFDie Inner = D.getAttributeValueAsReferencedDie(DW_AT_type);
220+
DWARFDie Inner = resolveReferencedType(D);
213221
const dwarf::Tag T = D.getTag();
214222
switch (T) {
215223
case DW_TAG_pointer_type: {
@@ -240,8 +248,7 @@ struct DWARFTypePrinter {
240248
OS << '(';
241249
else if (Word)
242250
OS << ' ';
243-
if (DWARFDie Cont =
244-
D.getAttributeValueAsReferencedDie(DW_AT_containing_type)) {
251+
if (DWARFDie Cont = resolveReferencedType(D, DW_AT_containing_type)) {
245252
appendQualifiedName(Cont);
246253
OS << "::";
247254
}
@@ -339,10 +346,9 @@ struct DWARFTypePrinter {
339346
case DW_TAG_pointer_type: {
340347
if (needsParens(Inner))
341348
OS << ')';
342-
appendUnqualifiedNameAfter(
343-
Inner, Inner.getAttributeValueAsReferencedDie(DW_AT_type),
344-
/*SkipFirstParamIfArtificial=*/D.getTag() ==
345-
DW_TAG_ptr_to_member_type);
349+
appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner),
350+
/*SkipFirstParamIfArtificial=*/D.getTag() ==
351+
DW_TAG_ptr_to_member_type);
346352
break;
347353
}
348354
/*
@@ -387,7 +393,7 @@ struct DWARFTypePrinter {
387393
appendTemplateParameters(C, FirstParameter);
388394
}
389395
if (C.getTag() == dwarf::DW_TAG_template_value_parameter) {
390-
DWARFDie T = C.getAttributeValueAsReferencedDie(DW_AT_type);
396+
DWARFDie T = resolveReferencedType(C);
391397
Sep();
392398
if (T.getTag() == DW_TAG_enumeration_type) {
393399
auto V = C.find(DW_AT_const_value);
@@ -523,9 +529,8 @@ struct DWARFTypePrinter {
523529
continue;
524530
auto TypeAttr = C.find(DW_AT_type);
525531
Sep();
526-
appendQualifiedName(TypeAttr
527-
? C.getAttributeValueAsReferencedDie(*TypeAttr)
528-
: DWARFDie());
532+
appendQualifiedName(TypeAttr ? resolveReferencedType(C, *TypeAttr)
533+
: DWARFDie());
529534
}
530535
if (IsTemplate && *FirstParameter && FirstParameter == &FirstParameterValue)
531536
OS << '<';
@@ -534,15 +539,15 @@ struct DWARFTypePrinter {
534539
void decomposeConstVolatile(DWARFDie &N, DWARFDie &T, DWARFDie &C,
535540
DWARFDie &V) {
536541
(N.getTag() == DW_TAG_const_type ? C : V) = N;
537-
T = N.getAttributeValueAsReferencedDie(DW_AT_type);
542+
T = resolveReferencedType(N);
538543
if (T) {
539544
auto Tag = T.getTag();
540545
if (Tag == DW_TAG_const_type) {
541546
C = T;
542-
T = T.getAttributeValueAsReferencedDie(DW_AT_type);
547+
T = resolveReferencedType(T);
543548
} else if (Tag == DW_TAG_volatile_type) {
544549
V = T;
545-
T = T.getAttributeValueAsReferencedDie(DW_AT_type);
550+
T = resolveReferencedType(T);
546551
}
547552
}
548553
}
@@ -552,12 +557,10 @@ struct DWARFTypePrinter {
552557
DWARFDie T;
553558
decomposeConstVolatile(N, T, C, V);
554559
if (T && T.getTag() == DW_TAG_subroutine_type)
555-
appendSubroutineNameAfter(T,
556-
T.getAttributeValueAsReferencedDie(DW_AT_type),
557-
false, C.isValid(), V.isValid());
560+
appendSubroutineNameAfter(T, resolveReferencedType(T), false, C.isValid(),
561+
V.isValid());
558562
else
559-
appendUnqualifiedNameAfter(
560-
T, T.getAttributeValueAsReferencedDie(DW_AT_type));
563+
appendUnqualifiedNameAfter(T, resolveReferencedType(T));
561564
}
562565
void appendConstVolatileQualifierBefore(DWARFDie N) {
563566
DWARFDie C;
@@ -567,7 +570,7 @@ struct DWARFTypePrinter {
567570
bool Subroutine = T && T.getTag() == DW_TAG_subroutine_type;
568571
DWARFDie A = T;
569572
while (A && A.getTag() == DW_TAG_array_type)
570-
A = A.getAttributeValueAsReferencedDie(DW_AT_type);
573+
A = resolveReferencedType(A);
571574
bool Leading =
572575
(!A || (A.getTag() != DW_TAG_pointer_type &&
573576
A.getTag() != llvm::dwarf::DW_TAG_ptr_to_member_type)) &&
@@ -611,7 +614,7 @@ struct DWARFTypePrinter {
611614
for (DWARFDie P : D) {
612615
if (P.getTag() != DW_TAG_formal_parameter)
613616
return;
614-
DWARFDie T = P.getAttributeValueAsReferencedDie(DW_AT_type);
617+
DWARFDie T = resolveReferencedType(P);
615618
if (SkipFirstParamIfArtificial && RealFirst && P.find(DW_AT_artificial)) {
616619
FirstParamIfArtificial = T;
617620
RealFirst = false;
@@ -631,7 +634,7 @@ struct DWARFTypePrinter {
631634
DWARFDie C;
632635
DWARFDie V;
633636
auto CVStep = [&](DWARFDie CV) {
634-
if (DWARFDie U = CV.getAttributeValueAsReferencedDie(DW_AT_type)) {
637+
if (DWARFDie U = resolveReferencedType(CV)) {
635638
if (U.getTag() == DW_TAG_const_type)
636639
return C = U;
637640
if (U.getTag() == DW_TAG_volatile_type)
@@ -658,8 +661,7 @@ struct DWARFTypePrinter {
658661
OS << " &";
659662
if (D.find(DW_AT_rvalue_reference))
660663
OS << " &&";
661-
appendUnqualifiedNameAfter(
662-
Inner, Inner.getAttributeValueAsReferencedDie(DW_AT_type));
664+
appendUnqualifiedNameAfter(Inner, resolveReferencedType(Inner));
663665
}
664666
void appendScopes(DWARFDie D) {
665667
if (D.getTag() == DW_TAG_compile_unit)
@@ -670,6 +672,7 @@ struct DWARFTypePrinter {
670672
return;
671673
if (D.getTag() == DW_TAG_subprogram)
672674
return;
675+
D = D.resolveTypeUnitReference();
673676
if (DWARFDie P = D.getParent())
674677
appendScopes(P);
675678
appendUnqualifiedName(D);
@@ -761,7 +764,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
761764
DINameKind::LinkageName))
762765
OS << Space << "\"" << Name << '\"';
763766
} else if (Attr == DW_AT_type) {
764-
DWARFDie D = Die.getAttributeValueAsReferencedDie(FormValue);
767+
DWARFDie D = resolveReferencedType(Die, FormValue);
765768
if (D && !D.isNULL()) {
766769
OS << Space << "\"";
767770
DWARFTypePrinter(OS).appendQualifiedName(D);
@@ -873,13 +876,27 @@ DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
873876

874877
DWARFDie
875878
DWARFDie::getAttributeValueAsReferencedDie(const DWARFFormValue &V) const {
879+
DWARFDie Result;
876880
if (auto SpecRef = V.getAsRelativeReference()) {
877881
if (SpecRef->Unit)
878-
return SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() + SpecRef->Offset);
879-
if (auto SpecUnit = U->getUnitVector().getUnitForOffset(SpecRef->Offset))
880-
return SpecUnit->getDIEForOffset(SpecRef->Offset);
882+
Result = SpecRef->Unit->getDIEForOffset(SpecRef->Unit->getOffset() +
883+
SpecRef->Offset);
884+
else if (auto SpecUnit =
885+
U->getUnitVector().getUnitForOffset(SpecRef->Offset))
886+
Result = SpecUnit->getDIEForOffset(SpecRef->Offset);
881887
}
882-
return DWARFDie();
888+
return Result;
889+
}
890+
891+
DWARFDie DWARFDie::resolveTypeUnitReference() const {
892+
if (auto Attr = find(DW_AT_signature)) {
893+
if (Optional<uint64_t> Sig = Attr->getAsReferenceUVal()) {
894+
if (DWARFTypeUnit *TU =
895+
U->getContext().getTypeUnitForHash(U->getVersion(), *Sig))
896+
return TU->getDIEForOffset(TU->getTypeOffset() + TU->getOffset());
897+
}
898+
}
899+
return *this;
883900
}
884901

885902
Optional<uint64_t> DWARFDie::getRangesBaseAttribute() const {

0 commit comments

Comments
 (0)