Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,13 +814,18 @@ DWARFASTParserClang::ParseTypeModifier(const SymbolContext &sc,
// there...
[[fallthrough]];

case DW_TAG_base_type:
case DW_TAG_base_type: {
resolve_state = Type::ResolveState::Full;
// If a builtin type's size isn't a multiple of a byte, DWARF producers may
// add a precise bit-size to the type. Use the most precise bit-size
// possible.
const uint64_t bit_size = attrs.data_bit_size
? *attrs.data_bit_size
: attrs.byte_size.value_or(0) * 8;
clang_type = m_ast.GetBuiltinTypeForDWARFEncodingAndBitSize(
attrs.name.GetStringRef(), attrs.encoding,
attrs.byte_size.value_or(0) * 8);
attrs.name.GetStringRef(), attrs.encoding, bit_size);
break;

}
case DW_TAG_pointer_type:
encoding_data_type = Type::eEncodingIsPointerUID;
break;
Expand Down
11 changes: 11 additions & 0 deletions lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(

case DW_ATE_signed:
if (!type_name.empty()) {
if (type_name.starts_with("_BitInt"))
return GetType(ast.getBitIntType(/*Unsigned=*/false, bit_size));
if (type_name == "wchar_t" &&
QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy) &&
(getTargetInfo() &&
Expand Down Expand Up @@ -1056,6 +1058,8 @@ CompilerType TypeSystemClang::GetBuiltinTypeForDWARFEncodingAndBitSize(

case DW_ATE_unsigned:
if (!type_name.empty()) {
if (type_name.starts_with("unsigned _BitInt"))
return GetType(ast.getBitIntType(/*Unsigned=*/true, bit_size));
if (type_name == "wchar_t") {
if (QualTypeMatchesBitSize(bit_size, ast, ast.WCharTy)) {
if (!(getTargetInfo() &&
Expand Down Expand Up @@ -3893,6 +3897,13 @@ TypeSystemClang::GetTypeInfo(lldb::opaque_compiler_type_t type,
->getModifiedType()
.getAsOpaquePtr(),
pointee_or_element_clang_type);
case clang::Type::BitInt: {
uint32_t type_flags = eTypeIsScalar | eTypeIsInteger | eTypeHasValue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: const

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't make this one const cause it's modified conditionally few lines down

if (qual_type->isSignedIntegerType())
type_flags |= eTypeIsSigned;

return type_flags;
}
case clang::Type::Builtin: {
const clang::BuiltinType *builtin_type =
llvm::cast<clang::BuiltinType>(qual_type->getCanonicalTypeInternal());
Expand Down
91 changes: 91 additions & 0 deletions lldb/unittests/Symbol/TestTypeSystemClang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ class TestTypeSystemClang : public testing::Test {
return ClangUtil::GetQualType(
m_ast->GetBuiltinTypeByName(ConstString(name)));
}

CompilerType GetBuiltinTypeForDWARFEncodingAndBitSize(
llvm::StringRef type_name, uint32_t encoding, uint32_t bit_size) const {
return m_ast->GetBuiltinTypeForDWARFEncodingAndBitSize(type_name, encoding,
bit_size);
}
};

TEST_F(TestTypeSystemClang, TestGetBasicTypeFromEnum) {
Expand Down Expand Up @@ -238,6 +244,91 @@ TEST_F(TestTypeSystemClang, TestBuiltinTypeForEncodingAndBitSize) {
VerifyEncodingAndBitSize(*m_ast, eEncodingIEEE754, 64);
}

TEST_F(TestTypeSystemClang, TestGetBuiltinTypeForDWARFEncodingAndBitSize) {
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitIn", llvm::dwarf::DW_ATE_signed, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"BitInt", llvm::dwarf::DW_ATE_signed, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt(2)", llvm::dwarf::DW_ATE_signed_char, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt", llvm::dwarf::DW_ATE_signed_char, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
.IsValid());

EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)
.GetTypeName(),
"_BitInt(2)");
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt", llvm::dwarf::DW_ATE_signed, 2)
.GetTypeName(),
"_BitInt(2)");
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt(129)", llvm::dwarf::DW_ATE_signed, 129)
.GetTypeName(),
"_BitInt(129)");
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt", llvm::dwarf::DW_ATE_signed, 129)
.GetTypeName(),
"_BitInt(129)");

EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitIn", llvm::dwarf::DW_ATE_unsigned, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned_char, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned_char, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_signed, 2)
.IsValid());
EXPECT_FALSE(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt", llvm::dwarf::DW_ATE_signed, 2)
.IsValid());

EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt(2)", llvm::dwarf::DW_ATE_unsigned, 2)
.GetTypeName(),
"unsigned _BitInt(2)");
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
.GetTypeName(),
"unsigned _BitInt(2)");
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt(129)", llvm::dwarf::DW_ATE_unsigned, 129)
.GetTypeName(),
"unsigned _BitInt(129)");
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 129)
.GetTypeName(),
"unsigned _BitInt(129)");
}

TEST_F(TestTypeSystemClang, TestBitIntTypeInfo) {
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"_BitInt", llvm::dwarf::DW_ATE_signed, 2)
.GetTypeInfo(),
eTypeIsSigned | eTypeIsScalar | eTypeHasValue | eTypeIsInteger);
EXPECT_EQ(GetBuiltinTypeForDWARFEncodingAndBitSize(
"unsigned _BitInt", llvm::dwarf::DW_ATE_unsigned, 2)
.GetTypeInfo(),
eTypeIsScalar | eTypeHasValue | eTypeIsInteger);
}

TEST_F(TestTypeSystemClang, TestBuiltinTypeForEmptyTriple) {
// Test that we can access type-info of builtin Clang AST
// types without crashing even when the target triple is
Expand Down
212 changes: 212 additions & 0 deletions lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1741,3 +1741,215 @@ TEST_F(DWARFASTParserClangTests, TestTypeBitSize) {
EXPECT_EQ(llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1U);
}

TEST_F(DWARFASTParserClangTests, TestBitIntParsing) {
// Tests that we correctly parse the DW_AT_base_type for a _BitInt.
// Older versions of Clang only emit the `_BitInt` string into the
// DW_AT_name (not including the bitsize). Make sure we understand
// those too.

const char *yamldata = R"(
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Machine: EM_AARCH64
DWARF:
debug_str:
- _BitInt(2)
- _BitInt
- unsigned _BitInt(2)
- unsigned _BitInt
debug_abbrev:
- ID: 0
Table:
- Code: 0x1
Tag: DW_TAG_compile_unit
Children: DW_CHILDREN_yes
Attributes:
- Attribute: DW_AT_language
Form: DW_FORM_data2
- Code: 0x2
Tag: DW_TAG_base_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_encoding
Form: DW_FORM_data1
- Attribute: DW_AT_byte_size
Form: DW_FORM_data1
- Attribute: DW_AT_bit_size
Form: DW_FORM_data1
- Code: 0x3
Tag: DW_TAG_base_type
Children: DW_CHILDREN_no
Attributes:
- Attribute: DW_AT_name
Form: DW_FORM_strp
- Attribute: DW_AT_encoding
Form: DW_FORM_data1
- Attribute: DW_AT_byte_size
Form: DW_FORM_data1

debug_info:
- Version: 5
UnitType: DW_UT_compile
AddrSize: 8
Entries:

# DW_TAG_compile_unit
# DW_AT_language [DW_FORM_data2] (DW_LANG_C_plus_plus)

- AbbrCode: 0x1
Values:
- Value: 0x04

# DW_TAG_base_type
# DW_AT_name [DW_FORM_strp] ('_BitInt(2)')

- AbbrCode: 0x2
Values:
- Value: 0x0
- Value: 0x05
- Value: 0x01
- Value: 0x02

# DW_TAG_base_type
# DW_AT_name [DW_FORM_strp] ('_BitInt')

- AbbrCode: 0x2
Values:
- Value: 0x0b
- Value: 0x05
- Value: 0x08
- Value: 0x34

# DW_TAG_base_type
# DW_AT_name [DW_FORM_strp] ('unsigned _BitInt(2)')

- AbbrCode: 0x2
Values:
- Value: 0x13
- Value: 0x07
- Value: 0x01
- Value: 0x02

# DW_TAG_base_type
# DW_AT_name [DW_FORM_strp] ('unsigned _BitInt')

- AbbrCode: 0x2
Values:
- Value: 0x27
- Value: 0x07
- Value: 0x08
- Value: 0x34

# DW_TAG_base_type
# DW_AT_name [DW_FORM_strp] ('_BitInt')

- AbbrCode: 0x3
Values:
- Value: 0x0b
- Value: 0x05
- Value: 0x08
...

)";

YAMLModuleTester t(yamldata);

DWARFUnit *unit = t.GetDwarfUnit();
ASSERT_NE(unit, nullptr);
const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
DWARFDIE cu_die(unit, cu_entry);

auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
auto &ast_ctx = *holder->GetAST();
DWARFASTParserClangStub ast_parser(ast_ctx);

auto type_die = cu_die.GetFirstChild();
ASSERT_TRUE(type_die.IsValid());

{
SymbolContext sc;
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
/*type_is_new_ptr=*/nullptr);
ASSERT_NE(type_sp, nullptr);

EXPECT_EQ(
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1U);
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
EXPECT_EQ(type_sp->GetName(), "_BitInt(2)");
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(2)");
}

{
type_die = type_die.GetSibling();
SymbolContext sc;
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
/*type_is_new_ptr=*/nullptr);
ASSERT_NE(type_sp, nullptr);

EXPECT_EQ(
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
8U);
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
EXPECT_EQ(type_sp->GetName(), "_BitInt");
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(52)");
}

{
type_die = type_die.GetSibling();
SymbolContext sc;
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
/*type_is_new_ptr=*/nullptr);
ASSERT_NE(type_sp, nullptr);

EXPECT_EQ(
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
1U);
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingUint);
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt(2)");
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
"unsigned _BitInt(2)");
}

{
type_die = type_die.GetSibling();
SymbolContext sc;
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
/*type_is_new_ptr=*/nullptr);
ASSERT_NE(type_sp, nullptr);

EXPECT_EQ(
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
8U);
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingUint);
EXPECT_EQ(type_sp->GetName(), "unsigned _BitInt");
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(),
"unsigned _BitInt(52)");
}

{
type_die = type_die.GetSibling();
SymbolContext sc;
auto type_sp = ast_parser.ParseTypeFromDWARF(sc, type_die,
/*type_is_new_ptr=*/nullptr);
ASSERT_NE(type_sp, nullptr);

EXPECT_EQ(
llvm::expectedToOptional(type_sp->GetByteSize(nullptr)).value_or(0),
8U);
EXPECT_EQ(type_sp->GetEncoding(), lldb::eEncodingSint);
EXPECT_EQ(type_sp->GetName(), "_BitInt");

// Older versions of Clang didn't emit a DW_AT_bit_size for _BitInt. In
// those cases we would format the CompilerType name using the byte-size.
EXPECT_EQ(type_sp->GetForwardCompilerType().GetTypeName(), "_BitInt(64)");
}
}