Skip to content

Commit facecc8

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 9ed8896 commit facecc8

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() &&
@@ -3893,6 +3897,13 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
38933897
->getModifiedType()
38943898
.getAsOpaquePtr(),
38953899
pointee_or_element_clang_type);
3900+
case clang::Type::BitInt: {
3901+
uint32_t type_flags = eTypeIsScalar | eTypeIsInteger | eTypeHasValue;
3902+
if (qual_type->isSignedIntegerType())
3903+
type_flags |= eTypeIsSigned;
3904+
3905+
return type_flags;
3906+
}
38963907
case clang::Type::Builtin: {
38973908
const clang::BuiltinType *builtin_type =
38983909
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
@@ -1741,3 +1741,220 @@ 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+
uint64_t count;
1887+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingSint);
1888+
EXPECT_EQ(type_sp->GetName(), "_BitInt(2)");
1889+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(2)");
1890+
}
1891+
1892+
{
1893+
type_die = type_die.GetSibling();
1894+
SymbolContext sc;
1895+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1896+
/*type_is_new_ptr=*/nullptr);
1897+
ASSERT_NE(type_sp, nullptr);
1898+
1899+
EXPECT_EQ(
1900+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1901+
8U);
1902+
uint64_t count;
1903+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingSint);
1904+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1905+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_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+
1U);
1918+
uint64_t count;
1919+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingUint);
1920+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt(2)");
1921+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1922+
"unsigned _BitInt(2)");
1923+
}
1924+
1925+
{
1926+
type_die = type_die.GetSibling();
1927+
SymbolContext sc;
1928+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1929+
/*type_is_new_ptr=*/nullptr);
1930+
ASSERT_NE(type_sp, nullptr);
1931+
1932+
EXPECT_EQ(
1933+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1934+
8U);
1935+
uint64_t count;
1936+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingUint);
1937+
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt");
1938+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
1939+
"unsigned _BitInt(52)");
1940+
}
1941+
1942+
{
1943+
type_die = type_die.GetSibling();
1944+
SymbolContext sc;
1945+
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
1946+
/*type_is_new_ptr=*/nullptr);
1947+
ASSERT_NE(type_sp, nullptr);
1948+
1949+
EXPECT_EQ(
1950+
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1951+
8U);
1952+
uint64_t count;
1953+
EXPECT_EQ(type_sp->GetEncoding(count), lldb::eEncodingSint);
1954+
EXPECT_EQ(type_sp->GetName(), "_BitInt");
1955+
1956+
// Older versions of Clang didn't emit a DW_AT_bit_size for _BitInt. In
1957+
// those cases we would format the CompilerType name using the byte-size.
1958+
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
1959+
}
1960+
}

0 commit comments

Comments
 (0)