Skip to content

Commit 48a596a

Browse files
committed
[llvm][DebugInfo] Add support for _BitInt in DWARFTypePrinter
As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark `_BitInt`s as "reconstitutable" when compiling with `-gsimple-template-names`. However, before doing so we need to make sure the `DWARFTypePrinter` can reconstruct template parameter values that have `_BitInt` type. This patch adds support for printing `DW_TAG_template_value_parameter`s that have `_BitInt` type. Since `-gsimple-template-names` only omits template parameters that are `<= 64` bit wide, we don't support `_BitInt`s larger than 64 bits.
1 parent f45bb98 commit 48a596a

File tree

2 files changed

+179
-4
lines changed

2 files changed

+179
-4
lines changed

llvm/include/llvm/DebugInfo/DWARF/DWARFTypePrinter.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ template <typename DieType> struct DWARFTypePrinter {
7878
}
7979
return false;
8080
}
81+
82+
/// If FormValue is a valid constant Form, print into \c OS the integral value
83+
/// casted to the type referred to by \c Cast.
84+
template <typename FormValueType>
85+
void appendCastedValue(const FormValueType &FormValue, DieType Cast,
86+
bool IsUnsigned);
8187
};
8288

8389
template <typename DieType>
@@ -413,6 +419,31 @@ DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
413419
return appendUnqualifiedNameBefore(D);
414420
}
415421

422+
template <typename DieType>
423+
template <typename FormValueType>
424+
void DWARFTypePrinter<DieType>::appendCastedValue(
425+
const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {
426+
std::string ValStr;
427+
if (IsUnsigned) {
428+
std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
429+
if (!UVal)
430+
return;
431+
432+
ValStr = std::to_string(*UVal);
433+
} else {
434+
std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
435+
if (!SVal)
436+
return;
437+
438+
ValStr = std::to_string(*SVal);
439+
}
440+
441+
OS << '(';
442+
appendQualifiedName(Cast);
443+
OS << ')';
444+
OS << std::move(ValStr);
445+
}
446+
416447
template <typename DieType>
417448
bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
418449
bool *FirstParameter) {
@@ -438,13 +469,11 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
438469
DieType T = detail::resolveReferencedType(C);
439470
Sep();
440471
if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
441-
OS << '(';
442-
appendQualifiedName(T);
443-
OS << ')';
444472
auto V = C.find(dwarf::DW_AT_const_value);
445-
OS << std::to_string(*V->getAsSignedConstant());
473+
appendCastedValue(*V, T, /*IsUnsigned=*/false);
446474
continue;
447475
}
476+
448477
// /Maybe/ we could do pointer/reference type parameters, looking for the
449478
// symbol in the ELF symbol table to get back to the variable...
450479
// but probably not worth it.
@@ -539,6 +568,12 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
539568
else
540569
OS << llvm::format("'\\U%08" PRIx64 "'", Val);
541570
}
571+
// FIXME: Handle _BitInt's larger than 64-bits which are emitted as
572+
// block data.
573+
} else if (Name.starts_with("_BitInt")) {
574+
appendCastedValue(*V, T, /*IsUnsigned=*/false);
575+
} else if (Name.starts_with("unsigned _BitInt")) {
576+
appendCastedValue(*V, T, /*IsUnsigned=*/true);
542577
}
543578
continue;
544579
}

llvm/unittests/DebugInfo/DWARF/DWARFDieTest.cpp

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,4 +839,144 @@ TEST(DWARFDie, DWARFTypePrinterTest) {
839839
testAppendQualifiedName(Ctx->getDIEForOffset(0x1a), "t1<t3<int> >::t2");
840840
testAppendQualifiedName(Ctx->getDIEForOffset(0x28), "t3<int>::my_int");
841841
}
842+
843+
TEST(DWARFDie, DWARFTypePrinterTest_BitInt) {
844+
// Make sure we can reconstruct the case where a template value parameter
845+
// is a _BitInt.
846+
847+
// DW_TAG_compile_unit
848+
// DW_TAG_base_type
849+
// DW_AT_name ("_BitInt(2)")
850+
// DW_AT_bit_size ("2")
851+
// DW_TAG_base_type
852+
// DW_AT_name ("_BitInt(65)")
853+
// DW_AT_bit_size ("65")
854+
// DW_TAG_base_type
855+
// DW_AT_name ("unsigned _BitInt(2)")
856+
// DW_AT_bit_size ("2")
857+
// DW_TAG_base_type
858+
// DW_AT_name ("unsigned _BitInt(65)")
859+
// DW_AT_bit_size ("65")
860+
// DW_TAG_structure_type
861+
// DW_AT_name ("foo")
862+
// DW_TAG_template_value_parameter
863+
// DW_AT_type ("_BitInt(2)")
864+
// DW_AT_const_value (DW_FORM_sdata "-1")
865+
// DW_TAG_template_value_parameter
866+
// DW_AT_type ("unsigned _BitInt(2)")
867+
// DW_AT_const_value (DW_FORM_udata "12")
868+
// DW_TAG_template_value_parameter
869+
// DW_AT_type ("_BitInt(65)")
870+
// DW_AT_const_value (DW_FORM_block1 "1")
871+
// DW_TAG_template_value_parameter
872+
// DW_AT_type ("unsigned _BitInt(65)")
873+
// DW_AT_const_value (DW_FORM_block1 "1")
874+
// NULL
875+
// NULL
876+
const char *yamldata = R"(
877+
debug_abbrev:
878+
- ID: 0
879+
Table:
880+
- Code: 0x1
881+
Tag: DW_TAG_compile_unit
882+
Children: DW_CHILDREN_yes
883+
- Code: 0x2
884+
Tag: DW_TAG_base_type
885+
Children: DW_CHILDREN_no
886+
Attributes:
887+
- Attribute: DW_AT_name
888+
Form: DW_FORM_string
889+
- Code: 0x3
890+
Tag: DW_TAG_structure_type
891+
Children: DW_CHILDREN_yes
892+
Attributes:
893+
- Attribute: DW_AT_name
894+
Form: DW_FORM_string
895+
- Code: 0x4
896+
Tag: DW_TAG_template_value_parameter
897+
Children: DW_CHILDREN_no
898+
Attributes:
899+
- Attribute: DW_AT_type
900+
Form: DW_FORM_ref4
901+
- Attribute: DW_AT_const_value
902+
Form: DW_FORM_sdata
903+
- Code: 0x5
904+
Tag: DW_TAG_template_value_parameter
905+
Children: DW_CHILDREN_no
906+
Attributes:
907+
- Attribute: DW_AT_type
908+
Form: DW_FORM_ref4
909+
- Attribute: DW_AT_const_value
910+
Form: DW_FORM_udata
911+
- Code: 0x6
912+
Tag: DW_TAG_template_value_parameter
913+
Children: DW_CHILDREN_no
914+
Attributes:
915+
- Attribute: DW_AT_type
916+
Form: DW_FORM_ref4
917+
- Attribute: DW_AT_const_value
918+
Form: DW_FORM_block1
919+
debug_info:
920+
- Version: 4
921+
AddrSize: 8
922+
Entries:
923+
- AbbrCode: 0x1
924+
- AbbrCode: 0x2
925+
Values:
926+
- Value: 0xDEADBEEFDEADBEEF
927+
CStr: _BitInt(2)
928+
- AbbrCode: 0x2
929+
Values:
930+
- Value: 0xDEADBEEFDEADBEEF
931+
CStr: _BitInt(65)
932+
- AbbrCode: 0x2
933+
Values:
934+
- Value: 0xDEADBEEFDEADBEEF
935+
CStr: unsigned _BitInt(2)
936+
- AbbrCode: 0x2
937+
Values:
938+
- Value: 0xDEADBEEFDEADBEEF
939+
CStr: unsigned _BitInt(65)
940+
- AbbrCode: 0x3
941+
Values:
942+
- Value: 0xDEADBEEFDEADBEEF
943+
CStr: foo
944+
- AbbrCode: 0x4
945+
Values:
946+
- Value: 0x0000000c
947+
- Value: 0xffffffffffffffff
948+
- AbbrCode: 0x5
949+
Values:
950+
- Value: 0x00000025
951+
- Value: 12
952+
- AbbrCode: 0x6
953+
Values:
954+
- Value: 0x00000018
955+
- Value: 0x0F
956+
BlockData: [ 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
957+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
958+
- AbbrCode: 0x6
959+
Values:
960+
- Value: 0x0000003a
961+
- Value: 0x0F
962+
BlockData: [ 0x22, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
963+
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 ]
964+
- AbbrCode: 0x0
965+
- AbbrCode: 0x0
966+
)";
967+
Expected<StringMap<std::unique_ptr<MemoryBuffer>>> Sections =
968+
DWARFYAML::emitDebugSections(StringRef(yamldata),
969+
/*IsLittleEndian=*/true,
970+
/*Is64BitAddrSize=*/true);
971+
ASSERT_THAT_EXPECTED(Sections, Succeeded());
972+
std::unique_ptr<DWARFContext> Ctx =
973+
DWARFContext::create(*Sections, 4, /*isLittleEndian=*/true);
974+
975+
// FIXME: support _BitInt's with block forms. Currently they are just omitted.
976+
// Will be necessary once -gsimple-template-names emit template value
977+
// parameters with bit-width larger than 64.
978+
testAppendAndTerminateTemplateParameters(
979+
Ctx->getDIEForOffset(0x50),
980+
"<(_BitInt(2))-1, (unsigned _BitInt(2))12, , >");
981+
}
842982
} // end anonymous namespace

0 commit comments

Comments
 (0)