Skip to content

Commit df81821

Browse files
committed
[lldb][TypeSystem] Better support for _BitInt types (llvm#165689)
Depends on: * llvm#165686 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 ``` Fixes llvm#110273 (cherry picked from commit deb54ba)
1 parent 3d0349f commit df81821

File tree

4 files changed

+323
-4
lines changed

4 files changed

+323
-4
lines changed

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -843,13 +843,18 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
843843
// there...
844844
[[fallthrough]];
845845

846-
case DW_TAG_base_type:
846+
case DW_TAG_base_type: {
847847
resolve_state = Type::ResolveState::Full;
848+
// If a builtin type's size isn't a multiple of a byte, DWARF producers may
849+
// add a precise bit-size to the type. Use the most precise bit-size
850+
// possible.
851+
const uint64_t bit_size = attrs.data_bit_size
852+
? *attrs.data_bit_size
853+
: attrs.byte_size.value_or(0) * 8;
848854
clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
849-
attrs.name.GetStringRef(), attrs.encoding,
850-
attrs.byte_size.value_or(0) * 8);
855+
attrs.name.GetStringRef(), attrs.encoding, bit_size);
851856
break;
852-
857+
}
853858
case DW_TAG_pointer_type:
854859
encoding_data_type = Type::eEncodingIsPointerUID;
855860
break;

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

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

988988
case DW_ATE_signed:
989989
if (!type_name.empty()) {
990+
if (type_name.starts_with("_BitInt"))
991+
return GetType(ast.getBitIntType(/*Unsigned=*/false, bit_size));
990992
if (type_name == "wchar_t" &&
991993
QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
992994
(getTargetInfo() &&
@@ -1043,6 +1045,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(
10431045

10441046
case DW_ATE_unsigned:
10451047
if (!type_name.empty()) {
1048+
if (type_name.starts_with("unsigned _BitInt"))
1049+
return GetType(ast.getBitIntType(/*Unsigned=*/true, bit_size));
10461050
if (type_name == "wchar_t") {
10471051
if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
10481052
if (!(getTargetInfo() &&
@@ -3925,6 +3929,13 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
39253929
->getModifiedType()
39263930
.getAsOpaquePtr(),
39273931
pointee_or_element_clang_type);
3932+
case clang::Type::BitInt: {
3933+
uint32_t type_flags = eTypeIsScalar | eTypeIsInteger | eTypeHasValue;
3934+
if (qual_type->isSignedIntegerType())
3935+
type_flags |= eTypeIsSigned;
3936+
3937+
return type_flags;
3938+
}
39283939
case clang::Type::Builtin: {
39293940
const clang::BuiltinType *builtin_type =
39303941
llvm::cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());

lldb/unittests/Symbol/TestTypeSystemClang.cpp

Lines changed: 91 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) {
@@ -233,6 +239,91 @@ TEST_F(TestTypeSystemClang, TestBuiltinTypeForEncodingAndBitSize) {
233239
VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);
234240
}
235241

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

lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,3 +1707,215 @@ 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+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
1853+
EXPECT_EQ(type_sp->GetName(), "_BitInt(2)");
1854+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(2)");
1855+
}
1856+
1857+
{
1858+
type_die = type_die.GetSibling();
1859+
SymbolContext sc;
1860+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1861+
/*type_is_new_ptr=*/nullptr);
1862+
ASSERT_NE(type_sp, nullptr);
1863+
1864+
EXPECT_EQ(
1865+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1866+
8U);
1867+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
1868+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1869+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(52)");
1870+
}
1871+
1872+
{
1873+
type_die = type_die.GetSibling();
1874+
SymbolContext sc;
1875+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1876+
/*type_is_new_ptr=*/nullptr);
1877+
ASSERT_NE(type_sp, nullptr);
1878+
1879+
EXPECT_EQ(
1880+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1881+
1U);
1882+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingUint);
1883+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt(2)");
1884+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1885+
"unsigned _BitInt(2)");
1886+
}
1887+
1888+
{
1889+
type_die = type_die.GetSibling();
1890+
SymbolContext sc;
1891+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1892+
/*type_is_new_ptr=*/nullptr);
1893+
ASSERT_NE(type_sp, nullptr);
1894+
1895+
EXPECT_EQ(
1896+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1897+
8U);
1898+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingUint);
1899+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt");
1900+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1901+
"unsigned _BitInt(52)");
1902+
}
1903+
1904+
{
1905+
type_die = type_die.GetSibling();
1906+
SymbolContext sc;
1907+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1908+
/*type_is_new_ptr=*/nullptr);
1909+
ASSERT_NE(type_sp, nullptr);
1910+
1911+
EXPECT_EQ(
1912+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1913+
8U);
1914+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
1915+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1916+
1917+
// Older versions of Clang didn't emit a DW_AT_bit_size for _BitInt. In
1918+
// those cases we would format the CompilerType name using the byte-size.
1919+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
1920+
}
1921+
}

0 commit comments

Comments
 (0)