Skip to content

Commit aa5fe56

Browse files
OCHyamsdstenb
andauthored
[DebugInfo] Add dataSize to DIBasicType to add DW_AT_bit_size to _BitInt types (llvm#164372)
DW_TAG_base_type DIEs are permitted to have both byte_size and bit_size attributes "If the value of an object of the given type does not fully occupy the storage described by a byte size attribute" * Add DataSizeInBits to DIBasicType (`DIBasicType(... dataSize: n ...)` in IR). * Change Clang to add DataSizeInBits to _BitInt type metadata. * Change LLVM to add DW_AT_bit_size to base_type DIEs that have non-zero DataSizeInBits. TODO: Do we need to emit DW_AT_data_bit_offset for big endian targets? See discussion on the PR. Fixes [llvm#61952](llvm#61952) --------- Co-authored-by: David Stenberg <[email protected]>
1 parent 9b513ad commit aa5fe56

File tree

16 files changed

+173
-57
lines changed

16 files changed

+173
-57
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,14 +1174,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
11741174
}
11751175

11761176
llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {
1177-
11781177
StringRef Name = Ty->isUnsigned() ? "unsigned _BitInt" : "_BitInt";
11791178
llvm::dwarf::TypeKind Encoding = Ty->isUnsigned()
11801179
? llvm::dwarf::DW_ATE_unsigned
11811180
: llvm::dwarf::DW_ATE_signed;
1182-
11831181
return DBuilder.createBasicType(Name, CGM.getContext().getTypeSize(Ty),
1184-
Encoding);
1182+
Encoding, llvm::DINode::FlagZero, 0,
1183+
Ty->getNumBits());
11851184
}
11861185

11871186
llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %clang_cc1 -x c++ %s -debug-info-kind=standalone -gno-column-info -emit-llvm -o - | FileCheck %s
2+
// RUN: %clang_cc1 -x c %s -debug-info-kind=standalone -gno-column-info -emit-llvm -o - | FileCheck %s
3+
4+
unsigned _BitInt(17) a;
5+
_BitInt(2) b;
6+
7+
// CHECK: !DIBasicType(name: "_BitInt", size: 8, dataSize: 2, encoding: DW_ATE_signed)
8+
// CHECK: !DIBasicType(name: "unsigned _BitInt", size: 32, dataSize: 17, encoding: DW_ATE_unsigned)

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,15 @@ namespace llvm {
209209
/// \param NumExtraInhabitants The number of extra inhabitants of the type.
210210
/// An extra inhabitant is a bit pattern that does not represent a valid
211211
/// value for instances of a given type. This is used by the Swift language.
212+
/// \param DataSizeInBits Optionally describes the number of bits used by
213+
/// the value of the object when this is less than the storage size of
214+
/// SizeInBits. Default value of zero indicates the object value and storage
215+
/// sizes are equal.
212216
LLVM_ABI DIBasicType *
213217
createBasicType(StringRef Name, uint64_t SizeInBits, unsigned Encoding,
214218
DINode::DIFlags Flags = DINode::FlagZero,
215-
uint32_t NumExtraInhabitants = 0);
219+
uint32_t NumExtraInhabitants = 0,
220+
uint32_t DataSizeInBits = 0);
216221

217222
/// Create debugging information entry for a binary fixed-point type.
218223
/// \param Name Type name.

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 48 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -891,96 +891,114 @@ class DIBasicType : public DIType {
891891
friend class MDNode;
892892

893893
unsigned Encoding;
894+
/// Describes the number of bits used by the value of the object. Non-zero
895+
/// when the value of an object does not fully occupy the storage size
896+
/// specified by SizeInBits.
897+
uint32_t DataSizeInBits;
894898

895899
protected:
896900
DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
897901
uint32_t AlignInBits, unsigned Encoding,
898-
uint32_t NumExtraInhabitants, DIFlags Flags,
899-
ArrayRef<Metadata *> Ops)
902+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
903+
DIFlags Flags, ArrayRef<Metadata *> Ops)
900904
: DIType(C, DIBasicTypeKind, Storage, Tag, 0, AlignInBits,
901905
NumExtraInhabitants, Flags, Ops),
902-
Encoding(Encoding) {}
906+
Encoding(Encoding), DataSizeInBits(DataSizeInBits) {}
903907
DIBasicType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
904908
uint32_t AlignInBits, unsigned Encoding,
905-
uint32_t NumExtraInhabitants, DIFlags Flags,
906-
ArrayRef<Metadata *> Ops)
909+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
910+
DIFlags Flags, ArrayRef<Metadata *> Ops)
907911
: DIType(C, ID, Storage, Tag, 0, AlignInBits, NumExtraInhabitants, Flags,
908912
Ops),
909-
Encoding(Encoding) {}
913+
Encoding(Encoding), DataSizeInBits(DataSizeInBits) {}
910914
~DIBasicType() = default;
911915

912916
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
913917
StringRef Name, uint64_t SizeInBits,
914918
uint32_t AlignInBits, unsigned Encoding,
915-
uint32_t NumExtraInhabitants, DIFlags Flags,
919+
uint32_t NumExtraInhabitants,
920+
uint32_t DataSizeInBits, DIFlags Flags,
916921
StorageType Storage, bool ShouldCreate = true) {
917922
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
918923
SizeInBits, AlignInBits, Encoding, NumExtraInhabitants,
919-
Flags, Storage, ShouldCreate);
924+
DataSizeInBits, Flags, Storage, ShouldCreate);
920925
}
921926
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
922927
MDString *Name, uint64_t SizeInBits,
923928
uint32_t AlignInBits, unsigned Encoding,
924-
uint32_t NumExtraInhabitants, DIFlags Flags,
929+
uint32_t NumExtraInhabitants,
930+
uint32_t DataSizeInBits, DIFlags Flags,
925931
StorageType Storage, bool ShouldCreate = true) {
926932
auto *SizeInBitsNode = ConstantAsMetadata::get(
927933
ConstantInt::get(Type::getInt64Ty(Context), SizeInBits));
928934
return getImpl(Context, Tag, Name, SizeInBitsNode, AlignInBits, Encoding,
929-
NumExtraInhabitants, Flags, Storage, ShouldCreate);
935+
NumExtraInhabitants, DataSizeInBits, Flags, Storage,
936+
ShouldCreate);
930937
}
931-
LLVM_ABI static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
932-
MDString *Name, Metadata *SizeInBits,
933-
uint32_t AlignInBits, unsigned Encoding,
934-
uint32_t NumExtraInhabitants,
935-
DIFlags Flags, StorageType Storage,
936-
bool ShouldCreate = true);
938+
LLVM_ABI static DIBasicType *
939+
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name,
940+
Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding,
941+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits, DIFlags Flags,
942+
StorageType Storage, bool ShouldCreate = true);
937943

938944
TempDIBasicType cloneImpl() const {
939945
return getTemporary(getContext(), getTag(), getRawName(),
940946
getRawSizeInBits(), getAlignInBits(), getEncoding(),
941-
getNumExtraInhabitants(), getFlags());
947+
getNumExtraInhabitants(), getDataSizeInBits(),
948+
getFlags());
942949
}
943950

944951
public:
945952
DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
946-
(Tag, Name, 0, 0, 0, 0, FlagZero))
953+
(Tag, Name, 0, 0, 0, 0, 0, FlagZero))
947954
DEFINE_MDNODE_GET(DIBasicType,
948955
(unsigned Tag, StringRef Name, uint64_t SizeInBits),
949-
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
956+
(Tag, Name, SizeInBits, 0, 0, 0, 0, FlagZero))
950957
DEFINE_MDNODE_GET(DIBasicType,
951958
(unsigned Tag, MDString *Name, uint64_t SizeInBits),
952-
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
959+
(Tag, Name, SizeInBits, 0, 0, 0, 0, FlagZero))
953960
DEFINE_MDNODE_GET(DIBasicType,
954961
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
955962
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
956-
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, Flags))
963+
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, 0, Flags))
957964
DEFINE_MDNODE_GET(DIBasicType,
958965
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
959966
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
960-
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, Flags))
967+
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, 0, Flags))
961968
DEFINE_MDNODE_GET(DIBasicType,
962969
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
963970
uint32_t AlignInBits, unsigned Encoding,
964971
uint32_t NumExtraInhabitants, DIFlags Flags),
965972
(Tag, Name, SizeInBits, AlignInBits, Encoding,
966-
NumExtraInhabitants, Flags))
973+
NumExtraInhabitants, 0, Flags))
974+
DEFINE_MDNODE_GET(DIBasicType,
975+
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
976+
uint32_t AlignInBits, unsigned Encoding,
977+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
978+
DIFlags Flags),
979+
(Tag, Name, SizeInBits, AlignInBits, Encoding,
980+
NumExtraInhabitants, DataSizeInBits, Flags))
967981
DEFINE_MDNODE_GET(DIBasicType,
968982
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
969983
uint32_t AlignInBits, unsigned Encoding,
970-
uint32_t NumExtraInhabitants, DIFlags Flags),
984+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
985+
DIFlags Flags),
971986
(Tag, Name, SizeInBits, AlignInBits, Encoding,
972-
NumExtraInhabitants, Flags))
987+
NumExtraInhabitants, DataSizeInBits, Flags))
973988
DEFINE_MDNODE_GET(DIBasicType,
974989
(unsigned Tag, MDString *Name, Metadata *SizeInBits,
975990
uint32_t AlignInBits, unsigned Encoding,
976-
uint32_t NumExtraInhabitants, DIFlags Flags),
991+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
992+
DIFlags Flags),
977993
(Tag, Name, SizeInBits, AlignInBits, Encoding,
978-
NumExtraInhabitants, Flags))
994+
NumExtraInhabitants, DataSizeInBits, Flags))
979995

980996
TempDIBasicType clone() const { return cloneImpl(); }
981997

982998
unsigned getEncoding() const { return Encoding; }
983999

1000+
uint32_t getDataSizeInBits() const { return DataSizeInBits; }
1001+
9841002
enum class Signedness { Signed, Unsigned };
9851003

9861004
/// Return the signedness of this type, or std::nullopt if this type is
@@ -1010,7 +1028,7 @@ class DIFixedPointType : public DIBasicType {
10101028
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
10111029
unsigned Kind, int Factor, ArrayRef<Metadata *> Ops)
10121030
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, AlignInBits,
1013-
Encoding, 0, Flags, Ops),
1031+
Encoding, 0, 0, Flags, Ops),
10141032
Kind(Kind), Factor(Factor) {
10151033
assert(Kind == FixedPointBinary || Kind == FixedPointDecimal);
10161034
}
@@ -1019,7 +1037,7 @@ class DIFixedPointType : public DIBasicType {
10191037
unsigned Kind, APInt Numerator, APInt Denominator,
10201038
ArrayRef<Metadata *> Ops)
10211039
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, AlignInBits,
1022-
Encoding, 0, Flags, Ops),
1040+
Encoding, 0, 0, Flags, Ops),
10231041
Kind(Kind), Factor(0), Numerator(Numerator), Denominator(Denominator) {
10241042
assert(Kind == FixedPointRational);
10251043
}
@@ -1028,7 +1046,7 @@ class DIFixedPointType : public DIBasicType {
10281046
unsigned Kind, int Factor, APInt Numerator,
10291047
APInt Denominator, ArrayRef<Metadata *> Ops)
10301048
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, AlignInBits,
1031-
Encoding, 0, Flags, Ops),
1049+
Encoding, 0, 0, Flags, Ops),
10321050
Kind(Kind), Factor(Factor), Numerator(Numerator),
10331051
Denominator(Denominator) {}
10341052
~DIFixedPointType() = default;

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5642,16 +5642,17 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
56425642
OPTIONAL(name, MDStringField, ); \
56435643
OPTIONAL(size, MDUnsignedOrMDField, (0, UINT64_MAX)); \
56445644
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
5645+
OPTIONAL(dataSize, MDUnsignedField, (0, UINT32_MAX)); \
56455646
OPTIONAL(encoding, DwarfAttEncodingField, ); \
56465647
OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX)); \
56475648
OPTIONAL(flags, DIFlagField, );
56485649
PARSE_MD_FIELDS();
56495650
#undef VISIT_MD_FIELDS
56505651

5651-
Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val,
5652-
size.getValueAsMetadata(Context),
5653-
align.Val, encoding.Val,
5654-
num_extra_inhabitants.Val, flags.Val));
5652+
Result = GET_OR_DISTINCT(
5653+
DIBasicType,
5654+
(Context, tag.Val, name.Val, size.getValueAsMetadata(Context), align.Val,
5655+
encoding.Val, num_extra_inhabitants.Val, dataSize.Val, flags.Val));
56555656
return false;
56565657
}
56575658

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15311531
break;
15321532
}
15331533
case bitc::METADATA_BASIC_TYPE: {
1534-
if (Record.size() < 6 || Record.size() > 8)
1534+
if (Record.size() < 6 || Record.size() > 9)
15351535
return error("Invalid record");
15361536

15371537
IsDistinct = Record[0] & 1;
@@ -1540,13 +1540,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15401540
? static_cast<DINode::DIFlags>(Record[6])
15411541
: DINode::FlagZero;
15421542
uint32_t NumExtraInhabitants = (Record.size() > 7) ? Record[7] : 0;
1543-
1543+
uint32_t DataSizeInBits = (Record.size() > 8) ? Record[8] : 0;
15441544
Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[3]);
1545-
15461545
MetadataList.assignValue(
15471546
GET_OR_DISTINCT(DIBasicType,
15481547
(Context, Record[1], getMDString(Record[2]), SizeInBits,
1549-
Record[4], Record[5], NumExtraInhabitants, Flags)),
1548+
Record[4], Record[5], NumExtraInhabitants,
1549+
DataSizeInBits, Flags)),
15501550
NextMetadataNo);
15511551
NextMetadataNo++;
15521552
break;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,7 @@ void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N,
19251925
Record.push_back(N->getEncoding());
19261926
Record.push_back(N->getFlags());
19271927
Record.push_back(N->getNumExtraInhabitants());
1928+
Record.push_back(N->getDataSizeInBits());
19281929

19291930
Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev);
19301931
Record.clear();

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1793,9 +1793,13 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
17931793
"_" + Twine(Btr.BitSize)).toStringRef(Str));
17941794
addUInt(Die, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Btr.Encoding);
17951795
// Round up to smallest number of bytes that contains this number of bits.
1796+
// ExprRefedBaseTypes is populated with types referenced by
1797+
// DW_OP_LLVM_convert operations in location expressions. These are often
1798+
// byte-sized, but one common counter-example is 1-bit sized conversions
1799+
// from `i1` types. TODO: Should these use DW_AT_bit_size? See
1800+
// DwarfUnit::constructTypeDIE.
17961801
addUInt(Die, dwarf::DW_AT_byte_size, std::nullopt,
17971802
divideCeil(Btr.BitSize, 8));
1798-
17991803
Btr.Die = &Die;
18001804
}
18011805
}

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,8 +766,19 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) {
766766
addUInt(Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
767767
BTy->getEncoding());
768768

769-
uint64_t Size = BTy->getSizeInBits() >> 3;
770-
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size);
769+
uint64_t SizeInBytes = divideCeil(BTy->getSizeInBits(), 8);
770+
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, SizeInBytes);
771+
if (BTy->getTag() == dwarf::Tag::DW_TAG_base_type) {
772+
// DW_TAG_base_type:
773+
// If the value of an object of the given type does not fully occupy the
774+
// storage described by a byte size attribute, the base type entry may also
775+
// have a DW_AT_bit_size [...] attribute.
776+
// TODO: Do big endian targets need DW_AT_data_bit_offset? See discussion in
777+
// pull request #164372.
778+
if (uint64_t DataSizeInBits = BTy->getDataSizeInBits();
779+
DataSizeInBits && DataSizeInBits != SizeInBytes * 8)
780+
addUInt(Buffer, dwarf::DW_AT_bit_size, std::nullopt, DataSizeInBits);
781+
}
771782

772783
if (BTy->isBigEndian())
773784
addUInt(Buffer, dwarf::DW_AT_endianity, std::nullopt, dwarf::DW_END_big);

llvm/lib/IR/AsmWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,6 +2199,7 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
21992199
Printer.printString("name", N->getName());
22002200
Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
22012201
Printer.printInt("align", N->getAlignInBits());
2202+
Printer.printInt("dataSize", N->getDataSizeInBits());
22022203
Printer.printDwarfEnum("encoding", N->getEncoding(),
22032204
dwarf::AttributeEncodingString);
22042205
Printer.printInt("num_extra_inhabitants", N->getNumExtraInhabitants());

0 commit comments

Comments
 (0)