Skip to content

Commit

Permalink
[DebugInfo] Add num_extra_inhabitants to debug info
Browse files Browse the repository at this point in the history
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.

This patch adds num_extra_inhabitants to LLVM-IR debug info and in DWARF
as an Apple extension.
  • Loading branch information
augusto2112 committed Oct 16, 2024
1 parent 76173b1 commit bef3e90
Show file tree
Hide file tree
Showing 15 changed files with 246 additions and 141 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/BinaryFormat/Dwarf.def
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ HANDLE_DW_AT(0x3fed, APPLE_property, 0, APPLE)
HANDLE_DW_AT(0x3fee, APPLE_objc_direct, 0, APPLE)
HANDLE_DW_AT(0x3fef, APPLE_sdk, 0, APPLE)
HANDLE_DW_AT(0x3ff0, APPLE_origin, 0, APPLE)
HANDLE_DW_AT(0x3ff1, APPLE_num_extra_inhabitants, 0, APPLE)

// Attribute form encodings.
HANDLE_DW_FORM(0x01, addr, 2, DWARF)
Expand Down
12 changes: 10 additions & 2 deletions llvm/include/llvm/IR/DIBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,13 @@ namespace llvm {
/// \param SizeInBits Size of the type.
/// \param Encoding DWARF encoding code, e.g., dwarf::DW_ATE_float.
/// \param Flags Optional DWARF attributes, e.g., DW_AT_endianity.
/// \param NumExtraInhabitants The number of extra inhabitants of the type.
/// An extra inhabitant is a bit pattern that does not represent a valid
/// value for instances of a given type.
DIBasicType *createBasicType(StringRef Name, uint64_t SizeInBits,
unsigned Encoding,
DINode::DIFlags Flags = DINode::FlagZero);
DINode::DIFlags Flags = DINode::FlagZero,
uint32_t NumExtraInhabitants = 0);

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

/// Create debugging information entry for an union.
/// \param Scope Scope in which this union is defined.
Expand Down
127 changes: 73 additions & 54 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -712,31 +712,38 @@ class DIType : public DIScope {
DIFlags Flags;
uint64_t SizeInBits;
uint64_t OffsetInBits;
uint32_t NumExtraInhabitants;

protected:
DIType(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag,
unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, ArrayRef<Metadata *> Ops)
uint64_t OffsetInBits, uint32_t NumExtraInhabitants, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIScope(C, ID, Storage, Tag, Ops) {
init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
init(Line, SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants,
Flags);
}
~DIType() = default;

void init(unsigned Line, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags) {
uint64_t OffsetInBits, uint32_t NumExtraInhabitants,
DIFlags Flags) {
this->Line = Line;
this->Flags = Flags;
this->SizeInBits = SizeInBits;
this->SubclassData32 = AlignInBits;
this->OffsetInBits = OffsetInBits;
this->NumExtraInhabitants = NumExtraInhabitants;
}

/// Change fields in place.
void mutate(unsigned Tag, unsigned Line, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags) {
uint32_t AlignInBits, uint64_t OffsetInBits,
uint32_t NumExtraInhabitants, DIFlags Flags) {
assert(isDistinct() && "Only distinct nodes can mutate");
setTag(Tag);
init(Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
init(Line, SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants,
Flags);
}

public:
Expand All @@ -749,6 +756,7 @@ class DIType : public DIScope {
uint32_t getAlignInBits() const;
uint32_t getAlignInBytes() const { return getAlignInBits() / CHAR_BIT; }
uint64_t getOffsetInBits() const { return OffsetInBits; }
uint32_t getNumExtraInhabitants() const { return NumExtraInhabitants; }
DIFlags getFlags() const { return Flags; }

DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); }
Expand Down Expand Up @@ -820,49 +828,55 @@ class DIBasicType : public DIType {

DIBasicType(LLVMContext &C, StorageType Storage, unsigned Tag,
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, ArrayRef<Metadata *> Ops)
uint32_t NumExtraInhabitants, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIType(C, DIBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
Flags, Ops),
NumExtraInhabitants, Flags, Ops),
Encoding(Encoding) {}
~DIBasicType() = default;

static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, StorageType Storage,
bool ShouldCreate = true) {
uint32_t NumExtraInhabitants, DIFlags Flags,
StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
SizeInBits, AlignInBits, Encoding, Flags, Storage,
ShouldCreate);
SizeInBits, AlignInBits, Encoding, NumExtraInhabitants,
Flags, Storage, ShouldCreate);
}
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
MDString *Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
DIFlags Flags, StorageType Storage,
bool ShouldCreate = true);
uint32_t NumExtraInhabitants, DIFlags Flags,
StorageType Storage, bool ShouldCreate = true);

TempDIBasicType cloneImpl() const {
return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
getAlignInBits(), getEncoding(), getFlags());
getAlignInBits(), getEncoding(),
getNumExtraInhabitants(), getFlags());
}

public:
DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
(Tag, Name, 0, 0, 0, FlagZero))
(Tag, Name, 0, 0, 0, 0, FlagZero))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, StringRef Name, uint64_t SizeInBits),
(Tag, Name, SizeInBits, 0, 0, FlagZero))
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, MDString *Name, uint64_t SizeInBits),
(Tag, Name, SizeInBits, 0, 0, FlagZero))
(Tag, Name, SizeInBits, 0, 0, 0, FlagZero))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
uint32_t AlignInBits, unsigned Encoding,
uint32_t NumExtraInhabitants, DIFlags Flags),
(Tag, Name, SizeInBits, AlignInBits, Encoding,
NumExtraInhabitants, Flags))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
(Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
uint32_t AlignInBits, unsigned Encoding,
uint32_t NumExtraInhabitants, DIFlags Flags),
(Tag, Name, SizeInBits, AlignInBits, Encoding,
NumExtraInhabitants, Flags))

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

Expand Down Expand Up @@ -890,7 +904,7 @@ class DIStringType : public DIType {
uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding,
ArrayRef<Metadata *> Ops)
: DIType(C, DIStringTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0,
FlagZero, Ops),
0, FlagZero, Ops),
Encoding(Encoding) {}
~DIStringType() = default;

Expand Down Expand Up @@ -1016,7 +1030,7 @@ class DIDerivedType : public DIType {
std::optional<PtrAuthData> PtrAuthData, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIType(C, DIDerivedTypeKind, Storage, Tag, Line, SizeInBits,
AlignInBits, OffsetInBits, Flags, Ops),
AlignInBits, OffsetInBits, 0, Flags, Ops),
DWARFAddressSpace(DWARFAddressSpace) {
if (PtrAuthData)
SubclassData32 = PtrAuthData->RawData;
Expand Down Expand Up @@ -1157,39 +1171,43 @@ class DICompositeType : public DIType {

DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag,
unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
uint32_t AlignInBits, uint64_t OffsetInBits,
uint32_t NumExtraInhabitants, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits,
AlignInBits, OffsetInBits, Flags, Ops),
AlignInBits, OffsetInBits, NumExtraInhabitants, Flags, Ops),
RuntimeLang(RuntimeLang) {}
~DICompositeType() = default;

/// Change fields in place.
void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags) {
uint32_t NumExtraInhabitants, DIFlags Flags) {
assert(isDistinct() && "Only distinct nodes can mutate");
assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate");
this->RuntimeLang = RuntimeLang;
DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags);
DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
NumExtraInhabitants, Flags);
}

static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
uint32_t AlignInBits, uint64_t OffsetInBits,
uint32_t NumExtraInhabitants, DIFlags Flags, DINodeArray Elements,
unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams, StringRef Identifier,
DIDerivedType *Discriminator, Metadata *DataLocation,
Metadata *Associated, Metadata *Allocated, Metadata *Rank,
DINodeArray Annotations, StorageType Storage,
bool ShouldCreate = true) {
return getImpl(
Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope,
BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(),
RuntimeLang, VTableHolder, TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator, DataLocation,
Associated, Allocated, Rank, Annotations.get(), Storage, ShouldCreate);
return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File,
Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits,
Flags, Elements.get(), RuntimeLang, VTableHolder,
TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator,
DataLocation, Associated, Allocated, Rank, Annotations.get(),
NumExtraInhabitants, Storage, ShouldCreate);
}
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
Expand All @@ -1199,7 +1217,8 @@ class DICompositeType : public DIType {
Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
Metadata *Associated, Metadata *Allocated, Metadata *Rank,
Metadata *Annotations, StorageType Storage, bool ShouldCreate = true);
Metadata *Annotations, uint32_t NumExtraInhabitants,
StorageType Storage, bool ShouldCreate = true);

TempDICompositeType cloneImpl() const {
return getTemporary(
Expand All @@ -1208,7 +1227,7 @@ class DICompositeType : public DIType {
getFlags(), getElements(), getRuntimeLang(), getVTableHolder(),
getTemplateParams(), getIdentifier(), getDiscriminator(),
getRawDataLocation(), getRawAssociated(), getRawAllocated(),
getRawRank(), getAnnotations());
getRawRank(), getAnnotations(), getNumExtraInhabitants());
}

public:
Expand All @@ -1222,11 +1241,11 @@ class DICompositeType : public DIType {
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
Metadata *DataLocation = nullptr, Metadata *Associated = nullptr,
Metadata *Allocated = nullptr, Metadata *Rank = nullptr,
DINodeArray Annotations = nullptr),
DINodeArray Annotations = nullptr, uint32_t NumExtraInhabitants = 0),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,
Annotations))
OffsetInBits, NumExtraInhabitants, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation,
Associated, Allocated, Rank, Annotations))
DEFINE_MDNODE_GET(
DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
Expand All @@ -1236,11 +1255,12 @@ class DICompositeType : public DIType {
Metadata *TemplateParams = nullptr, MDString *Identifier = nullptr,
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr,
Metadata *Associated = nullptr, Metadata *Allocated = nullptr,
Metadata *Rank = nullptr, Metadata *Annotations = nullptr),
Metadata *Rank = nullptr, Metadata *Annotations = nullptr,
uint32_t NumExtraInhabitants = 0),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,
Annotations))
Annotations, NumExtraInhabitants))

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

Expand All @@ -1255,8 +1275,8 @@ class DICompositeType : public DIType {
getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
uint64_t OffsetInBits, uint32_t NumExtraInhabitants, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
Metadata *Rank, Metadata *Annotations);
Expand All @@ -1272,15 +1292,14 @@ class DICompositeType : public DIType {
///
/// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns
/// nullptr.
static DICompositeType *
buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated,
Metadata *Allocated, Metadata *Rank, Metadata *Annotations);
static DICompositeType *buildODRType(
LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
uint32_t NumExtraInhabitants, DIFlags Flags, Metadata *Elements,
unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams,
Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated,
Metadata *Allocated, Metadata *Rank, Metadata *Annotations);

DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
DINodeArray getElements() const {
Expand Down
18 changes: 11 additions & 7 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5329,12 +5329,14 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
OPTIONAL(encoding, DwarfAttEncodingField, ); \
OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX)); \
OPTIONAL(flags, DIFlagField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val,
align.Val, encoding.Val, flags.Val));
align.Val, encoding.Val,
num_extra_inhabitants.Val, flags.Val));
return false;
}

Expand Down Expand Up @@ -5432,7 +5434,8 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(associated, MDField, ); \
OPTIONAL(allocated, MDField, ); \
OPTIONAL(rank, MDSignedOrMDField, ); \
OPTIONAL(annotations, MDField, );
OPTIONAL(annotations, MDField, ); \
OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX));
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS

Expand All @@ -5447,10 +5450,11 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
if (identifier.Val)
if (auto *CT = DICompositeType::buildODRType(
Context, *identifier.Val, tag.Val, name.Val, file.Val, line.Val,
scope.Val, baseType.Val, size.Val, align.Val, offset.Val, flags.Val,
elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val,
discriminator.Val, dataLocation.Val, associated.Val, allocated.Val,
Rank, annotations.Val)) {
scope.Val, baseType.Val, size.Val, align.Val, offset.Val,
num_extra_inhabitants.Val, flags.Val, elements.Val, runtimeLang.Val,
vtableHolder.Val, templateParams.Val, discriminator.Val,
dataLocation.Val, associated.Val, allocated.Val, Rank,
annotations.Val)) {
Result = CT;
return false;
}
Expand All @@ -5463,7 +5467,7 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
size.Val, align.Val, offset.Val, flags.Val, elements.Val,
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, Rank,
annotations.Val));
annotations.Val, num_extra_inhabitants.Val));
return false;
}

Expand Down
Loading

0 comments on commit bef3e90

Please sign in to comment.