-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[llvm][DebugInfo] Add new DW_AT_APPLE_enum_kind to encode enum_extensibility #124752
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[llvm][DebugInfo] Add new DW_AT_APPLE_enum_kind to encode enum_extensibility #124752
Conversation
(hmm, can't use the foundation library on godbolt/compiler explorer) |
Here are all the
So nothing about the extensibility is reflected here |
Is my thing about the ctor understanding correct, and it's that the ctor exists theoretically/abstractly, but not in the AST or in the generated IR/DWARF? Could it be added/would that be sufficient? But, yeah, probably fine to just add the attribute, since that's the real feature you want to know about. |
Hmmm this is what the AST looks like:
So yea no sign of a constructor, in either AST, IR or DWARF. So it does sound more like a hypothetical construct than something that is modelled in Clang (looking at how the |
I've only included the LLVM changes here now (anything metadata and DWARF attribute related). Will do the plumbing from the frontend in a separate patch |
@llvm/pr-subscribers-mlir @llvm/pr-subscribers-debuginfo Author: Michael Buch (Michael137) ChangesWhen creating To speed up Swift exression evaluation, this patch proposes encoding the C/C++/Objective-C I'm open to naming suggestions of the various new attributes/attribute constants proposed here. I tried to be as generic as possible if we wanted to extend it to other kinds of enum properties (e.g., flag enums). The new attribute would look as follows:
Absence of the attribute means the extensibility of the enum is unknown and abides by whatever the language rules of that CU dictate. This does feel like a big hammer for quite a specific use-case, so I'm happy to discuss alternatives. Alternatives considered:
Patch is 74.52 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124752.diff 19 Files Affected:
diff --git a/llvm/include/llvm/AsmParser/LLToken.h b/llvm/include/llvm/AsmParser/LLToken.h
index 7b47bc88ddb25f..c52622879b885e 100644
--- a/llvm/include/llvm/AsmParser/LLToken.h
+++ b/llvm/include/llvm/AsmParser/LLToken.h
@@ -497,6 +497,7 @@ enum Kind {
DwarfMacinfo, // DW_MACINFO_foo
ChecksumKind, // CSK_foo
DbgRecordType, // dbg_foo
+ DwarfEnumKind, // DW_APPLE_ENUM_KIND_foo
// Type valued tokens (TyVal).
Type,
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def
index 2bb84fbc864d8e..724a14ccc7aeaf 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.def
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.def
@@ -24,7 +24,8 @@
(defined HANDLE_DW_CFA && defined HANDLE_DW_CFA_PRED) || \
defined HANDLE_DW_APPLE_PROPERTY || defined HANDLE_DW_UT || \
defined HANDLE_DWARF_SECTION || defined HANDLE_DW_IDX || \
- defined HANDLE_DW_END || defined HANDLE_DW_SECT)
+ defined HANDLE_DW_END || defined HANDLE_DW_SECT || \
+ defined HANDLE_DW_APPLE_ENUM_KIND)
#error "Missing macro definition of HANDLE_DW*"
#endif
@@ -146,6 +147,10 @@
#define HANDLE_DW_SECT(ID, NAME)
#endif
+#ifndef HANDLE_DW_APPLE_ENUM_KIND
+#define HANDLE_DW_APPLE_ENUM_KIND(ID, NAME)
+#endif
+
HANDLE_DW_TAG(0x0000, null, 2, DWARF, DW_KIND_NONE)
HANDLE_DW_TAG(0x0001, array_type, 2, DWARF, DW_KIND_TYPE)
HANDLE_DW_TAG(0x0002, class_type, 2, DWARF, DW_KIND_TYPE)
@@ -638,6 +643,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_enum_kind, 0, APPLE)
// Attribute form encodings.
HANDLE_DW_FORM(0x01, addr, 2, DWARF)
@@ -1269,6 +1275,11 @@ HANDLE_DW_APPLE_PROPERTY(0x1000, nullability)
HANDLE_DW_APPLE_PROPERTY(0x2000, null_resettable)
HANDLE_DW_APPLE_PROPERTY(0x4000, class)
+// Enum kinds.
+// Keep in sync with EnumExtensibilityAttr::Kind.
+HANDLE_DW_APPLE_ENUM_KIND(0x00, Closed)
+HANDLE_DW_APPLE_ENUM_KIND(0x01, Open)
+
// DWARF v5 Unit Types.
HANDLE_DW_UT(0x01, compile)
HANDLE_DW_UT(0x02, type)
@@ -1367,3 +1378,4 @@ HANDLE_DW_SECT(8, RNGLISTS)
#undef HANDLE_DW_IDX
#undef HANDLE_DW_END
#undef HANDLE_DW_SECT
+#undef HANDLE_DW_APPLE_ENUM_KIND
diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.h b/llvm/include/llvm/BinaryFormat/Dwarf.h
index 3be819c0a76eeb..397b4b164386d8 100644
--- a/llvm/include/llvm/BinaryFormat/Dwarf.h
+++ b/llvm/include/llvm/BinaryFormat/Dwarf.h
@@ -44,9 +44,10 @@ namespace dwarf {
enum LLVMConstants : uint32_t {
/// LLVM mock tags (see also llvm/BinaryFormat/Dwarf.def).
/// \{
- DW_TAG_invalid = ~0U, ///< Tag for invalid results.
- DW_VIRTUALITY_invalid = ~0U, ///< Virtuality for invalid results.
- DW_MACINFO_invalid = ~0U, ///< Macinfo type for invalid results.
+ DW_TAG_invalid = ~0U, ///< Tag for invalid results.
+ DW_VIRTUALITY_invalid = ~0U, ///< Virtuality for invalid results.
+ DW_MACINFO_invalid = ~0U, ///< Macinfo type for invalid results.
+ DW_APPLE_ENUM_KIND_invalid = ~0U, ///< Enum kind for invalid results.
/// \}
/// Special values for an initial length field.
@@ -198,6 +199,12 @@ enum VirtualityAttribute {
DW_VIRTUALITY_max = 0x02
};
+enum EnumKindAttribute {
+#define HANDLE_DW_APPLE_ENUM_KIND(ID, NAME) DW_APPLE_ENUM_KIND_##NAME = ID,
+#include "llvm/BinaryFormat/Dwarf.def"
+ DW_APPLE_ENUM_KIND_max = 0x01
+};
+
enum DefaultedMemberAttribute {
#define HANDLE_DW_DEFAULTED(ID, NAME) DW_DEFAULTED_##NAME = ID,
#include "llvm/BinaryFormat/Dwarf.def"
@@ -981,6 +988,7 @@ StringRef AccessibilityString(unsigned Access);
StringRef DefaultedMemberString(unsigned DefaultedEncodings);
StringRef VisibilityString(unsigned Visibility);
StringRef VirtualityString(unsigned Virtuality);
+StringRef EnumKindString(unsigned EnumKind);
StringRef LanguageString(unsigned Language);
StringRef CaseString(unsigned Case);
StringRef ConventionString(unsigned Convention);
@@ -1020,6 +1028,7 @@ unsigned getOperationEncoding(StringRef OperationEncodingString);
unsigned getSubOperationEncoding(unsigned OpEncoding,
StringRef SubOperationEncodingString);
unsigned getVirtuality(StringRef VirtualityString);
+unsigned getEnumKind(StringRef EnumKindString);
unsigned getLanguage(StringRef LanguageString);
unsigned getCallingConvention(StringRef LanguageString);
unsigned getAttributeEncoding(StringRef EncodingString);
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 6c479415b9ed27..8bee9f4703dd9c 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -632,7 +632,8 @@ namespace llvm {
DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
DIType *UnderlyingType, unsigned RunTimeLang = 0,
- StringRef UniqueIdentifier = "", bool IsScoped = false);
+ StringRef UniqueIdentifier = "", bool IsScoped = false,
+ std::optional<uint32_t> EnumKind = std::nullopt);
/// Create debugging information entry for a set.
/// \param Scope Scope in which this set is defined.
/// \param Name Set name.
@@ -667,19 +668,20 @@ namespace llvm {
static DIType *createObjectPointerType(DIType *Ty, bool Implicit);
/// Create a permanent forward-declared type.
- DICompositeType *createForwardDecl(unsigned Tag, StringRef Name,
- DIScope *Scope, DIFile *F, unsigned Line,
- unsigned RuntimeLang = 0,
- uint64_t SizeInBits = 0,
- uint32_t AlignInBits = 0,
- StringRef UniqueIdentifier = "");
+ DICompositeType *
+ createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F,
+ unsigned Line, unsigned RuntimeLang = 0,
+ uint64_t SizeInBits = 0, uint32_t AlignInBits = 0,
+ StringRef UniqueIdentifier = "",
+ std::optional<uint32_t> EnumKind = std::nullopt);
/// Create a temporary forward-declared type.
DICompositeType *createReplaceableCompositeType(
unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line,
unsigned RuntimeLang = 0, uint64_t SizeInBits = 0,
uint32_t AlignInBits = 0, DINode::DIFlags Flags = DINode::FlagFwdDecl,
- StringRef UniqueIdentifier = "", DINodeArray Annotations = nullptr);
+ StringRef UniqueIdentifier = "", DINodeArray Annotations = nullptr,
+ std::optional<uint32_t> EnumKind = std::nullopt);
/// Retain DIScope* in a module even if it is not referenced
/// through debug info anchors.
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 5ea8c0d7b448dc..8515d8eda85686 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -1176,24 +1176,28 @@ class DICompositeType : public DIType {
friend class MDNode;
unsigned RuntimeLang;
+ std::optional<uint32_t> EnumKind;
DICompositeType(LLVMContext &C, StorageType Storage, unsigned Tag,
unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits,
- uint32_t NumExtraInhabitants, DIFlags Flags,
+ uint32_t NumExtraInhabitants,
+ std::optional<uint32_t> EnumKind, DIFlags Flags,
ArrayRef<Metadata *> Ops)
: DIType(C, DICompositeTypeKind, Storage, Tag, Line, SizeInBits,
AlignInBits, OffsetInBits, NumExtraInhabitants, Flags, Ops),
- RuntimeLang(RuntimeLang) {}
+ RuntimeLang(RuntimeLang), EnumKind(EnumKind) {}
~DICompositeType() = default;
/// Change fields in place.
void mutate(unsigned Tag, unsigned Line, unsigned RuntimeLang,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
- uint32_t NumExtraInhabitants, DIFlags Flags) {
+ uint32_t NumExtraInhabitants, std::optional<uint32_t> EnumKind,
+ DIFlags Flags) {
assert(isDistinct() && "Only distinct nodes can mutate");
assert(getRawIdentifier() && "Only ODR-uniqued nodes should mutate");
this->RuntimeLang = RuntimeLang;
+ this->EnumKind = EnumKind;
DIType::mutate(Tag, Line, SizeInBits, AlignInBits, OffsetInBits,
NumExtraInhabitants, Flags);
}
@@ -1203,15 +1207,15 @@ class DICompositeType : public DIType {
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIType *Specification,
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,
+ unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
+ 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,
+ Flags, Elements.get(), RuntimeLang, EnumKind, VTableHolder,
TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator,
DataLocation, Associated, Allocated, Rank, Annotations.get(),
@@ -1222,21 +1226,21 @@ class DICompositeType : public DIType {
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,
- MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
- Metadata *Associated, Metadata *Allocated, Metadata *Rank,
- Metadata *Annotations, Metadata *Specification,
- uint32_t NumExtraInhabitants, StorageType Storage,
- bool ShouldCreate = true);
+ std::optional<uint32_t> EnumKind, Metadata *VTableHolder,
+ Metadata *TemplateParams, MDString *Identifier,
+ Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated,
+ Metadata *Allocated, Metadata *Rank, Metadata *Annotations,
+ Metadata *Specification, uint32_t NumExtraInhabitants,
+ StorageType Storage, bool ShouldCreate = true);
TempDICompositeType cloneImpl() const {
return getTemporary(
getContext(), getTag(), getName(), getFile(), getLine(), getScope(),
getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(),
- getFlags(), getElements(), getRuntimeLang(), getVTableHolder(),
- getTemplateParams(), getIdentifier(), getDiscriminator(),
- getRawDataLocation(), getRawAssociated(), getRawAllocated(),
- getRawRank(), getAnnotations(), getSpecification(),
+ getFlags(), getElements(), getRuntimeLang(), getEnumKind(),
+ getVTableHolder(), getTemplateParams(), getIdentifier(),
+ getDiscriminator(), getRawDataLocation(), getRawAssociated(),
+ getRawAllocated(), getRawRank(), getAnnotations(), getSpecification(),
getNumExtraInhabitants());
}
@@ -1246,7 +1250,8 @@ class DICompositeType : public DIType {
(unsigned Tag, StringRef Name, DIFile *File, unsigned Line,
DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
- DINodeArray Elements, unsigned RuntimeLang, DIType *VTableHolder,
+ DINodeArray Elements, unsigned RuntimeLang,
+ std::optional<uint32_t> EnumKind, DIType *VTableHolder,
DITemplateParameterArray TemplateParams = nullptr,
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
Metadata *DataLocation = nullptr, Metadata *Associated = nullptr,
@@ -1255,23 +1260,24 @@ class DICompositeType : public DIType {
uint32_t NumExtraInhabitants = 0),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
OffsetInBits, Specification, NumExtraInhabitants, Flags, Elements,
- RuntimeLang, VTableHolder, TemplateParams, Identifier, Discriminator,
- DataLocation, Associated, Allocated, Rank, Annotations))
+ RuntimeLang, EnumKind, VTableHolder, TemplateParams, Identifier,
+ Discriminator, DataLocation, Associated, Allocated, Rank, Annotations))
DEFINE_MDNODE_GET(
DICompositeType,
(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 *Elements, unsigned RuntimeLang,
+ std::optional<uint32_t> EnumKind, Metadata *VTableHolder,
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 *Specification = 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, Specification, NumExtraInhabitants))
+ OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder,
+ TemplateParams, Identifier, Discriminator, DataLocation, Associated,
+ Allocated, Rank, Annotations, Specification, NumExtraInhabitants))
TempDICompositeType clone() const { return cloneImpl(); }
@@ -1288,10 +1294,11 @@ class DICompositeType : public DIType {
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, Metadata *Specification,
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);
+ unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
+ Metadata *VTableHolder, Metadata *TemplateParams,
+ Metadata *Discriminator, Metadata *DataLocation,
+ Metadata *Associated, Metadata *Allocated, Metadata *Rank,
+ Metadata *Annotations);
static DICompositeType *getODRTypeIfExists(LLVMContext &Context,
MDString &Identifier);
@@ -1310,10 +1317,11 @@ class DICompositeType : public DIType {
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
uint64_t OffsetInBits, Metadata *Specification,
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);
+ unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
+ 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 {
@@ -1327,6 +1335,7 @@ class DICompositeType : public DIType {
}
StringRef getIdentifier() const { return getStringOperand(7); }
unsigned getRuntimeLang() const { return RuntimeLang; }
+ std::optional<uint32_t> getEnumKind() const { return EnumKind; }
Metadata *getRawBaseType() const { return getOperand(3); }
Metadata *getRawElements() const { return getOperand(4); }
diff --git a/llvm/lib/AsmParser/LLLexer.cpp b/llvm/lib/AsmParser/LLLexer.cpp
index 5ea507c009bdc6..9bc5a79da49c61 100644
--- a/llvm/lib/AsmParser/LLLexer.cpp
+++ b/llvm/lib/AsmParser/LLLexer.cpp
@@ -975,6 +975,7 @@ lltok::Kind LLLexer::LexIdentifier() {
DWKEYWORD(CC, DwarfCC);
DWKEYWORD(OP, DwarfOp);
DWKEYWORD(MACINFO, DwarfMacinfo);
+ DWKEYWORD(APPLE_ENUM_KIND, DwarfEnumKind);
#undef DWKEYWORD
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index fa0079bac435c1..610ffe7d69be49 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4697,6 +4697,12 @@ struct DwarfCCField : public MDUnsignedField {
DwarfCCField() : MDUnsignedField(0, dwarf::DW_CC_hi_user) {}
};
+struct DwarfEnumKindField : public MDUnsignedField {
+ DwarfEnumKindField()
+ : MDUnsignedField(dwarf::DW_APPLE_ENUM_KIND_invalid,
+ dwarf::DW_APPLE_ENUM_KIND_max) {}
+};
+
struct EmissionKindField : public MDUnsignedField {
EmissionKindField() : MDUnsignedField(0, DICompileUnit::LastEmissionKind) {}
};
@@ -4870,6 +4876,25 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name,
return false;
}
+template <>
+bool LLParser::parseMDField(LocTy Loc, StringRef Name,
+ DwarfEnumKindField &Result) {
+ if (Lex.getKind() == lltok::APSInt)
+ return parseMDField(Loc, Name, static_cast<MDUnsignedField &>(Result));
+
+ if (Lex.getKind() != lltok::DwarfEnumKind)
+ return tokError("expected DWARF enum kind code");
+
+ unsigned EnumKind = dwarf::getEnumKind(Lex.getStrVal());
+ if (EnumKind == dwarf::DW_APPLE_ENUM_KIND_invalid)
+ return tokError("invalid DWARF enum kind code" + Twine(" '") +
+ Lex.getStrVal() + "'");
+ assert(EnumKind <= Result.Max && "Expected valid DWARF enum kind code");
+ Result.assign(EnumKind);
+ Lex.Lex();
+ return false;
+}
+
template <>
bool LLParser::parseMDField(LocTy Loc, StringRef Name, DwarfLangField &Result) {
if (Lex.getKind() == lltok::APSInt)
@@ -5489,6 +5514,7 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(flags, DIFlagField, ); \
OPTIONAL(elements, MDField, ); \
OPTIONAL(runtimeLang, DwarfLangField, ); \
+ OPTIONAL(enumKind, DwarfEnumKindField, ); \
OPTIONAL(vtableHolder, MDField, ); \
OPTIONAL(templateParams, MDField, ); \
OPTIONAL(identifier, MDStringField, ); \
@@ -5510,15 +5536,19 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
else if (rank.isMDField())
Rank = rank.getMDFieldValue();
+ std::optional<unsigned> EnumKind;
+ if (enumKind.Val != dwarf::DW_APPLE_ENUM_KIND_invalid)
+ EnumKind = enumKind.Val;
+
// If this has an identifier try to build an ODR type.
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,
specificatio...
[truncated]
|
This is the 2nd part to llvm#124752. Here we make sure to set the `DICompositeType` `EnumKind` if the enum was declared with `__attribute__((enum_extensibility(...)))`. In DWARF this will be rendered as `DW_AT_APPLE_enum_kind` and will be used by LLDB when creating `clang::EnumDecl`s from debug-info.
…#126045) This is the 2nd part to #124752. Here we make sure to set the `DICompositeType` `EnumKind` if the enum was declared with `__attribute__((enum_extensibility(...)))`. In DWARF this will be rendered as `DW_AT_APPLE_enum_kind` and will be used by LLDB when creating `clang::EnumDecl`s from debug-info. Depends on #126044
…y attribute (#126045) This is the 2nd part to llvm/llvm-project#124752. Here we make sure to set the `DICompositeType` `EnumKind` if the enum was declared with `__attribute__((enum_extensibility(...)))`. In DWARF this will be rendered as `DW_AT_APPLE_enum_kind` and will be used by LLDB when creating `clang::EnumDecl`s from debug-info. Depends on llvm/llvm-project#126044
…_enum_kind This patch consumes the `DW_AT_APPLE_enum_kind` attribute added in llvm#124752 and turns it into a Clang attribute in the AST. This will currently be used by the Swift language plugin when it creates `EnumDecl`s from debug-info and passes it to Swift compiler, which expects these attributes
…_enum_kind (#126221) This patch consumes the `DW_AT_APPLE_enum_kind` attribute added in #124752 and turns it into a Clang attribute in the AST. This will currently be used by the Swift language plugin when it creates `EnumDecl`s from debug-info and passes it to Swift compiler, which expects these attributes
…DW_AT_APPLE_enum_kind (#126221) This patch consumes the `DW_AT_APPLE_enum_kind` attribute added in llvm/llvm-project#124752 and turns it into a Clang attribute in the AST. This will currently be used by the Swift language plugin when it creates `EnumDecl`s from debug-info and passes it to Swift compiler, which expects these attributes
…ibility (llvm#124752) When creating `EnumDecl`s from DWARF for Objective-C `NS_ENUM`s, the Swift compiler tries to figure out if it should perform "swiftification" of that enum (which involves renaming the enumerator cases, etc.). The heuristics by which it determines whether we want to swiftify an enum is by checking the `enum_extensibility` attribute (because that's what `NS_ENUM` pretty much are). Currently LLDB fails to attach the `EnumExtensibilityAttr` to `EnumDecl`s it creates (because there's not enough info in DWARF to derive it), which means we have to fall back to re-building Swift modules on-the-fly, slowing down expression evaluation substantially. This happens around https://github.com/swiftlang/swift/blob/4b3931c8ce437b3f13f245e6423f95c94a5876ac/lib/ClangImporter/ImportEnumInfo.cpp#L37-L59 To speed up Swift exression evaluation, this patch proposes encoding the C/C++/Objective-C `enum_extensibility` attribute in DWARF via a new `DW_AT_APPLE_ENUM_KIND`. This would currently be only used from the LLDB Swift plugin. But may be of interest to other language plugins as well (though I haven't come up with a concrete use-case for it outside of Swift). I'm open to naming suggestions of the various new attributes/attribute constants proposed here. I tried to be as generic as possible if we wanted to extend it to other kinds of enum properties (e.g., flag enums). The new attribute would look as follows: ``` DW_TAG_enumeration_type DW_AT_type (0x0000003a "unsigned int") DW_AT_APPLE_enum_kind (DW_APPLE_ENUM_KIND_Closed) DW_AT_name ("ClosedEnum") DW_AT_byte_size (0x04) DW_AT_decl_file ("enum.c") DW_AT_decl_line (23) DW_TAG_enumeration_type DW_AT_type (0x0000003a "unsigned int") DW_AT_APPLE_enum_kind (DW_APPLE_ENUM_KIND_Open) DW_AT_name ("OpenEnum") DW_AT_byte_size (0x04) DW_AT_decl_file ("enum.c") DW_AT_decl_line (27) ``` Absence of the attribute means the extensibility of the enum is unknown and abides by whatever the language rules of that CU dictate. This does feel like a big hammer for quite a specific use-case, so I'm happy to discuss alternatives. Alternatives considered: * Re-using an existing DWARF attribute to express extensibility. E.g., a `DW_TAG_enumeration_type` could have a `DW_AT_count` or `DW_AT_upper_bound` indicating the number of enumerators, which could imply closed-ness. I felt like a dedicated attribute (which could be generalized further) seemed more applicable. But I'm open to re-using existing attributes. * Encoding the entire attribute string (i.e., `DW_TAG_LLVM_annotation ("enum_extensibility((open))")`) on the `DW_TAG_enumeration_type`. Then in LLDB somehow parse that out into a `EnumExtensibilityAttr`. I haven't found a great API in Clang to parse arbitrary strings into AST nodes (the ones I've found required fully formed C++ constructs). Though if someone knows of a good way to do this, happy to consider that too.
…llvm#126045) This is the 2nd part to llvm#124752. Here we make sure to set the `DICompositeType` `EnumKind` if the enum was declared with `__attribute__((enum_extensibility(...)))`. In DWARF this will be rendered as `DW_AT_APPLE_enum_kind` and will be used by LLDB when creating `clang::EnumDecl`s from debug-info. Depends on llvm#126044
…_enum_kind (llvm#126221) This patch consumes the `DW_AT_APPLE_enum_kind` attribute added in llvm#124752 and turns it into a Clang attribute in the AST. This will currently be used by the Swift language plugin when it creates `EnumDecl`s from debug-info and passes it to Swift compiler, which expects these attributes
This already landed, but I noticed an oddity in the
I don't think that second |
I have a patch that touches this same area, so I will include the fix there. I don't really know how to write a test case for it, but I think the test case for my new feature will fail if the code remains as-is. |
In Ada, an array can be packed and the elements can take less space than their natural object size. For example, for this type: type Packed_Array is array (4 .. 8) of Boolean; pragma pack (Packed_Array); ... each element of the array occupies a single bit, even though the "natural" size for a Boolean in memory is a byte. In DWARF, this is represented by putting a DW_AT_bit_stride onto the array type itself. This patch adds a bit stride to DICompositeType so that gnat-llvm can emit DWARF for these sorts of arrays. This also fixes a bug in MetadataLoader.cpp, introduced in llvm#124752. I don't know how to write a separate test case for that, but I believe the new array-bitstride.ll will fail if that fix is backed out.
Yup thanks for catching that. Indeed that should be |
… from bitcode This was pointed out in llvm#124752 (comment) There was not test that roundtrips this attribute through LLVM bitcode, so this was never caught.
…ND from bitcode This was pointed out in llvm#124752 (comment) There was no test that roundtrips this attribute through LLVM bitcode, so this was never caught.
…ND from bitcode This was pointed out in llvm#124752 (comment) There was no test that roundtrips this attribute through LLVM bitcode, so this was never caught.
…ND from bitcode This was pointed out in llvm#124752 (comment) There was no test that roundtrips this attribute through LLVM bitcode, so this was never caught.
… from bitcode (#132374) This was pointed out in #124752 (comment) There was no test that roundtrips this attribute through LLVM bitcode, so this was never caught.
…E_ENUM_KIND from bitcode (#132374) This was pointed out in llvm/llvm-project#124752 (comment) There was no test that roundtrips this attribute through LLVM bitcode, so this was never caught.
…ND from bitcode This was pointed out in llvm#124752 (comment) There was no test that roundtrips this attribute through LLVM bitcode, so this was never caught.
When creating
EnumDecl
s from DWARF for Objective-CNS_ENUM
s, the Swift compiler tries to figure out if it should perform "swiftification" of that enum (which involves renaming the enumerator cases, etc.). The heuristics by which it determines whether we want to swiftify an enum is by checking theenum_extensibility
attribute (because that's whatNS_ENUM
pretty much are). Currently LLDB fails to attach theEnumExtensibilityAttr
toEnumDecl
s it creates (because there's not enough info in DWARF to derive it), which means we have to fall back to re-building Swift modules on-the-fly, slowing down expression evaluation substantially. This happens around https://github.com/swiftlang/swift/blob/4b3931c8ce437b3f13f245e6423f95c94a5876ac/lib/ClangImporter/ImportEnumInfo.cpp#L37-L59To speed up Swift exression evaluation, this patch proposes encoding the C/C++/Objective-C
enum_extensibility
attribute in DWARF via a newDW_AT_APPLE_ENUM_KIND
. This would currently be only used from the LLDB Swift plugin. But may be of interest to other language plugins as well (though I haven't come up with a concrete use-case for it outside of Swift).I'm open to naming suggestions of the various new attributes/attribute constants proposed here. I tried to be as generic as possible if we wanted to extend it to other kinds of enum properties (e.g., flag enums).
The new attribute would look as follows:
Absence of the attribute means the extensibility of the enum is unknown and abides by whatever the language rules of that CU dictate.
This does feel like a big hammer for quite a specific use-case, so I'm happy to discuss alternatives.
Alternatives considered:
DW_TAG_enumeration_type
could have aDW_AT_count
orDW_AT_upper_bound
indicating the number of enumerators, which could imply closed-ness. I felt like a dedicated attribute (which could be generalized further) seemed more applicable. But I'm open to re-using existing attributes.DW_TAG_LLVM_annotation ("enum_extensibility((open))")
) on theDW_TAG_enumeration_type
. Then in LLDB somehow parse that out into aEnumExtensibilityAttr
. I haven't found a great API in Clang to parse arbitrary strings into AST nodes (the ones I've found required fully formed C++ constructs). Though if someone knows of a good way to do this, happy to consider that too.