Skip to content

Commit bdd06fb

Browse files
OCHyamsdstenb
authored andcommitted
[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]> (cherry picked from commit aa5fe56)
1 parent d9aa2f7 commit bdd06fb

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
@@ -1146,14 +1146,13 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
11461146
}
11471147

11481148
llvm::DIType *CGDebugInfo::CreateType(const BitIntType *Ty) {
1149-
11501149
StringRef Name = Ty->isUnsigned() ? "unsigned _BitInt" : "_BitInt";
11511150
llvm::dwarf::TypeKind Encoding = Ty->isUnsigned()
11521151
? llvm::dwarf::DW_ATE_unsigned
11531152
: llvm::dwarf::DW_ATE_signed;
1154-
11551153
return DBuilder.createBasicType(Name, CGM.getContext().getTypeSize(Ty),
1156-
Encoding);
1154+
Encoding, llvm::DINode::FlagZero, 0,
1155+
Ty->getNumBits());
11571156
}
11581157

11591158
llvm::DIType *CGDebugInfo::CreateType(const ComplexType *Ty) {

clang/test/CodeGen/bit-int.c

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
@@ -844,96 +844,114 @@ class DIBasicType : public DIType {
844844
friend class MDNode;
845845

846846
unsigned Encoding;
847+
/// Describes the number of bits used by the value of the object. Non-zero
848+
/// when the value of an object does not fully occupy the storage size
849+
/// specified by SizeInBits.
850+
uint32_t DataSizeInBits;
847851

848852
protected:
849853
DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
850854
uint32_t AlignInBits, unsigned Encoding,
851-
uint32_t NumExtraInhabitants, DIFlags Flags,
852-
ArrayRef<Metadata *> Ops)
855+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
856+
DIFlags Flags, ArrayRef<Metadata *> Ops)
853857
: DIType(C, DIBasicTypeKind, Storage, Tag, 0, AlignInBits,
854858
NumExtraInhabitants, Flags, Ops),
855-
Encoding(Encoding) {}
859+
Encoding(Encoding), DataSizeInBits(DataSizeInBits) {}
856860
DIBasicType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
857861
uint32_t AlignInBits, unsigned Encoding,
858-
uint32_t NumExtraInhabitants, DIFlags Flags,
859-
ArrayRef<Metadata *> Ops)
862+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
863+
DIFlags Flags, ArrayRef<Metadata *> Ops)
860864
: DIType(C, ID, Storage, Tag, 0, AlignInBits, NumExtraInhabitants, Flags,
861865
Ops),
862-
Encoding(Encoding) {}
866+
Encoding(Encoding), DataSizeInBits(DataSizeInBits) {}
863867
~DIBasicType() = default;
864868

865869
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
866870
StringRef Name, uint64_t SizeInBits,
867871
uint32_t AlignInBits, unsigned Encoding,
868-
uint32_t NumExtraInhabitants, DIFlags Flags,
872+
uint32_t NumExtraInhabitants,
873+
uint32_t DataSizeInBits, DIFlags Flags,
869874
StorageType Storage, bool ShouldCreate = true) {
870875
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
871876
SizeInBits, AlignInBits, Encoding, NumExtraInhabitants,
872-
Flags, Storage, ShouldCreate);
877+
DataSizeInBits, Flags, Storage, ShouldCreate);
873878
}
874879
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
875880
MDString *Name, uint64_t SizeInBits,
876881
uint32_t AlignInBits, unsigned Encoding,
877-
uint32_t NumExtraInhabitants, DIFlags Flags,
882+
uint32_t NumExtraInhabitants,
883+
uint32_t DataSizeInBits, DIFlags Flags,
878884
StorageType Storage, bool ShouldCreate = true) {
879885
auto *SizeInBitsNode = ConstantAsMetadata::get(
880886
ConstantInt::get(Type::getInt64Ty(Context), SizeInBits));
881887
return getImpl(Context, Tag, Name, SizeInBitsNode, AlignInBits, Encoding,
882-
NumExtraInhabitants, Flags, Storage, ShouldCreate);
888+
NumExtraInhabitants, DataSizeInBits, Flags, Storage,
889+
ShouldCreate);
883890
}
884-
LLVM_ABI static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
885-
MDString *Name, Metadata *SizeInBits,
886-
uint32_t AlignInBits, unsigned Encoding,
887-
uint32_t NumExtraInhabitants,
888-
DIFlags Flags, StorageType Storage,
889-
bool ShouldCreate = true);
891+
LLVM_ABI static DIBasicType *
892+
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name,
893+
Metadata *SizeInBits, uint32_t AlignInBits, unsigned Encoding,
894+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits, DIFlags Flags,
895+
StorageType Storage, bool ShouldCreate = true);
890896

891897
TempDIBasicType cloneImpl() const {
892898
return getTemporary(getContext(), getTag(), getRawName(),
893899
getRawSizeInBits(), getAlignInBits(), getEncoding(),
894-
getNumExtraInhabitants(), getFlags());
900+
getNumExtraInhabitants(), getDataSizeInBits(),
901+
getFlags());
895902
}
896903

897904
public:
898905
DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
899-
(Tag, Name, 0, 0, 0, 0, FlagZero))
906+
(Tag, Name, 0, 0, 0, 0, 0, FlagZero))
900907
DEFINE_MDNODE_GET(DIBasicType,
901908
(unsigned Tag, StringRef Name, uint64_t SizeInBits),
902-
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
909+
(Tag, Name, SizeInBits, 0, 0, 0, 0, FlagZero))
903910
DEFINE_MDNODE_GET(DIBasicType,
904911
(unsigned Tag, MDString *Name, uint64_t SizeInBits),
905-
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
912+
(Tag, Name, SizeInBits, 0, 0, 0, 0, FlagZero))
906913
DEFINE_MDNODE_GET(DIBasicType,
907914
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
908915
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
909-
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, Flags))
916+
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, 0, Flags))
910917
DEFINE_MDNODE_GET(DIBasicType,
911918
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
912919
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
913-
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, Flags))
920+
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, 0, Flags))
914921
DEFINE_MDNODE_GET(DIBasicType,
915922
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
916923
uint32_t AlignInBits, unsigned Encoding,
917924
uint32_t NumExtraInhabitants, DIFlags Flags),
918925
(Tag, Name, SizeInBits, AlignInBits, Encoding,
919-
NumExtraInhabitants, Flags))
926+
NumExtraInhabitants, 0, Flags))
927+
DEFINE_MDNODE_GET(DIBasicType,
928+
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
929+
uint32_t AlignInBits, unsigned Encoding,
930+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
931+
DIFlags Flags),
932+
(Tag, Name, SizeInBits, AlignInBits, Encoding,
933+
NumExtraInhabitants, DataSizeInBits, Flags))
920934
DEFINE_MDNODE_GET(DIBasicType,
921935
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
922936
uint32_t AlignInBits, unsigned Encoding,
923-
uint32_t NumExtraInhabitants, DIFlags Flags),
937+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
938+
DIFlags Flags),
924939
(Tag, Name, SizeInBits, AlignInBits, Encoding,
925-
NumExtraInhabitants, Flags))
940+
NumExtraInhabitants, DataSizeInBits, Flags))
926941
DEFINE_MDNODE_GET(DIBasicType,
927942
(unsigned Tag, MDString *Name, Metadata *SizeInBits,
928943
uint32_t AlignInBits, unsigned Encoding,
929-
uint32_t NumExtraInhabitants, DIFlags Flags),
944+
uint32_t NumExtraInhabitants, uint32_t DataSizeInBits,
945+
DIFlags Flags),
930946
(Tag, Name, SizeInBits, AlignInBits, Encoding,
931-
NumExtraInhabitants, Flags))
947+
NumExtraInhabitants, DataSizeInBits, Flags))
932948

933949
TempDIBasicType clone() const { return cloneImpl(); }
934950

935951
unsigned getEncoding() const { return Encoding; }
936952

953+
uint32_t getDataSizeInBits() const { return DataSizeInBits; }
954+
937955
enum class Signedness { Signed, Unsigned };
938956

939957
/// Return the signedness of this type, or std::nullopt if this type is
@@ -963,7 +981,7 @@ class DIFixedPointType : public DIBasicType {
963981
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
964982
unsigned Kind, int Factor, ArrayRef<Metadata *> Ops)
965983
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, AlignInBits,
966-
Encoding, 0, Flags, Ops),
984+
Encoding, 0, 0, Flags, Ops),
967985
Kind(Kind), Factor(Factor) {
968986
assert(Kind == FixedPointBinary || Kind == FixedPointDecimal);
969987
}
@@ -972,7 +990,7 @@ class DIFixedPointType : public DIBasicType {
972990
unsigned Kind, APInt Numerator, APInt Denominator,
973991
ArrayRef<Metadata *> Ops)
974992
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, AlignInBits,
975-
Encoding, 0, Flags, Ops),
993+
Encoding, 0, 0, Flags, Ops),
976994
Kind(Kind), Factor(0), Numerator(Numerator), Denominator(Denominator) {
977995
assert(Kind == FixedPointRational);
978996
}
@@ -981,7 +999,7 @@ class DIFixedPointType : public DIBasicType {
981999
unsigned Kind, int Factor, APInt Numerator,
9821000
APInt Denominator, ArrayRef<Metadata *> Ops)
9831001
: DIBasicType(C, DIFixedPointTypeKind, Storage, Tag, AlignInBits,
984-
Encoding, 0, Flags, Ops),
1002+
Encoding, 0, 0, Flags, Ops),
9851003
Kind(Kind), Factor(Factor), Numerator(Numerator),
9861004
Denominator(Denominator) {}
9871005
~DIFixedPointType() = default;

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5574,16 +5574,17 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
55745574
OPTIONAL(name, MDStringField, ); \
55755575
OPTIONAL(size, MDUnsignedOrMDField, (0, UINT64_MAX)); \
55765576
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
5577+
OPTIONAL(dataSize, MDUnsignedField, (0, UINT32_MAX)); \
55775578
OPTIONAL(encoding, DwarfAttEncodingField, ); \
55785579
OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX)); \
55795580
OPTIONAL(flags, DIFlagField, );
55805581
PARSE_MD_FIELDS();
55815582
#undef VISIT_MD_FIELDS
55825583

5583-
Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val,
5584-
size.getValueAsMetadata(Context),
5585-
align.Val, encoding.Val,
5586-
num_extra_inhabitants.Val, flags.Val));
5584+
Result = GET_OR_DISTINCT(
5585+
DIBasicType,
5586+
(Context, tag.Val, name.Val, size.getValueAsMetadata(Context), align.Val,
5587+
encoding.Val, num_extra_inhabitants.Val, dataSize.Val, flags.Val));
55875588
return false;
55885589
}
55895590

llvm/lib/Bitcode/Reader/MetadataLoader.cpp

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

15411541
IsDistinct = Record[0] & 1;
@@ -1544,13 +1544,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
15441544
? static_cast<DINode::DIFlags>(Record[6])
15451545
: DINode::FlagZero;
15461546
uint32_t NumExtraInhabitants = (Record.size() > 7) ? Record[7] : 0;
1547-
1547+
uint32_t DataSizeInBits = (Record.size() > 8) ? Record[8] : 0;
15481548
Metadata *SizeInBits = getMetadataOrConstant(SizeIsMetadata, Record[3]);
1549-
15501549
MetadataList.assignValue(
15511550
GET_OR_DISTINCT(DIBasicType,
15521551
(Context, Record[1], getMDString(Record[2]), SizeInBits,
1553-
Record[4], Record[5], NumExtraInhabitants, Flags)),
1552+
Record[4], Record[5], NumExtraInhabitants,
1553+
DataSizeInBits, Flags)),
15541554
NextMetadataNo);
15551555
NextMetadataNo++;
15561556
break;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,7 @@ void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N,
19211921
Record.push_back(N->getEncoding());
19221922
Record.push_back(N->getFlags());
19231923
Record.push_back(N->getNumExtraInhabitants());
1924+
Record.push_back(N->getDataSizeInBits());
19241925

19251926
Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev);
19261927
Record.clear();

llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1767,9 +1767,13 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
17671767
"_" + Twine(Btr.BitSize)).toStringRef(Str));
17681768
addUInt(Die, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Btr.Encoding);
17691769
// Round up to smallest number of bytes that contains this number of bits.
1770+
// ExprRefedBaseTypes is populated with types referenced by
1771+
// DW_OP_LLVM_convert operations in location expressions. These are often
1772+
// byte-sized, but one common counter-example is 1-bit sized conversions
1773+
// from `i1` types. TODO: Should these use DW_AT_bit_size? See
1774+
// DwarfUnit::constructTypeDIE.
17701775
addUInt(Die, dwarf::DW_AT_byte_size, std::nullopt,
17711776
divideCeil(Btr.BitSize, 8));
1772-
17731777
Btr.Die = &Die;
17741778
}
17751779
}

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

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

757-
uint64_t Size = BTy->getSizeInBits() >> 3;
758-
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, Size);
757+
uint64_t SizeInBytes = divideCeil(BTy->getSizeInBits(), 8);
758+
addUInt(Buffer, dwarf::DW_AT_byte_size, std::nullopt, SizeInBytes);
759+
if (BTy->getTag() == dwarf::Tag::DW_TAG_base_type) {
760+
// DW_TAG_base_type:
761+
// If the value of an object of the given type does not fully occupy the
762+
// storage described by a byte size attribute, the base type entry may also
763+
// have a DW_AT_bit_size [...] attribute.
764+
// TODO: Do big endian targets need DW_AT_data_bit_offset? See discussion in
765+
// pull request #164372.
766+
if (uint64_t DataSizeInBits = BTy->getDataSizeInBits();
767+
DataSizeInBits && DataSizeInBits != SizeInBytes * 8)
768+
addUInt(Buffer, dwarf::DW_AT_bit_size, std::nullopt, DataSizeInBits);
769+
}
759770

760771
if (BTy->isBigEndian())
761772
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
@@ -2235,6 +2235,7 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
22352235
Printer.printString("name", N->getName());
22362236
Printer.printMetadataOrInt("size", N->getRawSizeInBits(), true);
22372237
Printer.printInt("align", N->getAlignInBits());
2238+
Printer.printInt("dataSize", N->getDataSizeInBits());
22382239
Printer.printDwarfEnum("encoding", N->getEncoding(),
22392240
dwarf::AttributeEncodingString);
22402241
Printer.printInt("num_extra_inhabitants", N->getNumExtraInhabitants());

0 commit comments

Comments
 (0)