Skip to content

Commit 7db0516

Browse files
committed
[DebugInfo] Add num_extra_inhabitants to debug info
An extra inhabitant is a bit pattern that does not represent a valid value for instances of a given type. The number of extra inhabitants is the number of those bit configurations. This is used by Swift to save space when composing types. For example, because Bool only needs 2 bit patterns to represent all of its values (true and false), an Optional<Bool> only occupies 1 byte in memory by using a bit configuration that is unused by Bool. Which bit patterns are unused are part of the ABI of the language. Since Swift generics are not monomorphized, by using dynamic libraries you can have generic types whose size, alignment, etc, are known only at runtime (which is why this feature is needed). This patch adds num_extra_inhabitants to LLVM-IR debug info and in DWARF as an Apple extension.
1 parent 6ab26ea commit 7db0516

File tree

15 files changed

+280
-158
lines changed

15 files changed

+280
-158
lines changed

llvm/include/llvm/BinaryFormat/Dwarf.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ HANDLE_DW_AT(0x3fed, APPLE_property, 0, APPLE)
636636
HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
637637
HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
638638
HANDLE_DW_AT(0x3ff0, APPLE_origin, 0, APPLE)
639+
HANDLE_DW_AT(0x3ff1, APPLE_num_extra_inhabitants, 0, APPLE)
639640

640641
// Attribute form encodings.
641642
HANDLE_DW_FORM(0x01, addr, 2, DWARF)

llvm/include/llvm/IR/DIBuilder.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,13 @@ namespace llvm {
225225
/// \param SizeInBits Size of the type.
226226
/// \param Encoding DWARF encoding code, e.g., dwarf::DW_ATE_float.
227227
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
228+
/// \param NumExtraInhabitants The number of extra inhabitants of the type.
229+
/// An extra inhabitant is a bit pattern that does not represent a valid
230+
/// value for instances of a given type.
228231
DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits,
229232
unsigned Encoding,
230-
DINode::DIFlags Flags = DINode::FlagZero);
233+
DINode::DIFlags Flags = DINode::FlagZero,
234+
uint32_t NumExtraInhabitants = 0);
231235

232236
/// Create debugging information entry for a string
233237
/// type.
@@ -484,11 +488,15 @@ namespace llvm {
484488
/// \param Elements Struct elements.
485489
/// \param RunTimeLang Optional parameter, Objective-C runtime version.
486490
/// \param UniqueIdentifier A unique identifier for the struct.
491+
/// \param NumExtraInhabitants The number of extra inhabitants of the type.
492+
/// An extra inhabitant is a bit pattern that does not represent a valid
493+
/// value for instances of a given type.
487494
DICompositeType *createStructType(
488495
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
489496
uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags,
490497
DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0,
491-
DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = "");
498+
DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = "",
499+
uint32_t NumExtraInhabitants = 0);
492500

493501
/// Create debugging information entry for an union.
494502
/// \param Scope Scope in which this union is defined.

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 79 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -712,31 +712,38 @@ class DIType : public DIScope {
712712
DIFlags Flags;
713713
uint64_t SizeInBits;
714714
uint64_t OffsetInBits;
715+
uint32_t NumExtraInhabitants;
715716

716717
protected:
717718
DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
718719
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
719-
uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops)
720+
uint64_t OffsetInBits, uint32_t NumExtraInhabitants, DIFlags Flags,
721+
ArrayRef<Metadata *> Ops)
720722
: DIScope(C, ID, Storage, Tag, Ops) {
721-
init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
723+
init(Line, SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants,
724+
Flags);
722725
}
723726
~DIType() = default;
724727

725728
void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
726-
uint64_t OffsetInBits, DIFlags Flags) {
729+
uint64_t OffsetInBits, uint32_t NumExtraInhabitants,
730+
DIFlags Flags) {
727731
this->Line = Line;
728732
this->Flags = Flags;
729733
this->SizeInBits = SizeInBits;
730734
this->SubclassData32 = AlignInBits;
731735
this->OffsetInBits = OffsetInBits;
736+
this->NumExtraInhabitants = NumExtraInhabitants;
732737
}
733738

734739
/// Change fields in place.
735740
void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits,
736-
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) {
741+
uint32_t AlignInBits, uint64_t OffsetInBits,
742+
uint32_t NumExtraInhabitants, DIFlags Flags) {
737743
assert(isDistinct() && "Only distinct nodes can mutate");
738744
setTag(Tag);
739-
init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
745+
init(Line, SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants,
746+
Flags);
740747
}
741748

742749
public:
@@ -749,6 +756,7 @@ class DIType : public DIScope {
749756
uint32_t getAlignInBits() const;
750757
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
751758
uint64_t getOffsetInBits() const { return OffsetInBits; }
759+
uint32_t getNumExtraInhabitants() const { return NumExtraInhabitants; }
752760
DIFlags getFlags() const { return Flags; }
753761

754762
DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
@@ -820,49 +828,63 @@ class DIBasicType : public DIType {
820828

821829
DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
822830
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
823-
DIFlags Flags, ArrayRef<Metadata *> Ops)
831+
uint32_t NumExtraInhabitants, DIFlags Flags,
832+
ArrayRef<Metadata *> Ops)
824833
: DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
825-
Flags, Ops),
834+
NumExtraInhabitants, Flags, Ops),
826835
Encoding(Encoding) {}
827836
~DIBasicType() = default;
828837

829838
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
830839
StringRef Name, uint64_t SizeInBits,
831840
uint32_t AlignInBits, unsigned Encoding,
832-
DIFlags Flags, StorageType Storage,
833-
bool ShouldCreate = true) {
841+
uint32_t NumExtraInhabitants, DIFlags Flags,
842+
StorageType Storage, bool ShouldCreate = true) {
834843
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
835-
SizeInBits, AlignInBits, Encoding, Flags, Storage,
836-
ShouldCreate);
844+
SizeInBits, AlignInBits, Encoding, NumExtraInhabitants,
845+
Flags, Storage, ShouldCreate);
837846
}
838847
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
839848
MDString *Name, uint64_t SizeInBits,
840849
uint32_t AlignInBits, unsigned Encoding,
841-
DIFlags Flags, StorageType Storage,
842-
bool ShouldCreate = true);
850+
uint32_t NumExtraInhabitants, DIFlags Flags,
851+
StorageType Storage, bool ShouldCreate = true);
843852

844853
TempDIBasicType cloneImpl() const {
845854
return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
846-
getAlignInBits(), getEncoding(), getFlags());
855+
getAlignInBits(), getEncoding(),
856+
getNumExtraInhabitants(), getFlags());
847857
}
848858

849859
public:
850860
DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
851-
(Tag, Name, 0, 0, 0, FlagZero))
861+
(Tag, Name, 0, 0, 0, 0, FlagZero))
852862
DEFINE_MDNODE_GET(DIBasicType,
853863
(unsigned Tag, StringRef Name, uint64_t SizeInBits),
854-
(Tag, Name, SizeInBits, 0, 0, FlagZero))
864+
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
855865
DEFINE_MDNODE_GET(DIBasicType,
856866
(unsigned Tag, MDString *Name, uint64_t SizeInBits),
857-
(Tag, Name, SizeInBits, 0, 0, FlagZero))
867+
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
858868
DEFINE_MDNODE_GET(DIBasicType,
859869
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
860870
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
861-
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
871+
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, Flags))
862872
DEFINE_MDNODE_GET(DIBasicType,
863873
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
864874
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
865-
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
875+
(Tag, Name, SizeInBits, AlignInBits, Encoding, 0, Flags))
876+
DEFINE_MDNODE_GET(DIBasicType,
877+
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
878+
uint32_t AlignInBits, unsigned Encoding,
879+
uint32_t NumExtraInhabitants, DIFlags Flags),
880+
(Tag, Name, SizeInBits, AlignInBits, Encoding,
881+
NumExtraInhabitants, Flags))
882+
DEFINE_MDNODE_GET(DIBasicType,
883+
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
884+
uint32_t AlignInBits, unsigned Encoding,
885+
uint32_t NumExtraInhabitants, DIFlags Flags),
886+
(Tag, Name, SizeInBits, AlignInBits, Encoding,
887+
NumExtraInhabitants, Flags))
866888

867889
TempDIBasicType clone() const { return cloneImpl(); }
868890

@@ -890,7 +912,7 @@ class DIStringType : public DIType {
890912
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
891913
ArrayRef<Metadata *> Ops)
892914
: DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
893-
FlagZero, Ops),
915+
0, FlagZero, Ops),
894916
Encoding(Encoding) {}
895917
~DIStringType() = default;
896918

@@ -1016,7 +1038,7 @@ class DIDerivedType : public DIType {
10161038
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
10171039
ArrayRef<Metadata *> Ops)
10181040
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
1019-
AlignInBits, OffsetInBits, Flags, Ops),
1041+
AlignInBits, OffsetInBits, 0, Flags, Ops),
10201042
DWARFAddressSpace(DWARFAddressSpace) {
10211043
if (PtrAuthData)
10221044
SubclassData32 = PtrAuthData->RawData;
@@ -1157,39 +1179,43 @@ class DICompositeType : public DIType {
11571179

11581180
DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag,
11591181
unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits,
1160-
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
1182+
uint32_t AlignInBits, uint64_t OffsetInBits,
1183+
uint32_t NumExtraInhabitants, DIFlags Flags,
11611184
ArrayRef<Metadata *> Ops)
11621185
: DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits,
1163-
AlignInBits, OffsetInBits, Flags, Ops),
1186+
AlignInBits, OffsetInBits, NumExtraInhabitants, Flags, Ops),
11641187
RuntimeLang(RuntimeLang) {}
11651188
~DICompositeType() = default;
11661189

11671190
/// Change fields in place.
11681191
void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang,
11691192
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
1170-
DIFlags Flags) {
1193+
uint32_t NumExtraInhabitants, DIFlags Flags) {
11711194
assert(isDistinct() && "Only distinct nodes can mutate");
11721195
assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate");
11731196
this->RuntimeLang = RuntimeLang;
1174-
DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
1197+
DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
1198+
NumExtraInhabitants, Flags);
11751199
}
11761200

11771201
static DICompositeType *
11781202
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
11791203
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
1180-
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
1181-
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
1204+
uint32_t AlignInBits, uint64_t OffsetInBits,
1205+
uint32_t NumExtraInhabitants, DIFlags Flags, DINodeArray Elements,
1206+
unsigned RuntimeLang, DIType *VTableHolder,
11821207
DITemplateParameterArray TemplateParams, StringRef Identifier,
11831208
DIDerivedType *Discriminator, Metadata *DataLocation,
11841209
Metadata *Associated, Metadata *Allocated, Metadata *Rank,
11851210
DINodeArray Annotations, StorageType Storage,
11861211
bool ShouldCreate = true) {
1187-
return getImpl(
1188-
Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
1189-
BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
1190-
RuntimeLang, VTableHolder, TemplateParams.get(),
1191-
getCanonicalMDString(Context, Identifier), Discriminator, DataLocation,
1192-
Associated, Allocated, Rank, Annotations.get(), Storage, ShouldCreate);
1212+
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
1213+
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
1214+
Flags, Elements.get(), RuntimeLang, VTableHolder,
1215+
TemplateParams.get(),
1216+
getCanonicalMDString(Context, Identifier), Discriminator,
1217+
DataLocation, Associated, Allocated, Rank, Annotations.get(),
1218+
NumExtraInhabitants, Storage, ShouldCreate);
11931219
}
11941220
static DICompositeType *
11951221
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@@ -1199,7 +1225,8 @@ class DICompositeType : public DIType {
11991225
Metadata *VTableHolder, Metadata *TemplateParams,
12001226
MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
12011227
Metadata *Associated, Metadata *Allocated, Metadata *Rank,
1202-
Metadata *Annotations, StorageType Storage, bool ShouldCreate = true);
1228+
Metadata *Annotations, uint32_t NumExtraInhabitants,
1229+
StorageType Storage, bool ShouldCreate = true);
12031230

12041231
TempDICompositeType cloneImpl() const {
12051232
return getTemporary(
@@ -1208,7 +1235,7 @@ class DICompositeType : public DIType {
12081235
getFlags(), getElements(), getRuntimeLang(), getVTableHolder(),
12091236
getTemplateParams(), getIdentifier(), getDiscriminator(),
12101237
getRawDataLocation(), getRawAssociated(), getRawAllocated(),
1211-
getRawRank(), getAnnotations());
1238+
getRawRank(), getAnnotations(), getNumExtraInhabitants());
12121239
}
12131240

12141241
public:
@@ -1222,11 +1249,11 @@ class DICompositeType : public DIType {
12221249
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
12231250
Metadata *DataLocation = nullptr, Metadata *Associated = nullptr,
12241251
Metadata *Allocated = nullptr, Metadata *Rank = nullptr,
1225-
DINodeArray Annotations = nullptr),
1252+
DINodeArray Annotations = nullptr, uint32_t NumExtraInhabitants = 0),
12261253
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
1227-
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
1228-
Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,
1229-
Annotations))
1254+
OffsetInBits, NumExtraInhabitants, Flags, Elements, RuntimeLang,
1255+
VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation,
1256+
Associated, Allocated, Rank, Annotations))
12301257
DEFINE_MDNODE_GET(
12311258
DICompositeType,
12321259
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
@@ -1236,11 +1263,12 @@ class DICompositeType : public DIType {
12361263
Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr,
12371264
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr,
12381265
Metadata *Associated = nullptr, Metadata *Allocated = nullptr,
1239-
Metadata *Rank = nullptr, Metadata *Annotations = nullptr),
1266+
Metadata *Rank = nullptr, Metadata *Annotations = nullptr,
1267+
uint32_t NumExtraInhabitants = 0),
12401268
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
12411269
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
12421270
Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,
1243-
Annotations))
1271+
Annotations, NumExtraInhabitants))
12441272

12451273
TempDICompositeType clone() const { return cloneImpl(); }
12461274

@@ -1255,8 +1283,8 @@ class DICompositeType : public DIType {
12551283
getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
12561284
MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
12571285
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
1258-
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
1259-
unsigned RuntimeLang, Metadata *VTableHolder,
1286+
uint64_t OffsetInBits, uint32_t NumExtraInhabitants, DIFlags Flags,
1287+
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
12601288
Metadata *TemplateParams, Metadata *Discriminator,
12611289
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
12621290
Metadata *Rank, Metadata *Annotations);
@@ -1272,15 +1300,14 @@ class DICompositeType : public DIType {
12721300
///
12731301
/// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns
12741302
/// nullptr.
1275-
static DICompositeType *
1276-
buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
1277-
MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
1278-
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
1279-
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
1280-
unsigned RuntimeLang, Metadata *VTableHolder,
1281-
Metadata *TemplateParams, Metadata *Discriminator,
1282-
Metadata *DataLocation, Metadata *Associated,
1283-
Metadata *Allocated, Metadata *Rank, Metadata *Annotations);
1303+
static DICompositeType *buildODRType(
1304+
LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
1305+
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
1306+
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
1307+
uint32_t NumExtraInhabitants, DIFlags Flags, Metadata *Elements,
1308+
unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams,
1309+
Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated,
1310+
Metadata *Allocated, Metadata *Rank, Metadata *Annotations);
12841311

12851312
DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
12861313
DINodeArray getElements() const {

0 commit comments

Comments
 (0)