Skip to content

Commit 63ea712

Browse files
Michael137Debadri Basak
authored andcommitted
[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
1 parent ccaa2b3 commit 63ea712

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
@@ -814,13 +814,18 @@ 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+
const uint64_t bit_size = attrs.data_bit_size
823+
? *attrs.data_bit_size
824+
: attrs.byte_size.value_or(0) * 8;
819825
clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
820-
attrs.name.GetStringRef(), attrs.encoding,
821-
attrs.byte_size.value_or(0) * 8);
826+
attrs.name.GetStringRef(), attrs.encoding, bit_size);
822827
break;
823-
828+
}
824829
case DW_TAG_pointer_type:
825830
encoding_data_type = Type::eEncodingIsPointerUID;
826831
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() &&
@@ -3889,6 +3893,13 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
38893893
->getModifiedType()
38903894
.getAsOpaquePtr(),
38913895
pointee_or_element_clang_type);
3896+
case clang::Type::BitInt: {
3897+
uint32_t type_flags = eTypeIsScalar | eTypeIsInteger | eTypeHasValue;
3898+
if (qual_type->isSignedIntegerType())
3899+
type_flags |= eTypeIsSigned;
3900+
3901+
return type_flags;
3902+
}
38923903
case clang::Type::Builtin: {
38933904
const clang::BuiltinType *builtin_type =
38943905
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) {
@@ -238,6 +244,91 @@ 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+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
276+
"_BitInt(129)", llvm::dwarf::DW_ATE_signed, 129)
277+
.GetTypeName(),
278+
"_BitInt(129)");
279+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
280+
"_BitInt", llvm::dwarf::DW_ATE_signed, 129)
281+
.GetTypeName(),
282+
"_BitInt(129)");
283+
284+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
285+
"unsigned _BitIn", llvm::dwarf::DW_ATE_unsigned, 2)
286+
.IsValid());
287+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
288+
"unsigned BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
289+
.IsValid());
290+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
291+
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned_char, 2)
292+
.IsValid());
293+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
294+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned_char, 2)
295+
.IsValid());
296+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
297+
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)
298+
.IsValid());
299+
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
300+
"unsigned _BitInt", llvm::dwarf::DW_ATE_signed, 2)
301+
.IsValid());
302+
303+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
304+
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)
305+
.GetTypeName(),
306+
"unsigned _BitInt(2)");
307+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
308+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
309+
.GetTypeName(),
310+
"unsigned _BitInt(2)");
311+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
312+
"unsigned _BitInt(129)", llvm::dwarf::DW_ATE_unsigned, 129)
313+
.GetTypeName(),
314+
"unsigned _BitInt(129)");
315+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
316+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 129)
317+
.GetTypeName(),
318+
"unsigned _BitInt(129)");
319+
}
320+
321+
TEST_F(TestTypeSystemClang, TestBitIntTypeInfo) {
322+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
323+
"_BitInt", llvm::dwarf::DW_ATE_signed, 2)
324+
.GetTypeInfo(),
325+
eTypeIsSigned | eTypeIsScalar | eTypeHasValue | eTypeIsInteger);
326+
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
327+
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
328+
.GetTypeInfo(),
329+
eTypeIsScalar | eTypeHasValue | eTypeIsInteger);
330+
}
331+
241332
TEST_F(TestTypeSystemClang, TestBuiltinTypeForEmptyTriple) {
242333
// Test that we can access type-info of builtin Clang AST
243334
// 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
@@ -1741,3 +1741,215 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) {
17411741
EXPECT_EQ(llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
17421742
1U);
17431743
}
1744+
1745+
TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
1746+
// Tests that we correctly parse the DW_AT_base_type for a _BitInt.
1747+
// Older versions of Clang only emit the `_BitInt` string into the
1748+
// DW_AT_name (not including the bitsize). Make sure we understand
1749+
// those too.
1750+
1751+
const char *yamldata = R"(
1752+
--- !ELF
1753+
FileHeader:
1754+
Class: ELFCLASS64
1755+
Data: ELFDATA2LSB
1756+
Type: ET_EXEC
1757+
Machine: EM_AARCH64
1758+
DWARF:
1759+
debug_str:
1760+
- _BitInt(2)
1761+
- _BitInt
1762+
- unsigned _BitInt(2)
1763+
- unsigned _BitInt
1764+
debug_abbrev:
1765+
- ID: 0
1766+
Table:
1767+
- Code: 0x1
1768+
Tag: DW_TAG_compile_unit
1769+
Children: DW_CHILDREN_yes
1770+
Attributes:
1771+
- Attribute: DW_AT_language
1772+
Form: DW_FORM_data2
1773+
- Code: 0x2
1774+
Tag: DW_TAG_base_type
1775+
Children: DW_CHILDREN_no
1776+
Attributes:
1777+
- Attribute: DW_AT_name
1778+
Form: DW_FORM_strp
1779+
- Attribute: DW_AT_encoding
1780+
Form: DW_FORM_data1
1781+
- Attribute: DW_AT_byte_size
1782+
Form: DW_FORM_data1
1783+
- Attribute: DW_AT_bit_size
1784+
Form: DW_FORM_data1
1785+
- Code: 0x3
1786+
Tag: DW_TAG_base_type
1787+
Children: DW_CHILDREN_no
1788+
Attributes:
1789+
- Attribute: DW_AT_name
1790+
Form: DW_FORM_strp
1791+
- Attribute: DW_AT_encoding
1792+
Form: DW_FORM_data1
1793+
- Attribute: DW_AT_byte_size
1794+
Form: DW_FORM_data1
1795+
1796+
debug_info:
1797+
- Version: 5
1798+
UnitType: DW_UT_compile
1799+
AddrSize: 8
1800+
Entries:
1801+
1802+
# DW_TAG_compile_unit
1803+
# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)
1804+
1805+
- AbbrCode: 0x1
1806+
Values:
1807+
- Value: 0x04
1808+
1809+
# DW_TAG_base_type
1810+
# DW_AT_name [DW_FORM_strp] ('_BitInt(2)')
1811+
1812+
- AbbrCode: 0x2
1813+
Values:
1814+
- Value: 0x0
1815+
- Value: 0x05
1816+
- Value: 0x01
1817+
- Value: 0x02
1818+
1819+
# DW_TAG_base_type
1820+
# DW_AT_name [DW_FORM_strp] ('_BitInt')
1821+
1822+
- AbbrCode: 0x2
1823+
Values:
1824+
- Value: 0x0b
1825+
- Value: 0x05
1826+
- Value: 0x08
1827+
- Value: 0x34
1828+
1829+
# DW_TAG_base_type
1830+
# DW_AT_name [DW_FORM_strp] ('unsigned _BitInt(2)')
1831+
1832+
- AbbrCode: 0x2
1833+
Values:
1834+
- Value: 0x13
1835+
- Value: 0x07
1836+
- Value: 0x01
1837+
- Value: 0x02
1838+
1839+
# DW_TAG_base_type
1840+
# DW_AT_name [DW_FORM_strp] ('unsigned _BitInt')
1841+
1842+
- AbbrCode: 0x2
1843+
Values:
1844+
- Value: 0x27
1845+
- Value: 0x07
1846+
- Value: 0x08
1847+
- Value: 0x34
1848+
1849+
# DW_TAG_base_type
1850+
# DW_AT_name [DW_FORM_strp] ('_BitInt')
1851+
1852+
- AbbrCode: 0x3
1853+
Values:
1854+
- Value: 0x0b
1855+
- Value: 0x05
1856+
- Value: 0x08
1857+
...
1858+
1859+
)";
1860+
1861+
YAMLModuleTester t(yamldata);
1862+
1863+
DWARFUnit *unit = t.GetDwarfUnit();
1864+
ASSERT_NE(unit, nullptr);
1865+
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
1866+
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
1867+
ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
1868+
DWARFDIE cu_die(unit, cu_entry);
1869+
1870+
auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
1871+
auto &ast_ctx = *holder->GetAST();
1872+
DWARFASTParserClangStub ast_parser(ast_ctx);
1873+
1874+
auto type_die = cu_die.GetFirstChild();
1875+
ASSERT_TRUE(type_die.IsValid());
1876+
1877+
{
1878+
SymbolContext sc;
1879+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1880+
/*type_is_new_ptr=*/nullptr);
1881+
ASSERT_NE(type_sp, nullptr);
1882+
1883+
EXPECT_EQ(
1884+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1885+
1U);
1886+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
1887+
EXPECT_EQ(type_sp->GetName(), "_BitInt(2)");
1888+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_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+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
1902+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1903+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(52)");
1904+
}
1905+
1906+
{
1907+
type_die = type_die.GetSibling();
1908+
SymbolContext sc;
1909+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1910+
/*type_is_new_ptr=*/nullptr);
1911+
ASSERT_NE(type_sp, nullptr);
1912+
1913+
EXPECT_EQ(
1914+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1915+
1U);
1916+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingUint);
1917+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt(2)");
1918+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1919+
"unsigned _BitInt(2)");
1920+
}
1921+
1922+
{
1923+
type_die = type_die.GetSibling();
1924+
SymbolContext sc;
1925+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1926+
/*type_is_new_ptr=*/nullptr);
1927+
ASSERT_NE(type_sp, nullptr);
1928+
1929+
EXPECT_EQ(
1930+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1931+
8U);
1932+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingUint);
1933+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt");
1934+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1935+
"unsigned _BitInt(52)");
1936+
}
1937+
1938+
{
1939+
type_die = type_die.GetSibling();
1940+
SymbolContext sc;
1941+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1942+
/*type_is_new_ptr=*/nullptr);
1943+
ASSERT_NE(type_sp, nullptr);
1944+
1945+
EXPECT_EQ(
1946+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1947+
8U);
1948+
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
1949+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1950+
1951+
// Older versions of Clang didn't emit a DW_AT_bit_size for _BitInt. In
1952+
// those cases we would format the CompilerType name using the byte-size.
1953+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
1954+
}
1955+
}

0 commit comments

Comments
 (0)