Skip to content

Commit 9b33d9a

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 9b33d9a

File tree

2 files changed

+180
-4
lines changed

2 files changed

+180
-4
lines changed

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

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "llvm/ADT/StringRef.h"
1414
#include "llvm/BinaryFormat/Dwarf.h"
1515
#include "llvm/Support/Error.h"
16+
#include "llvm/Support/FormatVariadic.h"
1617

1718
#include <string>
1819

@@ -78,6 +79,12 @@ template <typename DieType> struct DWARFTypePrinter {
7879
}
7980
return false;
8081
}
82+
83+
/// If FormValue is a valid constant Form, print into \c OS the integral value
84+
/// casted to the type referred to by \c Cast.
85+
template <typename FormValueType>
86+
void appendCastedValue(const FormValueType &FormValue, DieType Cast,
87+
bool IsUnsigned);
8188
};
8289

8390
template <typename DieType>
@@ -413,6 +420,31 @@ DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
413420
return appendUnqualifiedNameBefore(D);
414421
}
415422

423+
template <typename DieType>
424+
template <typename FormValueType>
425+
void DWARFTypePrinter<DieType>::appendCastedValue(
426+
const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {
427+
std::string ValStr;
428+
if (IsUnsigned) {
429+
std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
430+
if (!UVal)
431+
return;
432+
433+
ValStr = std::to_string(*UVal);
434+
} else {
435+
std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
436+
if (!SVal)
437+
return;
438+
439+
ValStr = std::to_string(*SVal);
440+
}
441+
442+
OS << '(';
443+
appendQualifiedName(Cast);
444+
OS << ')';
445+
OS << std::move(ValStr);
446+
}
447+
416448
template <typename DieType>
417449
bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
418450
bool *FirstParameter) {
@@ -438,13 +470,11 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
438470
DieType T = detail::resolveReferencedType(C);
439471
Sep();
440472
if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
441-
OS << '(';
442-
appendQualifiedName(T);
443-
OS << ')';
444473
auto V = C.find(dwarf::DW_AT_const_value);
445-
OS << std::to_string(*V->getAsSignedConstant());
474+
appendCastedValue(*V, T, /*IsUnsigned=*/false);
446475
continue;
447476
}
477+
448478
// /Maybe/ we could do pointer/reference type parameters, looking for the
449479
// symbol in the ELF symbol table to get back to the variable...
450480
// but probably not worth it.
@@ -539,6 +569,12 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
539569
else
540570
OS << llvm::format("'\\U%08" PRIx64 "'", Val);
541571
}
572+
// FIXME: Handle _BitInt's larger than 64-bits which are emitted as
573+
// block data.
574+
} else if (Name.starts_with("_BitInt")) {
575+
appendCastedValue(*V, T, /*IsUnsigned=*/false);
576+
} else if (Name.starts_with("unsigned _BitInt")) {
577+
appendCastedValue(*V, T, /*IsUnsigned=*/true);
542578
}
543579
continue;
544580
}

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)