[clang] [llvm] [WIP][clang][DebugInfo] Add new DW_AT_APPLE_ENUM_KIND to encode enum_extensibility (PR #124752)
Michael Buch via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 28 06:19:04 PST 2025
https://github.com/Michael137 created https://github.com/llvm/llvm-project/pull/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.
>From b00ae7f30e725e7d3897c3b87cacc6eaba79feb8 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 27 Jan 2025 18:14:06 +0000
Subject: [PATCH] [WIP][clang][DebugInfo] Add new DW_AT_APPLE_ENUM_KIND to
encode enum_extensibility
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.
---
clang/lib/CodeGen/CGDebugInfo.cpp | 7 +-
.../CodeGen/debug-info-enum-extensibility.c | 49 +++++
llvm/include/llvm/AsmParser/LLToken.h | 1 +
llvm/include/llvm/BinaryFormat/Dwarf.def | 14 +-
llvm/include/llvm/BinaryFormat/Dwarf.h | 15 +-
llvm/include/llvm/IR/DIBuilder.h | 18 +-
llvm/include/llvm/IR/DebugInfoMetadata.h | 77 ++++----
llvm/lib/AsmParser/LLLexer.cpp | 1 +
llvm/lib/AsmParser/LLParser.cpp | 43 +++-
llvm/lib/BinaryFormat/Dwarf.cpp | 21 ++
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 22 ++-
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 3 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 3 +
llvm/lib/IR/AsmWriter.cpp | 4 +
llvm/lib/IR/DIBuilder.cpp | 57 +++---
llvm/lib/IR/DebugInfoMetadata.cpp | 44 +++--
.../unittests/IR/DebugTypeODRUniquingTest.cpp | 80 ++++----
llvm/unittests/IR/MetadataTest.cpp | 184 ++++++++++--------
.../Transforms/Utils/CloningTest.cpp | 3 +-
19 files changed, 413 insertions(+), 233 deletions(-)
create mode 100644 clang/test/CodeGen/debug-info-enum-extensibility.c
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 6cbcaf03844102..7d6364a4f90d95 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -3574,9 +3574,14 @@ llvm::DIType *CGDebugInfo::CreateTypeDefinition(const EnumType *Ty) {
unsigned Line = getLineNumber(ED->getLocation());
llvm::DIScope *EnumContext = getDeclContextDescriptor(ED);
llvm::DIType *ClassTy = getOrCreateType(ED->getIntegerType(), DefUnit);
+
+ std::optional<int32_t> EnumKind;
+ if (auto *Attr = ED->getAttr<EnumExtensibilityAttr>())
+ EnumKind = Attr->getExtensibility();
+
return DBuilder.createEnumerationType(
EnumContext, ED->getName(), DefUnit, Line, Size, Align, EltArray, ClassTy,
- /*RunTimeLang=*/0, Identifier, ED->isScoped());
+ /*RunTimeLang=*/0, Identifier, ED->isScoped(), EnumKind);
}
llvm::DIMacro *CGDebugInfo::CreateMacro(llvm::DIMacroFile *Parent,
diff --git a/clang/test/CodeGen/debug-info-enum-extensibility.c b/clang/test/CodeGen/debug-info-enum-extensibility.c
new file mode 100644
index 00000000000000..80c32e0b6357f3
--- /dev/null
+++ b/clang/test/CodeGen/debug-info-enum-extensibility.c
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited %s -o - | FileCheck %s
+
+// CHECK-NOT: enumKind
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "ClosedEnum"
+// CHECK-SAME: enumKind: 0)
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "OpenEnum"
+// CHECK-SAME: enumKind: 1)
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "ClosedFlagEnum"
+// CHECK-SAME: enumKind: 0)
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "OpenFlagEnum"
+// CHECK-SAME: enumKind: 1)
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "MixedEnum"
+// CHECK-SAME: enumKind: 1)
+
+enum Enum {
+ E0, E1
+};
+
+enum FlagEnum {
+ FE0 = 1 << 0, FE1 = 1 << 1
+};
+
+enum __attribute__((enum_extensibility(closed))) ClosedEnum {
+ A0, A1
+};
+
+enum __attribute__((enum_extensibility(open))) OpenEnum {
+ B0, B1
+};
+
+enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum {
+ C0 = 1 << 0, C1 = 1 << 1
+};
+
+enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum {
+ D0 = 1 << 0, D1 = 1 << 1
+};
+
+enum __attribute__((enum_extensibility(open), enum_extensibility(closed))) MixedEnum {
+ M0, M1
+};
+
+enum Enum e;
+enum FlagEnum fe;
+enum ClosedEnum ce;
+enum OpenEnum oe;
+enum ClosedFlagEnum cfe;
+enum OpenFlagEnum ofe;
+enum MixedEnum me;
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..5f82f0119e9c3c 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, ///< Virtuality 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 Virtuality);
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..8bf7eca9a09b63 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(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,
specification.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)) {
+ elements.Val, runtimeLang.Val, EnumKind, vtableHolder.Val,
+ templateParams.Val, discriminator.Val, dataLocation.Val,
+ associated.Val, allocated.Val, Rank, annotations.Val)) {
Result = CT;
return false;
}
@@ -5529,9 +5559,10 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
DICompositeType,
(Context, 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, identifier.Val,
- discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, Rank,
- annotations.Val, specification.Val, num_extra_inhabitants.Val));
+ runtimeLang.Val, EnumKind, vtableHolder.Val, templateParams.Val,
+ identifier.Val, discriminator.Val, dataLocation.Val, associated.Val,
+ allocated.Val, Rank, annotations.Val, specification.Val,
+ num_extra_inhabitants.Val));
return false;
}
diff --git a/llvm/lib/BinaryFormat/Dwarf.cpp b/llvm/lib/BinaryFormat/Dwarf.cpp
index 0cd5dfbd023e4e..b9b10a541b2632 100644
--- a/llvm/lib/BinaryFormat/Dwarf.cpp
+++ b/llvm/lib/BinaryFormat/Dwarf.cpp
@@ -390,6 +390,25 @@ unsigned llvm::dwarf::getVirtuality(StringRef VirtualityString) {
.Default(DW_VIRTUALITY_invalid);
}
+StringRef llvm::dwarf::EnumKindString(unsigned EnumKind) {
+ switch (EnumKind) {
+ default:
+ return StringRef();
+#define HANDLE_DW_APPLE_ENUM_KIND(ID, NAME) \
+ case DW_APPLE_ENUM_KIND_##NAME: \
+ return "DW_APPLE_ENUM_KIND_" #NAME;
+#include "llvm/BinaryFormat/Dwarf.def"
+ }
+}
+
+unsigned llvm::dwarf::getEnumKind(StringRef EnumKindString) {
+ return StringSwitch<unsigned>(EnumKindString)
+#define HANDLE_DW_APPLE_ENUM_KIND(ID, NAME) \
+ .Case("DW_APPLE_ENUM_KIND_" #NAME, DW_APPLE_ENUM_KIND_##NAME)
+#include "llvm/BinaryFormat/Dwarf.def"
+ .Default(DW_APPLE_ENUM_KIND_invalid);
+}
+
StringRef llvm::dwarf::LanguageString(unsigned Language) {
switch (Language) {
default:
@@ -741,6 +760,8 @@ StringRef llvm::dwarf::AttributeValueString(uint16_t Attr, unsigned Val) {
return LanguageString(Val);
case DW_AT_defaulted:
return DefaultedMemberString(Val);
+ case DW_AT_APPLE_enum_kind:
+ return EnumKindString(Val);
}
return StringRef();
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 1caa8480efc518..413d9f68e6cc3b 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1600,7 +1600,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_COMPOSITE_TYPE: {
- if (Record.size() < 16 || Record.size() > 24)
+ if (Record.size() < 16 || Record.size() > 25)
return error("Invalid record");
// If we have a UUID and this is not a forward declaration, lookup the
@@ -1622,6 +1622,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(Record[10]);
Metadata *Elements = nullptr;
unsigned RuntimeLang = Record[12];
+ std::optional<uint32_t> EnumKind;
+
Metadata *VTableHolder = nullptr;
Metadata *TemplateParams = nullptr;
Metadata *Discriminator = nullptr;
@@ -1683,24 +1685,28 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Specification = getMDOrNull(Record[23]);
}
}
+
+ if (Record.size() > 25 && Record[25] != dwarf::DW_APPLE_ENUM_KIND_invalid)
+ EnumKind = Record[25];
+
DICompositeType *CT = nullptr;
if (Identifier)
CT = DICompositeType::buildODRType(
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Specification,
- NumExtraInhabitants, Flags, Elements, RuntimeLang, VTableHolder,
- TemplateParams, Discriminator, DataLocation, Associated, Allocated,
- Rank, Annotations);
+ NumExtraInhabitants, Flags, Elements, RuntimeLang, EnumKind,
+ VTableHolder, TemplateParams, Discriminator, DataLocation, Associated,
+ Allocated, Rank, Annotations);
// Create a node if we didn't get a lazy ODR type.
if (!CT)
CT = GET_OR_DISTINCT(DICompositeType,
(Context, Tag, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, Flags,
- Elements, RuntimeLang, VTableHolder, TemplateParams,
- Identifier, Discriminator, DataLocation, Associated,
- Allocated, Rank, Annotations, Specification,
- NumExtraInhabitants));
+ Elements, RuntimeLang, EnumKind, VTableHolder,
+ TemplateParams, Identifier, Discriminator,
+ DataLocation, Associated, Allocated, Rank,
+ Annotations, Specification, NumExtraInhabitants));
if (!IsNotUsedInTypeRef && Identifier)
MetadataList.addTypeRef(*Identifier, *cast<DICompositeType>(CT));
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 31c96400dd0fe5..28518607222af0 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -23,6 +23,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/Bitcode/BitcodeCommon.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
@@ -1959,6 +1960,8 @@ void ModuleBitcodeWriter::writeDICompositeType(
Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get()));
Record.push_back(N->getNumExtraInhabitants());
Record.push_back(VE.getMetadataOrNullID(N->getRawSpecification()));
+ Record.push_back(
+ N->getEnumKind().value_or(dwarf::DW_APPLE_ENUM_KIND_invalid));
Stream.EmitRecord(bitc::METADATA_COMPOSITE_TYPE, Record, Abbrev);
Record.clear();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index d3450b8b0556fd..3426780d553fe9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1624,6 +1624,9 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addFlag(Buffer, dwarf::DW_AT_enum_class);
}
+ if (auto Kind = CTy->getEnumKind())
+ addUInt(Buffer, dwarf::DW_AT_APPLE_enum_kind, dwarf::DW_FORM_data1, *Kind);
+
auto *Context = CTy->getScope();
bool IndexEnumerators = !Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) ||
isa<DINamespace>(Context) || isa<DICommonBlock>(Context);
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index a37a8901489cf7..ff78d650808097 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2257,6 +2257,10 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
Printer.printMetadata("annotations", N->getRawAnnotations());
if (auto *Specification = N->getRawSpecification())
Printer.printMetadata("specification", Specification);
+
+ if (auto EnumKind = N->getEnumKind())
+ Printer.printInt("enumKind", *EnumKind, /*ShouldSkipZero=*/false);
+
Out << ")";
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index d9bd4f11e89a39..e27015892928ca 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -511,8 +511,8 @@ DICompositeType *DIBuilder::createClassType(
auto *R = DICompositeType::get(
VMContext, dwarf::DW_TAG_class_type, Name, File, LineNumber,
getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RunTimeLang, VTableHolder,
- cast_or_null<MDTuple>(TemplateParams), UniqueIdentifier);
+ OffsetInBits, Flags, Elements, RunTimeLang, /*EnumKind=*/std::nullopt,
+ VTableHolder, cast_or_null<MDTuple>(TemplateParams), UniqueIdentifier);
trackIfUnresolved(R);
return R;
}
@@ -526,9 +526,9 @@ DICompositeType *DIBuilder::createStructType(
auto *R = DICompositeType::get(
VMContext, dwarf::DW_TAG_structure_type, Name, File, LineNumber,
getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits, 0,
- Flags, Elements, RunTimeLang, VTableHolder, nullptr, UniqueIdentifier,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, Specification,
- NumExtraInhabitants);
+ Flags, Elements, RunTimeLang, /*EnumKind=*/std::nullopt, VTableHolder,
+ nullptr, UniqueIdentifier, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, Specification, NumExtraInhabitants);
trackIfUnresolved(R);
return R;
}
@@ -540,7 +540,8 @@ DICompositeType *DIBuilder::createUnionType(
auto *R = DICompositeType::get(
VMContext, dwarf::DW_TAG_union_type, Name, File, LineNumber,
getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
- Elements, RunTimeLang, nullptr, nullptr, UniqueIdentifier);
+ Elements, RunTimeLang, /*EnumKind=*/std::nullopt, nullptr, nullptr,
+ UniqueIdentifier);
trackIfUnresolved(R);
return R;
}
@@ -554,7 +555,8 @@ DIBuilder::createVariantPart(DIScope *Scope, StringRef Name, DIFile *File,
auto *R = DICompositeType::get(
VMContext, dwarf::DW_TAG_variant_part, Name, File, LineNumber,
getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
- Elements, 0, nullptr, nullptr, UniqueIdentifier, Discriminator);
+ Elements, 0, /*EnumKind=*/std::nullopt, nullptr, nullptr,
+ UniqueIdentifier, Discriminator);
trackIfUnresolved(R);
return R;
}
@@ -565,17 +567,16 @@ DISubroutineType *DIBuilder::createSubroutineType(DITypeRefArray ParameterTypes,
return DISubroutineType::get(VMContext, Flags, CC, ParameterTypes);
}
-DICompositeType *
-DIBuilder::createEnumerationType(DIScope *Scope, StringRef Name, DIFile *File,
- unsigned LineNumber, uint64_t SizeInBits,
- uint32_t AlignInBits, DINodeArray Elements,
- DIType *UnderlyingType, unsigned RunTimeLang,
- StringRef UniqueIdentifier, bool IsScoped) {
+DICompositeType *DIBuilder::createEnumerationType(
+ DIScope *Scope, StringRef Name, DIFile *File, unsigned LineNumber,
+ uint64_t SizeInBits, uint32_t AlignInBits, DINodeArray Elements,
+ DIType *UnderlyingType, unsigned RunTimeLang, StringRef UniqueIdentifier,
+ bool IsScoped, std::optional<uint32_t> EnumKind) {
auto *CTy = DICompositeType::get(
VMContext, dwarf::DW_TAG_enumeration_type, Name, File, LineNumber,
getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0,
IsScoped ? DINode::FlagEnumClass : DINode::FlagZero, Elements,
- RunTimeLang, nullptr, nullptr, UniqueIdentifier);
+ RunTimeLang, EnumKind, nullptr, nullptr, UniqueIdentifier);
AllEnumTypes.emplace_back(CTy);
trackIfUnresolved(CTy);
return CTy;
@@ -602,8 +603,8 @@ DIBuilder::createArrayType(uint64_t Size, uint32_t AlignInBits, DIType *Ty,
PointerUnion<DIExpression *, DIVariable *> RK) {
auto *R = DICompositeType::get(
VMContext, dwarf::DW_TAG_array_type, "", nullptr, 0, nullptr, Ty, Size,
- AlignInBits, 0, DINode::FlagZero, Subscripts, 0, nullptr, nullptr, "",
- nullptr,
+ AlignInBits, 0, DINode::FlagZero, Subscripts, 0,
+ /*EnumKind=*/std::nullopt, nullptr, nullptr, "", nullptr,
isa<DIExpression *>(DL) ? (Metadata *)cast<DIExpression *>(DL)
: (Metadata *)cast<DIVariable *>(DL),
isa<DIExpression *>(AS) ? (Metadata *)cast<DIExpression *>(AS)
@@ -621,7 +622,8 @@ DICompositeType *DIBuilder::createVectorType(uint64_t Size,
DINodeArray Subscripts) {
auto *R = DICompositeType::get(VMContext, dwarf::DW_TAG_array_type, "",
nullptr, 0, nullptr, Ty, Size, AlignInBits, 0,
- DINode::FlagVector, Subscripts, 0, nullptr);
+ DINode::FlagVector, Subscripts, 0,
+ /*EnumKind=*/std::nullopt, nullptr);
trackIfUnresolved(R);
return R;
}
@@ -666,17 +668,16 @@ void DIBuilder::retainType(DIScope *T) {
DIBasicType *DIBuilder::createUnspecifiedParameter() { return nullptr; }
-DICompositeType *
-DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope,
- DIFile *F, unsigned Line, unsigned RuntimeLang,
- uint64_t SizeInBits, uint32_t AlignInBits,
- StringRef UniqueIdentifier) {
+DICompositeType *DIBuilder::createForwardDecl(
+ unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line,
+ unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits,
+ StringRef UniqueIdentifier, std::optional<uint32_t> EnumKind) {
// FIXME: Define in terms of createReplaceableForwardDecl() by calling
// replaceWithUniqued().
auto *RetTy = DICompositeType::get(
VMContext, Tag, Name, F, Line, getNonCompileUnitScope(Scope), nullptr,
SizeInBits, AlignInBits, 0, DINode::FlagFwdDecl, nullptr, RuntimeLang,
- nullptr, nullptr, UniqueIdentifier);
+ /*EnumKind=*/EnumKind, nullptr, nullptr, UniqueIdentifier);
trackIfUnresolved(RetTy);
return RetTy;
}
@@ -684,14 +685,14 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope,
DICompositeType *DIBuilder::createReplaceableCompositeType(
unsigned Tag, StringRef Name, DIScope *Scope, DIFile *F, unsigned Line,
unsigned RuntimeLang, uint64_t SizeInBits, uint32_t AlignInBits,
- DINode::DIFlags Flags, StringRef UniqueIdentifier,
- DINodeArray Annotations) {
+ DINode::DIFlags Flags, StringRef UniqueIdentifier, DINodeArray Annotations,
+ std::optional<uint32_t> EnumKind) {
auto *RetTy =
DICompositeType::getTemporary(
VMContext, Tag, Name, F, Line, getNonCompileUnitScope(Scope), nullptr,
- SizeInBits, AlignInBits, 0, Flags, nullptr, RuntimeLang, nullptr,
- nullptr, UniqueIdentifier, nullptr, nullptr, nullptr, nullptr,
- nullptr, Annotations)
+ SizeInBits, AlignInBits, 0, Flags, nullptr, RuntimeLang, EnumKind,
+ nullptr, nullptr, UniqueIdentifier, nullptr, nullptr, nullptr,
+ nullptr, nullptr, Annotations)
.release();
trackIfUnresolved(RetTy);
return RetTy;
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 915cdd301f2c7e..32e659d43edcfc 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -767,11 +767,12 @@ DICompositeType *DICompositeType::getImpl(
LLVMContext &Context, 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, MDString *Identifier, Metadata *Discriminator,
- Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
- Metadata *Rank, Metadata *Annotations, Metadata *Specification,
- uint32_t NumExtraInhabitants, StorageType Storage, bool ShouldCreate) {
+ Metadata *Elements, unsigned RuntimeLang, 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) {
assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType.
@@ -787,7 +788,7 @@ DICompositeType *DICompositeType::getImpl(
Rank, Annotations, Specification};
DEFINE_GETIMPL_STORE(DICompositeType,
(Tag, Line, RuntimeLang, SizeInBits, AlignInBits,
- OffsetInBits, NumExtraInhabitants, Flags),
+ OffsetInBits, NumExtraInhabitants, EnumKind, Flags),
Ops);
}
@@ -796,10 +797,10 @@ DICompositeType *DICompositeType::buildODRType(
Metadata *File, unsigned Line, Metadata *Scope, 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) {
+ Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
+ Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
+ Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
+ Metadata *Rank, Metadata *Annotations) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -808,9 +809,9 @@ DICompositeType *DICompositeType::buildODRType(
return CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, &Identifier, Discriminator,
- DataLocation, Associated, Allocated, Rank, Annotations,
- Specification, NumExtraInhabitants);
+ EnumKind, VTableHolder, TemplateParams, &Identifier,
+ Discriminator, DataLocation, Associated, Allocated, Rank,
+ Annotations, Specification, NumExtraInhabitants);
if (CT->getTag() != Tag)
return nullptr;
@@ -821,7 +822,7 @@ DICompositeType *DICompositeType::buildODRType(
// Mutate CT in place. Keep this in sync with getImpl.
CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
- NumExtraInhabitants, Flags);
+ NumExtraInhabitants, EnumKind, Flags);
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, &Identifier,
Discriminator, DataLocation, Associated, Allocated,
@@ -839,10 +840,10 @@ DICompositeType *DICompositeType::getODRType(
Metadata *File, unsigned Line, Metadata *Scope, 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) {
+ Metadata *Elements, unsigned RuntimeLang, std::optional<uint32_t> EnumKind,
+ Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator,
+ Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
+ Metadata *Rank, Metadata *Annotations) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -850,9 +851,10 @@ DICompositeType *DICompositeType::getODRType(
if (!CT) {
CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
- AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
- TemplateParams, &Identifier, Discriminator, DataLocation, Associated,
- Allocated, Rank, Annotations, Specification, NumExtraInhabitants);
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, EnumKind,
+ VTableHolder, TemplateParams, &Identifier, Discriminator, DataLocation,
+ Associated, Allocated, Rank, Annotations, Specification,
+ NumExtraInhabitants);
} else {
if (CT->getTag() != Tag)
return nullptr;
diff --git a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
index 7180b8183c50a7..7c673b01661888 100644
--- a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
+++ b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
@@ -30,8 +30,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
// Without a type map, this should return null.
EXPECT_FALSE(DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
- nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
// Enable the mapping. There still shouldn't be a type.
Context.enableDebugTypeODRUniquing();
@@ -40,8 +40,8 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
// Create some ODR-uniqued type.
auto &CT = *DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
- nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, std::nullopt,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
EXPECT_EQ(UUID.getString(), CT.getIdentifier());
// Check that we get it back, even if we change a field.
@@ -49,14 +49,14 @@ TEST(DebugTypeODRUniquingTest, getODRType) {
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero,
- nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, 0, std::nullopt, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr));
+ EXPECT_EQ(&CT, DICompositeType::getODRType(
+ Context, UUID, dwarf::DW_TAG_class_type,
+ MDString::get(Context, "name"), nullptr, 0, nullptr,
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0,
+ std::nullopt, nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr));
- EXPECT_EQ(&CT,
- DICompositeType::getODRType(
- Context, UUID, dwarf::DW_TAG_class_type,
- MDString::get(Context, "name"), nullptr, 0, nullptr, nullptr, 0,
- 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
// Check that it's discarded with the type map.
Context.disableDebugTypeODRUniquing();
@@ -75,43 +75,48 @@ TEST(DebugTypeODRUniquingTest, buildODRType) {
MDString &UUID = *MDString::get(Context, "Type");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0, nullptr,
- nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0,
+ std::nullopt, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr);
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(dwarf::DW_TAG_class_type, CT.getTag());
// Update with another forward decl. This should be a no-op.
- EXPECT_EQ(&CT, DICompositeType::buildODRType(
- Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
- 0, nullptr, nullptr, 0, 0, 0, nullptr, 0,
- DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr));
+ EXPECT_EQ(&CT,
+ DICompositeType::buildODRType(
+ Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0,
+ nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl,
+ nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr));
EXPECT_FALSE(DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_structure_type, nullptr, nullptr, 0, nullptr,
- nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0,
+ std::nullopt, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr));
// Update with a definition. This time we should see a change.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero,
- nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr));
+ nullptr, 0, std::nullopt, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_FALSE(CT.isForwardDecl());
// Further updates should be ignored.
- EXPECT_EQ(&CT, DICompositeType::buildODRType(
- Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
- 0, nullptr, nullptr, 0, 0, 0, nullptr, 0,
- DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr));
+ EXPECT_EQ(&CT,
+ DICompositeType::buildODRType(
+ Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 0,
+ nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl,
+ nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr));
EXPECT_FALSE(CT.isForwardDecl());
- EXPECT_EQ(&CT, DICompositeType::buildODRType(
- Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
- 111u, nullptr, nullptr, 0, 0, 0, nullptr, 0,
- DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr));
+ EXPECT_EQ(&CT,
+ DICompositeType::buildODRType(
+ Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr, 111u,
+ nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero,
+ nullptr, 0, std::nullopt, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr));
EXPECT_NE(111u, CT.getLine());
}
@@ -123,8 +128,8 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
MDString &UUID = *MDString::get(Context, "UUID");
auto &CT = *DICompositeType::buildODRType(
Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, nullptr,
- 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr);
+ 0, DINode::FlagFwdDecl, nullptr, 0, std::nullopt, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
// Create macros for running through all the fields except Identifier and Flags.
#define FOR_EACH_MDFIELD() \
@@ -141,7 +146,8 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
DO_FOR_FIELD(AlignInBits) \
DO_FOR_FIELD(OffsetInBits) \
DO_FOR_FIELD(NumExtraInhabitants) \
- DO_FOR_FIELD(RuntimeLang)
+ DO_FOR_FIELD(RuntimeLang) \
+ DO_FOR_FIELD(EnumKind)
// Create all the fields.
#define DO_FOR_FIELD(X) auto *X = MDString::get(Context, #X);
@@ -157,8 +163,8 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
Context, UUID, 0, Name, File, Line, Scope, BaseType,
SizeInBits, AlignInBits, OffsetInBits, nullptr,
NumExtraInhabitants, DINode::FlagArtificial, Elements,
- RuntimeLang, VTableHolder, TemplateParams, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr));
+ RuntimeLang, EnumKind, VTableHolder, TemplateParams,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
// Confirm that all the right fields got updated.
#define DO_FOR_FIELD(X) EXPECT_EQ(X, CT.getRaw##X());
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 628221339c89bf..8fe40a94ee546a 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -115,9 +115,10 @@ class MetadataTest : public testing::Test {
return ConstantAsMetadata::get(getConstant());
}
DIType *getCompositeType() {
- return DICompositeType::getDistinct(
- Context, dwarf::DW_TAG_structure_type, "", nullptr, 0, nullptr, nullptr,
- 32, 32, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr, "");
+ return DICompositeType::getDistinct(Context, dwarf::DW_TAG_structure_type,
+ "", nullptr, 0, nullptr, nullptr, 32,
+ 32, 0, DINode::FlagZero, nullptr, 0,
+ std::nullopt, nullptr, nullptr, "");
}
Function *getFunction(StringRef Name) {
return Function::Create(
@@ -2001,11 +2002,12 @@ TEST_F(DICompositeTypeTest, get) {
DIType *VTableHolder = getCompositeType();
MDTuple *TemplateParams = getTuple();
StringRef Identifier = "some id";
+ std::optional<uint32_t> EnumKind = 1;
- auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier);
+ auto *N = DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder,
+ TemplateParams, Identifier);
EXPECT_EQ(Tag, N->getTag());
EXPECT_EQ(Name, N->getName());
EXPECT_EQ(File, N->getFile());
@@ -2021,84 +2023,91 @@ TEST_F(DICompositeTypeTest, get) {
EXPECT_EQ(VTableHolder, N->getVTableHolder());
EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
EXPECT_EQ(Identifier, N->getIdentifier());
+ EXPECT_EQ(EnumKind, N->getEnumKind());
- EXPECT_EQ(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EXPECT_EQ(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ EnumKind, VTableHolder, TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(Context, Tag + 1, Name, File, Line, Scope,
BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
- EXPECT_NE(N, DICompositeType::get(Context, Tag, "abc", File, Line, Scope,
- BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams,
+ Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, "abc", File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ EnumKind, VTableHolder, TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, getFile(), Line, Scope,
BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams,
+ Identifier));
EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line + 1, Scope,
BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
- EXPECT_NE(N, DICompositeType::get(
- Context, Tag, Name, File, Line, getSubprogram(), BaseType,
- SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
- RuntimeLang, VTableHolder, TemplateParams, Identifier));
- EXPECT_NE(N, DICompositeType::get(
- Context, Tag, Name, File, Line, Scope, getBasicType("other"),
- SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
- RuntimeLang, VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams,
+ Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line,
+ getSubprogram(), BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements,
+ RuntimeLang, EnumKind, VTableHolder,
+ TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits + 1, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ getBasicType("other"), SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements,
+ RuntimeLang, EnumKind, VTableHolder,
+ TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits, AlignInBits + 1,
+ BaseType, SizeInBits + 1, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams,
+ Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits + 1, OffsetInBits, Flags, Elements, RuntimeLang,
+ EnumKind, VTableHolder, TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams, Identifier));
DINode::DIFlags FlagsPOne = static_cast<DINode::DIFlags>(Flags + 1);
EXPECT_NE(N, DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, FlagsPOne, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, getTuple(), RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1,
- VTableHolder, TemplateParams, Identifier));
+ EnumKind, VTableHolder, TemplateParams, Identifier));
EXPECT_NE(N, DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- getCompositeType(), TemplateParams, Identifier));
- EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, getTuple(), Identifier));
- EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, "other"));
+ EnumKind, getCompositeType(), TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ EnumKind, VTableHolder, getTuple(), Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ EnumKind, VTableHolder, TemplateParams, "other"));
// Be sure that missing identifiers get null pointers.
EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,
BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, "")
+ EnumKind, VTableHolder, TemplateParams, "")
->getRawIdentifier());
EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,
BaseType, SizeInBits, AlignInBits,
OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams)
+ EnumKind, VTableHolder, TemplateParams)
->getRawIdentifier());
TempDICompositeType Temp = N->clone();
@@ -2118,14 +2127,15 @@ TEST_F(DICompositeTypeTest, getWithLargeValues) {
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
MDTuple *Elements = getTuple();
unsigned RuntimeLang = 6;
+ std::optional<uint32_t> EnumKind = 1;
DIType *VTableHolder = getCompositeType();
MDTuple *TemplateParams = getTuple();
StringRef Identifier = "some id";
- auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
- BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier);
+ auto *N = DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang, EnumKind, VTableHolder,
+ TemplateParams, Identifier);
EXPECT_EQ(SizeInBits, N->getSizeInBits());
EXPECT_EQ(AlignInBits, N->getAlignInBits());
EXPECT_EQ(OffsetInBits, N->getOffsetInBits());
@@ -2143,11 +2153,13 @@ TEST_F(DICompositeTypeTest, replaceOperands) {
uint64_t OffsetInBits = 4;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
unsigned RuntimeLang = 6;
+ std::optional<uint32_t> EnumKind = 1;
StringRef Identifier = "some id";
- auto *N = DICompositeType::get(
- Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier);
+ auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, nullptr, RuntimeLang,
+ EnumKind, nullptr, nullptr, Identifier);
auto *Elements = MDTuple::getDistinct(Context, {});
EXPECT_EQ(nullptr, N->getElements().get());
@@ -2188,6 +2200,7 @@ TEST_F(DICompositeTypeTest, variant_part) {
uint64_t OffsetInBits = 4;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(5);
unsigned RuntimeLang = 6;
+ std::optional<uint32_t> EnumKind = 1;
StringRef Identifier = "some id";
DIDerivedType *Discriminator = cast<DIDerivedType>(getDerivedType());
DIDerivedType *Discriminator2 = cast<DIDerivedType>(getDerivedType());
@@ -2196,22 +2209,22 @@ TEST_F(DICompositeTypeTest, variant_part) {
auto *N = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- Discriminator);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, Discriminator);
// Test the hashing.
auto *Same = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- Discriminator);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, Discriminator);
auto *Other = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- Discriminator2);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, Discriminator2);
auto *NoDisc = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr);
EXPECT_EQ(N, Same);
EXPECT_NE(Same, Other);
@@ -2233,6 +2246,7 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
uint64_t OffsetInBits = 4;
DINode::DIFlags Flags = static_cast<DINode::DIFlags>(3);
unsigned RuntimeLang = 6;
+ std::optional<uint32_t> EnumKind = 1;
StringRef Identifier = "some id";
DIType *Type = getDerivedType();
Metadata *DlVar1 = DILocalVariable::get(Context, Scope, "dl_var1", File, 8,
@@ -2257,18 +2271,18 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
ConstantAsMetadata *RankConst2 = ConstantAsMetadata::get(RankInt2);
auto *N1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DlVar1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DlVar1);
auto *Same1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DlVar1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DlVar1);
auto *Other1 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DlVar2);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DlVar2);
EXPECT_EQ(N1, Same1);
EXPECT_NE(Same1, Other1);
@@ -2276,18 +2290,18 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
auto *N2 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1);
auto *Same2 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1);
auto *Other2 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation2);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation2);
EXPECT_EQ(N2, Same2);
EXPECT_NE(Same2, Other2);
@@ -2295,18 +2309,18 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
auto *N3 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1, nullptr, nullptr, Rank1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1, nullptr, nullptr, Rank1);
auto *Same3 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1, nullptr, nullptr, Rank1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1, nullptr, nullptr, Rank1);
auto *Other3 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1, nullptr, nullptr, Rank2);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1, nullptr, nullptr, Rank2);
EXPECT_EQ(N3, Same3);
EXPECT_NE(Same3, Other3);
@@ -2314,18 +2328,18 @@ TEST_F(DICompositeTypeTest, dynamicArray) {
auto *N4 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1, nullptr, nullptr, RankConst1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1, nullptr, nullptr, RankConst1);
auto *Same4 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1, nullptr, nullptr, RankConst1);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1, nullptr, nullptr, RankConst1);
auto *Other4 = DICompositeType::get(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier,
- nullptr, DataLocation1, nullptr, nullptr, RankConst2);
+ OffsetInBits, Flags, nullptr, RuntimeLang, EnumKind, nullptr, nullptr,
+ Identifier, nullptr, DataLocation1, nullptr, nullptr, RankConst2);
EXPECT_EQ(N4, Same4);
EXPECT_NE(Same4, Other4);
diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp
index 96e863b257c95e..885ba3e2e0581c 100644
--- a/llvm/unittests/Transforms/Utils/CloningTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp
@@ -514,7 +514,8 @@ class CloneFunc : public ::testing::Test {
// cloning).
auto *StructType = DICompositeType::getDistinct(
C, dwarf::DW_TAG_structure_type, "some_struct", nullptr, 0, nullptr,
- nullptr, 32, 32, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr);
+ nullptr, 32, 32, 0, DINode::FlagZero, nullptr, 0, std::nullopt, nullptr,
+ nullptr);
auto *InlinedSP = DBuilder.createFunction(
CU, "inlined", "inlined", File, 8, FuncType, 9, DINode::FlagZero,
DISubprogram::SPFlagLocalToUnit | DISubprogram::SPFlagDefinition);
More information about the llvm-commits
mailing list