Skip to content

Commit 1783aa4

Browse files
committed
[lldb][TypeSystem] Better support for _BitInt types
This patch ensures we make use of the `DW_AT_bit_size` on `DW_TAG_base_type`s (which since llvm#164372 can exist on `_BitInt`s) and adjusts `TypeSystemClang` to recognize `_BitInt`. For DWARF from older versions of Clang that didn't emit a `DW_AT_bit_size`, we would create `_BitInt`s using the byte-size. Not sure we can do much better than that. But the situation beforehand wasn't much better. Before: ``` (lldb) v (char) a = '\x01' (unsigned char) b = '\x01' (long) c = 2 (unsigned long) d = 2 ``` After: ``` (lldb) v (_BitInt(2)) a = 1 (unsigned _BitInt(2)) b = 1 (_BitInt(52)) c = 2 (unsigned _BitInt(52)) d = 2 ```
1 parent 31f8d65 commit 1783aa4

File tree

4 files changed

+311
-4
lines changed

4 files changed

+311
-4
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -814,13 +814,17 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
814814
// there...
815815
[[fallthrough]];
816816

817-
case DW_TAG_base_type:
817+
case DW_TAG_base_type: {
818818
resolve_state = Type::ResolveState::Full;
819+
// If a builtin type's size isn't a multiple of a byte, DWARF producers may
820+
// add a precise bit-size to the type. Use the most precise bit-size
821+
// possible.
822+
uint64_t bit_size = attrs.data_bit_size ? *attrs.data_bit_size
823+
: attrs.byte_size.value_or(0) * 8;
819824
clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
820-
attrs.name.GetStringRef(), attrs.encoding,
821-
attrs.byte_size.value_or(0) * 8);
825+
attrs.name.GetStringRef(), attrs.encoding, bit_size);
822826
break;
823-
827+
}
824828
case DW_TAG_pointer_type:
825829
encoding_data_type = Type::eEncodingIsPointerUID;
826830
break;

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
10001000

10011001
case DW_ATE_signed:
10021002
if (!type_name.empty()) {
1003+
if (type_name.starts_with("_BitInt"))
1004+
return GetType(ast.getBitIntType(/*Unsigned=*/false, bit_size));
10031005
if (type_name == "wchar_t" &&
10041006
QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
10051007
(getTargetInfo() &&
@@ -1056,6 +1058,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
10561058

10571059
case DW_ATE_unsigned:
10581060
if (!type_name.empty()) {
1061+
if (type_name.starts_with("unsigned _BitInt"))
1062+
return GetType(ast.getBitIntType(/*Unsigned=*/true, bit_size));
10591063
if (type_name == "wchar_t") {
10601064
if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
10611065
if (!(getTargetInfo() &&
@@ -3888,6 +3892,13 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
38883892
->getModifiedType()
38893893
.getAsOpaquePtr(),
38903894
pointee_or_element_clang_type);
3895+
case clang::Type::BitInt: {
3896+
uint32_t type_flags = eTypeIsScalar | eTypeIsInteger | eTypeHasValue;
3897+
if (qual_type->isSignedIntegerType())
3898+
type_flags |= eTypeIsSigned;
3899+
3900+
return type_flags;
3901+
}
38913902
case clang::Type::Builtin: {
38923903
const clang::BuiltinType *builtin_type =
38933904
llvm::cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());

lldb/unittests/Symbol/TestTypeSystemClang.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ class TestTypeSystemClang : public testing::Test {
5252
return ClangUtil::GetQualType(
5353
m_ast->GetBuiltinTypeByName(ConstString(name)));
5454
}
55+
56+
CompilerType GetBuiltinTypeForDWARFEncodingAndBitSize(
57+
llvm::StringRef type_name, uint32_t encoding, uint32_t bit_size) const {
58+
return m_ast->GetBuiltinTypeForDWARFEncodingAndBitSize(type_name, encoding,
59+
bit_size);
60+
}
5561
};
5662

5763
TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
@@ -238,6 +244,75 @@ TEST_F(TestTypeSystemClang, TestBuiltinTypeForEncodingAndBitSize) {
238244
VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);
239245
}
240246

247+
TEST_F(TestTypeSystemClang, TestGetBuiltinTypeForDWARFEncodingAndBitSize) {
248+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
249+
"_BitIn", llvm::dwarf::DW_ATE_signed, 2)
250+
.IsValid());
251+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
252+
"BitInt", llvm::dwarf::DW_ATE_signed, 2)
253+
.IsValid());
254+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
255+
"_BitInt(2)", llvm::dwarf::DW_ATE_signed_char, 2)
256+
.IsValid());
257+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
258+
"_BitInt", llvm::dwarf::DW_ATE_signed_char, 2)
259+
.IsValid());
260+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
261+
"_BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)
262+
.IsValid());
263+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
264+
"_BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
265+
.IsValid());
266+
267+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
268+
"_BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)
269+
.GetTypeName(),
270+
"_BitInt(2)");
271+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
272+
"_BitInt", llvm::dwarf::DW_ATE_signed, 2)
273+
.GetTypeName(),
274+
"_BitInt(2)");
275+
276+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
277+
"unsigned _BitIn", llvm::dwarf::DW_ATE_unsigned, 2)
278+
.IsValid());
279+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
280+
"unsigned BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
281+
.IsValid());
282+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
283+
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned_char, 2)
284+
.IsValid());
285+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
286+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned_char, 2)
287+
.IsValid());
288+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
289+
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)
290+
.IsValid());
291+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
292+
"unsigned _BitInt", llvm::dwarf::DW_ATE_signed, 2)
293+
.IsValid());
294+
295+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
296+
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)
297+
.GetTypeName(),
298+
"unsigned _BitInt(2)");
299+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
300+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
301+
.GetTypeName(),
302+
"unsigned _BitInt(2)");
303+
}
304+
305+
TEST_F(TestTypeSystemClang, TestBitIntTypeInfo) {
306+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
307+
"_BitInt", llvm::dwarf::DW_ATE_signed, 2)
308+
.GetTypeInfo(),
309+
eTypeIsSigned | eTypeIsScalar | eTypeHasValue | eTypeIsInteger);
310+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
311+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
312+
.GetTypeInfo(),
313+
eTypeIsScalar | eTypeHasValue | eTypeIsInteger);
314+
}
315+
241316
TEST_F(TestTypeSystemClang, TestBuiltinTypeForEmptyTriple) {
242317
// Test that we can access type-info of builtin Clang AST
243318
// types without crashing even when the target triple is

lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,3 +1707,220 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) {
17071707
EXPECT_EQ(llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
17081708
1U);
17091709
}
1710+
1711+
TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
1712+
// Tests that we correctly parse the DW_AT_base_type for a _BitInt.
1713+
// Older versions of Clang only emit the `_BitInt` string into the
1714+
// DW_AT_name (not including the bitsize). Make sure we understand
1715+
// those too.
1716+
1717+
const char *yamldata = R"(
1718+
--- !ELF
1719+
FileHeader:
1720+
Class: ELFCLASS64
1721+
Data: ELFDATA2LSB
1722+
Type: ET_EXEC
1723+
Machine: EM_AARCH64
1724+
DWARF:
1725+
debug_str:
1726+
- _BitInt(2)
1727+
- _BitInt
1728+
- unsigned _BitInt(2)
1729+
- unsigned _BitInt
1730+
debug_abbrev:
1731+
- ID: 0
1732+
Table:
1733+
- Code: 0x1
1734+
Tag: DW_TAG_compile_unit
1735+
Children: DW_CHILDREN_yes
1736+
Attributes:
1737+
- Attribute: DW_AT_language
1738+
Form: DW_FORM_data2
1739+
- Code: 0x2
1740+
Tag: DW_TAG_base_type
1741+
Children: DW_CHILDREN_no
1742+
Attributes:
1743+
- Attribute: DW_AT_name
1744+
Form: DW_FORM_strp
1745+
- Attribute: DW_AT_encoding
1746+
Form: DW_FORM_data1
1747+
- Attribute: DW_AT_byte_size
1748+
Form: DW_FORM_data1
1749+
- Attribute: DW_AT_bit_size
1750+
Form: DW_FORM_data1
1751+
- Code: 0x3
1752+
Tag: DW_TAG_base_type
1753+
Children: DW_CHILDREN_no
1754+
Attributes:
1755+
- Attribute: DW_AT_name
1756+
Form: DW_FORM_strp
1757+
- Attribute: DW_AT_encoding
1758+
Form: DW_FORM_data1
1759+
- Attribute: DW_AT_byte_size
1760+
Form: DW_FORM_data1
1761+
1762+
debug_info:
1763+
- Version: 5
1764+
UnitType: DW_UT_compile
1765+
AddrSize: 8
1766+
Entries:
1767+
1768+
# DW_TAG_compile_unit
1769+
# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
1770+
1771+
- AbbrCode: 0x1
1772+
Values:
1773+
- Value: 0x04
1774+
1775+
# DW_TAG_base_type
1776+
# DW_AT_name [DW_FORM_strp] ('_BitInt(2)')
1777+
1778+
- AbbrCode: 0x2
1779+
Values:
1780+
- Value: 0x0
1781+
- Value: 0x05
1782+
- Value: 0x01
1783+
- Value: 0x02
1784+
1785+
# DW_TAG_base_type
1786+
# DW_AT_name [DW_FORM_strp] ('_BitInt')
1787+
1788+
- AbbrCode: 0x2
1789+
Values:
1790+
- Value: 0x0b
1791+
- Value: 0x05
1792+
- Value: 0x08
1793+
- Value: 0x34
1794+
1795+
# DW_TAG_base_type
1796+
# DW_AT_name [DW_FORM_strp] ('unsigned _BitInt(2)')
1797+
1798+
- AbbrCode: 0x2
1799+
Values:
1800+
- Value: 0x13
1801+
- Value: 0x07
1802+
- Value: 0x01
1803+
- Value: 0x02
1804+
1805+
# DW_TAG_base_type
1806+
# DW_AT_name [DW_FORM_strp] ('unsigned _BitInt')
1807+
1808+
- AbbrCode: 0x2
1809+
Values:
1810+
- Value: 0x27
1811+
- Value: 0x07
1812+
- Value: 0x08
1813+
- Value: 0x34
1814+
1815+
# DW_TAG_base_type
1816+
# DW_AT_name [DW_FORM_strp] ('_BitInt')
1817+
1818+
- AbbrCode: 0x3
1819+
Values:
1820+
- Value: 0x0b
1821+
- Value: 0x05
1822+
- Value: 0x08
1823+
...
1824+
1825+
)";
1826+
1827+
YAMLModuleTester t(yamldata);
1828+
1829+
DWARFUnit *unit = t.GetDwarfUnit();
1830+
ASSERT_NE(unit, nullptr);
1831+
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1832+
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1833+
ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1834+
DWARFDIE cu_die(unit, cu_entry);
1835+
1836+
auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
1837+
auto &ast_ctx = *holder->GetAST();
1838+
DWARFASTParserClangStub ast_parser(ast_ctx);
1839+
1840+
auto type_die = cu_die.GetFirstChild();
1841+
ASSERT_TRUE(type_die.IsValid());
1842+
1843+
{
1844+
SymbolContext sc;
1845+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1846+
/*type_is_new_ptr=*/nullptr);
1847+
ASSERT_NE(type_sp, nullptr);
1848+
1849+
EXPECT_EQ(
1850+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1851+
1U);
1852+
uint64_t count;
1853+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingSint);
1854+
EXPECT_EQ(type_sp->GetName(), "_BitInt(2)");
1855+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(2)");
1856+
}
1857+
1858+
{
1859+
type_die = type_die.GetSibling();
1860+
SymbolContext sc;
1861+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1862+
/*type_is_new_ptr=*/nullptr);
1863+
ASSERT_NE(type_sp, nullptr);
1864+
1865+
EXPECT_EQ(
1866+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1867+
8U);
1868+
uint64_t count;
1869+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingSint);
1870+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1871+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(52)");
1872+
}
1873+
1874+
{
1875+
type_die = type_die.GetSibling();
1876+
SymbolContext sc;
1877+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1878+
/*type_is_new_ptr=*/nullptr);
1879+
ASSERT_NE(type_sp, nullptr);
1880+
1881+
EXPECT_EQ(
1882+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1883+
1U);
1884+
uint64_t count;
1885+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingUint);
1886+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt(2)");
1887+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1888+
"unsigned _BitInt(2)");
1889+
}
1890+
1891+
{
1892+
type_die = type_die.GetSibling();
1893+
SymbolContext sc;
1894+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1895+
/*type_is_new_ptr=*/nullptr);
1896+
ASSERT_NE(type_sp, nullptr);
1897+
1898+
EXPECT_EQ(
1899+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1900+
8U);
1901+
uint64_t count;
1902+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingUint);
1903+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt");
1904+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1905+
"unsigned _BitInt(52)");
1906+
}
1907+
1908+
{
1909+
type_die = type_die.GetSibling();
1910+
SymbolContext sc;
1911+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1912+
/*type_is_new_ptr=*/nullptr);
1913+
ASSERT_NE(type_sp, nullptr);
1914+
1915+
EXPECT_EQ(
1916+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1917+
8U);
1918+
uint64_t count;
1919+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingSint);
1920+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1921+
1922+
// Older versions of Clang didn't emit a DW_AT_bit_size for _BitInt. In
1923+
// those cases we would format the CompilerType name using the byte-size.
1924+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
1925+
}
1926+
}

0 commit comments

Comments
 (0)