[llvm] [DebugInfo] Add an specification_of attribute to LLVM DebugInfo (PR #115362)
Augusto Noronha via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 11 11:15:45 PST 2024
https://github.com/augusto2112 updated https://github.com/llvm/llvm-project/pull/115362
>From 47f302d1ca42c9869b4eca3fee3902db23f577ab Mon Sep 17 00:00:00 2001
From: Augusto Noronha <augusto at Augustos-MacBook-Pro.local>
Date: Thu, 7 Nov 2024 11:08:32 -0800
Subject: [PATCH] [DebugInfo] Add an specification_of attribute to LLVM
DebugInfo
Add a specification_of attribute to LLVM DebugInfo, which is analogous
to DWARF's DW_AT_specification. According to the DWARF spec:
"A debugging information entry that represents a declaration that
completes another (earlier) non-defining declaration may have a
DW_AT_specification attribute whose value is a reference to the
debugging information entry representing the non-defining declaration."
This patch allows types to be specifications of other types. For
example, a templated type where the template parameters are substituted
in could be a specification of the non-substituted template type.
---
llvm/include/llvm/IR/DIBuilder.h | 5 +-
llvm/include/llvm/IR/DebugInfoMetadata.h | 52 +++++++++-------
llvm/lib/AsmParser/LLParser.cpp | 13 ++--
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 +++--
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 1 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 5 ++
llvm/lib/IR/AsmWriter.cpp | 2 +
llvm/lib/IR/DIBuilder.cpp | 4 +-
llvm/lib/IR/DebugInfoMetadata.cpp | 43 ++++++-------
llvm/lib/IR/LLVMContextImpl.h | 8 ++-
llvm/test/Assembler/debug-info.ll | 9 ++-
llvm/test/DebugInfo/AArch64/specification.ll | 31 ++++++++++
.../unittests/IR/DebugTypeODRUniquingTest.cpp | 62 +++++++++----------
13 files changed, 160 insertions(+), 91 deletions(-)
create mode 100644 llvm/test/DebugInfo/AArch64/specification.ll
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 046890d0c7e1f1..bd0cfbed874a42 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -488,6 +488,9 @@ namespace llvm {
/// \param Elements Struct elements.
/// \param RunTimeLang Optional parameter, Objective-C runtime version.
/// \param UniqueIdentifier A unique identifier for the struct.
+ /// \param SpecificationOf The type that this type completes (is a
+ /// specification of). For example, this could be a templated type whose
+ /// template parameters have been substituted in.
/// \param NumExtraInhabitants The number of extra inhabitants of the type.
/// An extra inhabitant is a bit pattern that does not represent a valid
/// value for instances of a given type. This is used by the Swift language.
@@ -496,7 +499,7 @@ namespace llvm {
uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags,
DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang = 0,
DIType *VTableHolder = nullptr, StringRef UniqueIdentifier = "",
- uint32_t NumExtraInhabitants = 0);
+ DIType *SpecificationOf = nullptr, uint32_t NumExtraInhabitants = 0);
/// Create debugging information entry for an union.
/// \param Scope Scope in which this union is defined.
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 5c8394e45c9d7f..643f242c040829 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -1201,7 +1201,7 @@ class DICompositeType : public DIType {
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File,
unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits,
- uint32_t AlignInBits, uint64_t OffsetInBits,
+ uint32_t AlignInBits, uint64_t OffsetInBits, DIType *SpecificationOf,
uint32_t NumExtraInhabitants, DIFlags Flags, DINodeArray Elements,
unsigned RuntimeLang, DIType *VTableHolder,
DITemplateParameterArray TemplateParams, StringRef Identifier,
@@ -1215,7 +1215,7 @@ class DICompositeType : public DIType {
TemplateParams.get(),
getCanonicalMDString(Context, Identifier), Discriminator,
DataLocation, Associated, Allocated, Rank, Annotations.get(),
- NumExtraInhabitants, Storage, ShouldCreate);
+ SpecificationOf, NumExtraInhabitants, Storage, ShouldCreate);
}
static DICompositeType *
getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
@@ -1225,8 +1225,9 @@ class DICompositeType : public DIType {
Metadata *VTableHolder, Metadata *TemplateParams,
MDString *Identifier, Metadata *Discriminator, Metadata *DataLocation,
Metadata *Associated, Metadata *Allocated, Metadata *Rank,
- Metadata *Annotations, uint32_t NumExtraInhabitants,
- StorageType Storage, bool ShouldCreate = true);
+ Metadata *Annotations, Metadata *SpecificationOf,
+ uint32_t NumExtraInhabitants, StorageType Storage,
+ bool ShouldCreate = true);
TempDICompositeType cloneImpl() const {
return getTemporary(
@@ -1235,7 +1236,8 @@ class DICompositeType : public DIType {
getFlags(), getElements(), getRuntimeLang(), getVTableHolder(),
getTemplateParams(), getIdentifier(), getDiscriminator(),
getRawDataLocation(), getRawAssociated(), getRawAllocated(),
- getRawRank(), getAnnotations(), getNumExtraInhabitants());
+ getRawRank(), getAnnotations(), getSpecificationOf(),
+ getNumExtraInhabitants());
}
public:
@@ -1249,11 +1251,12 @@ class DICompositeType : public DIType {
StringRef Identifier = "", DIDerivedType *Discriminator = nullptr,
Metadata *DataLocation = nullptr, Metadata *Associated = nullptr,
Metadata *Allocated = nullptr, Metadata *Rank = nullptr,
- DINodeArray Annotations = nullptr, uint32_t NumExtraInhabitants = 0),
+ DINodeArray Annotations = nullptr, DIType *SpecificationOf = nullptr,
+ uint32_t NumExtraInhabitants = 0),
(Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
- OffsetInBits, NumExtraInhabitants, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier, Discriminator, DataLocation,
- Associated, Allocated, Rank, Annotations))
+ OffsetInBits, SpecificationOf, NumExtraInhabitants, Flags, Elements,
+ RuntimeLang, VTableHolder, TemplateParams, Identifier, Discriminator,
+ DataLocation, Associated, Allocated, Rank, Annotations))
DEFINE_MDNODE_GET(
DICompositeType,
(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
@@ -1264,11 +1267,11 @@ class DICompositeType : public DIType {
Metadata *Discriminator = nullptr, Metadata *DataLocation = nullptr,
Metadata *Associated = nullptr, Metadata *Allocated = nullptr,
Metadata *Rank = nullptr, Metadata *Annotations = nullptr,
- uint32_t NumExtraInhabitants = 0),
+ Metadata *SpecificationOf = 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, NumExtraInhabitants))
+ Annotations, SpecificationOf, NumExtraInhabitants))
TempDICompositeType clone() const { return cloneImpl(); }
@@ -1283,8 +1286,9 @@ class DICompositeType : public DIType {
getODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
- uint64_t OffsetInBits, uint32_t NumExtraInhabitants, DIFlags Flags,
- Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
+ uint64_t OffsetInBits, Metadata *SpecificationOf,
+ 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);
@@ -1300,14 +1304,16 @@ class DICompositeType : public DIType {
///
/// If not \a LLVMContext::isODRUniquingDebugTypes(), this function returns
/// nullptr.
- static DICompositeType *buildODRType(
- LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
- Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
- uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
- 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);
+ static DICompositeType *
+ buildODRType(LLVMContext &Context, MDString &Identifier, unsigned Tag,
+ MDString *Name, Metadata *File, unsigned Line, Metadata *Scope,
+ Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits,
+ uint64_t OffsetInBits, Metadata *SpecificationOf,
+ uint32_t NumExtraInhabitants, DIFlags Flags, Metadata *Elements,
+ unsigned RuntimeLang, Metadata *VTableHolder,
+ Metadata *TemplateParams, Metadata *Discriminator,
+ Metadata *DataLocation, Metadata *Associated,
+ Metadata *Allocated, Metadata *Rank, Metadata *Annotations);
DIType *getBaseType() const { return cast_or_null<DIType>(getRawBaseType()); }
DINodeArray getElements() const {
@@ -1367,6 +1373,10 @@ class DICompositeType : public DIType {
return cast_or_null<MDTuple>(getRawAnnotations());
}
+ Metadata *getRawSpecificationOf() const { return getOperand(14); }
+ DIType *getSpecificationOf() const {
+ return cast_or_null<DIType>(getRawSpecificationOf());
+ }
/// Replace operands.
///
/// If this \a isUniqued() and not \a isResolved(), on a uniquing collision
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index dd1baabc7e9ac4..4bae02c069b9f9 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5437,7 +5437,8 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(allocated, MDField, ); \
OPTIONAL(rank, MDSignedOrMDField, ); \
OPTIONAL(annotations, MDField, ); \
- OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX));
+ OPTIONAL(num_extra_inhabitants, MDUnsignedField, (0, UINT32_MAX)); \
+ OPTIONAL(specification_of, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
@@ -5453,10 +5454,10 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
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,
- 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)) {
+ specification_of.Val, num_extra_inhabitants.Val, flags.Val,
+ elements.Val, runtimeLang.Val, vtableHolder.Val, templateParams.Val,
+ discriminator.Val, dataLocation.Val, associated.Val, allocated.Val,
+ Rank, annotations.Val)) {
Result = CT;
return false;
}
@@ -5469,7 +5470,7 @@ bool LLParser::parseDICompositeType(MDNode *&Result, bool IsDistinct) {
size.Val, align.Val, offset.Val, flags.Val, elements.Val,
runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val,
discriminator.Val, dataLocation.Val, associated.Val, allocated.Val, Rank,
- annotations.Val, num_extra_inhabitants.Val));
+ annotations.Val, specification_of.Val, num_extra_inhabitants.Val));
return false;
}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 8ca46a4ce821a5..b4936870d7a6df 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() > 23)
+ if (Record.size() < 16 || Record.size() > 24)
return error("Invalid record");
// If we have a UUID and this is not a forward declaration, lookup the
@@ -1630,6 +1630,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Metadata *Allocated = nullptr;
Metadata *Rank = nullptr;
Metadata *Annotations = nullptr;
+ Metadata *SpecificationOf = nullptr;
auto *Identifier = getMDString(Record[15]);
// If this module is being parsed so that it can be ThinLTO imported
// into another module, composite types only need to be imported as
@@ -1678,14 +1679,18 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
if (Record.size() > 21) {
Annotations = getMDOrNull(Record[21]);
}
+ if (Record.size() > 23) {
+ SpecificationOf = getMDOrNull(Record[23]);
+ }
}
DICompositeType *CT = nullptr;
if (Identifier)
CT = DICompositeType::buildODRType(
Context, *Identifier, Tag, Name, File, Line, Scope, BaseType,
- SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants, Flags,
- Elements, RuntimeLang, VTableHolder, TemplateParams, Discriminator,
- DataLocation, Associated, Allocated, Rank, Annotations);
+ SizeInBits, AlignInBits, OffsetInBits, SpecificationOf,
+ NumExtraInhabitants, Flags, Elements, RuntimeLang, VTableHolder,
+ TemplateParams, Discriminator, DataLocation, Associated, Allocated,
+ Rank, Annotations);
// Create a node if we didn't get a lazy ODR type.
if (!CT)
@@ -1694,7 +1699,8 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
SizeInBits, AlignInBits, OffsetInBits, Flags,
Elements, RuntimeLang, VTableHolder, TemplateParams,
Identifier, Discriminator, DataLocation, Associated,
- Allocated, Rank, Annotations, NumExtraInhabitants));
+ Allocated, Rank, Annotations, SpecificationOf,
+ 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 de01750857bba3..97994b0e913508 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1947,6 +1947,7 @@ void ModuleBitcodeWriter::writeDICompositeType(
Record.push_back(VE.getMetadataOrNullID(N->getRawRank()));
Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get()));
Record.push_back(N->getNumExtraInhabitants());
+ Record.push_back(VE.getMetadataOrNullID(N->getRawSpecificationOf()));
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 c6d9fcfb0b76c1..0e6ef631bff0f9 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1043,6 +1043,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addUInt(Buffer, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1,
CC);
}
+
+ if (auto *SpecifiedFrom = CTy->getSpecificationOf())
+ addDIEEntry(Buffer, dwarf::DW_AT_specification,
+ *getOrCreateContextDIE(SpecifiedFrom));
+
break;
}
default:
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 8716a7ce2aec36..1cad4be4db73e3 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2235,6 +2235,8 @@ static void writeDICompositeType(raw_ostream &Out, const DICompositeType *N,
else
Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true);
Printer.printMetadata("annotations", N->getRawAnnotations());
+ if (auto *SpecificationOf = N->getRawSpecificationOf())
+ Printer.printMetadata("specification_of", SpecificationOf);
Out << ")";
}
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index 3d8e12e95b774f..ecf394e103309b 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -521,13 +521,13 @@ DICompositeType *DIBuilder::createStructType(
DIScope *Context, StringRef Name, DIFile *File, unsigned LineNumber,
uint64_t SizeInBits, uint32_t AlignInBits, DINode::DIFlags Flags,
DIType *DerivedFrom, DINodeArray Elements, unsigned RunTimeLang,
- DIType *VTableHolder, StringRef UniqueIdentifier,
+ DIType *VTableHolder, StringRef UniqueIdentifier, DIType *SpecificationOf,
uint32_t NumExtraInhabitants) {
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,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, SpecificationOf,
NumExtraInhabitants);
trackIfUnresolved(R);
return R;
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index f7268a51406283..a06db3f8387136 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -770,21 +770,21 @@ DICompositeType *DICompositeType::getImpl(
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated, Metadata *Allocated,
- Metadata *Rank, Metadata *Annotations, uint32_t NumExtraInhabitants,
- StorageType Storage, bool ShouldCreate) {
+ Metadata *Rank, Metadata *Annotations, Metadata *SpecificationOf,
+ uint32_t NumExtraInhabitants, StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType.
- DEFINE_GETIMPL_LOOKUP(DICompositeType,
- (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
- AlignInBits, OffsetInBits, Flags, Elements,
- RuntimeLang, VTableHolder, TemplateParams, Identifier,
- Discriminator, DataLocation, Associated, Allocated,
- Rank, Annotations, NumExtraInhabitants));
+ DEFINE_GETIMPL_LOOKUP(
+ DICompositeType,
+ (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder, TemplateParams,
+ Identifier, Discriminator, DataLocation, Associated, Allocated, Rank,
+ Annotations, SpecificationOf, NumExtraInhabitants));
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, Identifier,
Discriminator, DataLocation, Associated, Allocated,
- Rank, Annotations};
+ Rank, Annotations, SpecificationOf};
DEFINE_GETIMPL_STORE(DICompositeType,
(Tag, Line, RuntimeLang, SizeInBits, AlignInBits,
OffsetInBits, NumExtraInhabitants, Flags),
@@ -795,10 +795,11 @@ DICompositeType *DICompositeType::buildODRType(
LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
- uint32_t NumExtraInhabitants, DIFlags Flags, Metadata *Elements,
- unsigned RuntimeLang, Metadata *VTableHolder, Metadata *TemplateParams,
- Metadata *Discriminator, Metadata *DataLocation, Metadata *Associated,
- Metadata *Allocated, Metadata *Rank, Metadata *Annotations) {
+ Metadata *SpecificationOf, 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) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -809,8 +810,7 @@ DICompositeType *DICompositeType::buildODRType(
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
VTableHolder, TemplateParams, &Identifier, Discriminator,
DataLocation, Associated, Allocated, Rank, Annotations,
- NumExtraInhabitants);
-
+ SpecificationOf, NumExtraInhabitants);
if (CT->getTag() != Tag)
return nullptr;
@@ -825,7 +825,7 @@ DICompositeType *DICompositeType::buildODRType(
Metadata *Ops[] = {File, Scope, Name, BaseType,
Elements, VTableHolder, TemplateParams, &Identifier,
Discriminator, DataLocation, Associated, Allocated,
- Rank, Annotations};
+ Rank, Annotations, SpecificationOf};
assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
"Mismatched number of operands");
for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@@ -838,10 +838,11 @@ DICompositeType *DICompositeType::getODRType(
LLVMContext &Context, MDString &Identifier, unsigned Tag, MDString *Name,
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
- 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 *SpecificationOf, 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) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -851,7 +852,7 @@ DICompositeType *DICompositeType::getODRType(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
TemplateParams, &Identifier, Discriminator, DataLocation, Associated,
- Allocated, Rank, Annotations, NumExtraInhabitants);
+ Allocated, Rank, Annotations, SpecificationOf, NumExtraInhabitants);
} else {
if (CT->getTag() != Tag)
return nullptr;
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 1912b1a6b7f3df..ea2a34532374a8 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -655,6 +655,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Metadata *Allocated;
Metadata *Rank;
Metadata *Annotations;
+ Metadata *SpecificationOf;
uint32_t NumExtraInhabitants;
MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,
@@ -665,7 +666,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
MDString *Identifier, Metadata *Discriminator,
Metadata *DataLocation, Metadata *Associated,
Metadata *Allocated, Metadata *Rank, Metadata *Annotations,
- uint32_t NumExtraInhabitants)
+ Metadata *SpecificationOf, uint32_t NumExtraInhabitants)
: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),
BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),
AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),
@@ -673,7 +674,8 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
TemplateParams(TemplateParams), Identifier(Identifier),
Discriminator(Discriminator), DataLocation(DataLocation),
Associated(Associated), Allocated(Allocated), Rank(Rank),
- Annotations(Annotations), NumExtraInhabitants(NumExtraInhabitants) {}
+ Annotations(Annotations), SpecificationOf(SpecificationOf),
+ NumExtraInhabitants(NumExtraInhabitants) {}
MDNodeKeyImpl(const DICompositeType *N)
: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),
Line(N->getLine()), Scope(N->getRawScope()),
@@ -687,6 +689,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
DataLocation(N->getRawDataLocation()),
Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()),
Rank(N->getRawRank()), Annotations(N->getRawAnnotations()),
+ SpecificationOf(N->getSpecificationOf()),
NumExtraInhabitants(N->getNumExtraInhabitants()) {}
bool isKeyOf(const DICompositeType *RHS) const {
@@ -706,6 +709,7 @@ template <> struct MDNodeKeyImpl<DICompositeType> {
Associated == RHS->getRawAssociated() &&
Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank() &&
Annotations == RHS->getRawAnnotations() &&
+ SpecificationOf == RHS->getSpecificationOf() &&
NumExtraInhabitants == RHS->getNumExtraInhabitants();
}
diff --git a/llvm/test/Assembler/debug-info.ll b/llvm/test/Assembler/debug-info.ll
index 7faaf50496def9..89500e73489442 100644
--- a/llvm/test/Assembler/debug-info.ll
+++ b/llvm/test/Assembler/debug-info.ll
@@ -1,8 +1,8 @@
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; RUN: verify-uselistorder %s
-; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45}
-!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46, !47, !48}
+; CHECK: !named = !{!0, !0, !1, !2, !3, !4, !5, !6, !7, !8, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46, !47}
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25, !26, !27, !28, !29, !30, !31, !32, !33, !34, !35, !36, !37, !38, !39, !40, !41, !42, !43, !44, !45, !46, !47, !48, !49, !50}
; CHECK: !0 = !DISubrange(count: 3, lowerBound: 0)
; CHECK-NEXT: !1 = !DISubrange(count: 3, lowerBound: 4)
@@ -117,3 +117,8 @@
;CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "ExtraInhabitantCompositeType", file: !10, size: 64, num_extra_inhabitants: 66, identifier: "MangledExtraInhabitantCompositeType")
!48 = !DICompositeType(tag: DW_TAG_structure_type, name: "ExtraInhabitantCompositeType", file: !12, size: 64, num_extra_inhabitants: 66, identifier: "MangledExtraInhabitantCompositeType")
+
+!49 = !DICompositeType(tag: DW_TAG_structure_type, name: "BaseType", file: !12, size: 64, identifier: "BaseType")
+
+; CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "SpecificationType", file: !10, size: 64, identifier: "SpecificationType", specification_of: !46)
+!50 = !DICompositeType(tag: DW_TAG_structure_type, name: "SpecificationType", file: !12, size: 64, identifier: "SpecificationType", specification_of: !49)
diff --git a/llvm/test/DebugInfo/AArch64/specification.ll b/llvm/test/DebugInfo/AArch64/specification.ll
new file mode 100644
index 00000000000000..2ae17ca9d2fb4e
--- /dev/null
+++ b/llvm/test/DebugInfo/AArch64/specification.ll
@@ -0,0 +1,31 @@
+; RUN: llc %s -filetype=obj -mtriple arm64e-apple-darwin -o - \
+; RUN: | llvm-dwarfdump - | FileCheck %s
+
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_AT_specification ({{.*}} "BaseType")
+; CHECK: DW_AT_name ("SpecificationType")
+; CHECK: DW_AT_byte_size (0x08)
+
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_AT_name ("BaseType")
+; CHECK: DW_AT_byte_size (0x08)
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+ at p = common global i8* null, align 8, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!6, !7}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 1, type: !11, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug, globals: !5)
+!3 = !DIFile(filename: "/tmp/p.c", directory: "/")
+!4 = !{}
+!5 = !{!0}
+!6 = !{i32 2, !"Dwarf Version", i32 4}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+
+!10 = !DICompositeType(tag: DW_TAG_structure_type, name: "BaseType", file: !3, size: 64, identifier: "BaseType")
+
+!11 = !DICompositeType(tag: DW_TAG_structure_type, name: "SpecificationType", file: !3, size: 64, identifier: "SpecificationType", specification_of: !10)
diff --git a/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp b/llvm/unittests/IR/DebugTypeODRUniquingTest.cpp
index e9f8146df75742..7180b8183c50a7 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, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
// Enable the mapping. There still shouldn't be a type.
Context.enableDebugTypeODRUniquing();
@@ -40,23 +40,23 @@ 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, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero, nullptr, 0, 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.
EXPECT_EQ(&CT, DICompositeType::getODRTypeIfExists(Context, UUID));
EXPECT_EQ(&CT, DICompositeType::getODRType(
Context, UUID, dwarf::DW_TAG_class_type, nullptr, nullptr,
- 0, nullptr, nullptr, 0, 0, 0, 0, DINode::FlagZero, nullptr,
- 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr));
+ 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero,
+ nullptr, 0, 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, 0, DINode::FlagZero, nullptr, 0, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
+ 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,43 @@ 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, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr);
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, 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, 0, DINode::FlagFwdDecl,
- nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr));
+ 0, nullptr, nullptr, 0, 0, 0, nullptr, 0,
+ DINode::FlagFwdDecl, nullptr, 0, 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, 0, DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
+ nullptr, 0, 0, 0, nullptr, 0, DINode::FlagFwdDecl, nullptr, 0, 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, 0, DINode::FlagZero, nullptr,
- 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr));
+ 0, nullptr, nullptr, 0, 0, 0, nullptr, 0, DINode::FlagZero,
+ nullptr, 0, 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, 0, DINode::FlagFwdDecl,
- nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr));
+ 0, nullptr, nullptr, 0, 0, 0, nullptr, 0,
+ DINode::FlagFwdDecl, nullptr, 0, 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, 0, DINode::FlagZero,
- nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr));
+ 111u, nullptr, nullptr, 0, 0, 0, nullptr, 0,
+ DINode::FlagZero, nullptr, 0, nullptr, nullptr, nullptr,
+ nullptr, nullptr, nullptr, nullptr, nullptr));
EXPECT_NE(111u, CT.getLine());
}
@@ -122,8 +122,8 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
// Build an ODR type that's a forward decl with no other fields set.
MDString &UUID = *MDString::get(Context, "UUID");
auto &CT = *DICompositeType::buildODRType(
- Context, UUID, 0, nullptr, nullptr, 0, nullptr, nullptr, 0, 0, 0, 0,
- DINode::FlagFwdDecl, nullptr, 0, nullptr, nullptr, nullptr, nullptr,
+ 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);
// Create macros for running through all the fields except Identifier and Flags.
@@ -155,10 +155,10 @@ TEST(DebugTypeODRUniquingTest, buildODRTypeFields) {
// Replace all the fields with new values that are distinct from each other.
EXPECT_EQ(&CT, DICompositeType::buildODRType(
Context, UUID, 0, Name, File, Line, Scope, BaseType,
- SizeInBits, AlignInBits, OffsetInBits, NumExtraInhabitants,
- DINode::FlagArtificial, Elements, RuntimeLang,
- VTableHolder, TemplateParams, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr));
+ SizeInBits, AlignInBits, OffsetInBits, nullptr,
+ NumExtraInhabitants, DINode::FlagArtificial, Elements,
+ RuntimeLang, 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());
More information about the llvm-commits
mailing list