[clang] [llvm] [DebugInfo][BPF] Add 'btf:type_tag' annotation in DWARF (PR #91423)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 5 00:01:54 PDT 2024
https://github.com/eddyz87 updated https://github.com/llvm/llvm-project/pull/91423
>From 4b35b0a87ba70815f9647be8a43c91e496d2b5ea Mon Sep 17 00:00:00 2001
From: Eduard Zingerman <eddyz87 at gmail.com>
Date: Tue, 14 Feb 2023 00:49:33 +0200
Subject: [PATCH 1/3] [DebugInfo][BPF] Add 'annotations' field for DIBasicType
& DISubroutineType
Extend DIBasicType and DISubroutineType with additional field
'annotations', e.g. as below:
!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !6)
!6 = !{!7}
!7 = !{!"btf:type_tag", !"tag1"}
The field would be used by BPF backend to generate DWARF attributes
corresponding to "btf_type_tag" type attributes, e.g.:
0x00000029: DW_TAG_base_type
DW_AT_name ("int")
DW_AT_encoding (DW_ATE_signed)
DW_AT_byte_size (0x04)
0x0000002d: DW_TAG_LLVM_annotation
DW_AT_name ("btf:type_tag")
DW_AT_const_value ("tag1")
Such DWARF entries would be used to generate BTF definitions by tools
like pahole [1].
Note: similar fields with similar purposes are already present in
DIDerivedType and DICompositeType.
Currently "btf_type_tag" attributes are represented in debug
information as 'annotations' fields in DIDerivedType with
DW_TAG_pointer_type tag. The annotation on a pointer corresponds to
pointee having the attributes in the final BTF.
The discussion at [2] came to conclusion, that such annotations should
apply to the annotated type itself. Hence the necessity to extend
DIBasicType & DISubroutineType types with 'annotations' field to
represent cases like below:
int __attribute__((btf_type_tag("foo"))) bar;
[1] https://github.com/acmel/dwarves
[2] https://lore.kernel.org/bpf/87r0w9jjoq.fsf@oracle.com/
This was previously tracked as differential revision:
https://reviews.llvm.org/D143966
---
llvm/include/llvm/IR/DebugInfoMetadata.h | 80 ++++++++---
llvm/lib/AsmParser/LLParser.cpp | 17 ++-
llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 ++-
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 +
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 6 +-
llvm/lib/IR/AsmWriter.cpp | 6 +-
llvm/lib/IR/DebugInfoMetadata.cpp | 15 +-
llvm/lib/IR/LLVMContextImpl.h | 30 ++--
llvm/test/Bitcode/attr-btf_tag-dibasic.ll | 36 +++++
.../test/Bitcode/attr-btf_tag-disubroutine.ll | 41 ++++++
llvm/test/DebugInfo/attr-btf_type_tag.ll | 136 +++++++++++++-----
11 files changed, 295 insertions(+), 90 deletions(-)
create mode 100644 llvm/test/Bitcode/attr-btf_tag-dibasic.ll
create mode 100644 llvm/test/Bitcode/attr-btf_tag-disubroutine.ll
diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 18873a551595a..c98f0305c1c3f 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -828,40 +828,45 @@ class DIBasicType : public DIType {
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
StringRef Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
- DIFlags Flags, StorageType Storage,
- bool ShouldCreate = true) {
+ DIFlags Flags, DINodeArray Annotations,
+ StorageType Storage, bool ShouldCreate = true) {
return getImpl(Context, Tag, getCanonicalMDString(Context, Name),
- SizeInBits, AlignInBits, Encoding, Flags, Storage,
- ShouldCreate);
+ SizeInBits, AlignInBits, Encoding, Flags, Annotations.get(),
+ Storage, ShouldCreate);
}
static DIBasicType *getImpl(LLVMContext &Context, unsigned Tag,
MDString *Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
- DIFlags Flags, StorageType Storage,
- bool ShouldCreate = true);
+ DIFlags Flags, Metadata *Annotations,
+ StorageType Storage, bool ShouldCreate = true);
TempDIBasicType cloneImpl() const {
return getTemporary(getContext(), getTag(), getName(), getSizeInBits(),
- getAlignInBits(), getEncoding(), getFlags());
+ getAlignInBits(), getEncoding(), getFlags(),
+ getAnnotations());
}
public:
DEFINE_MDNODE_GET(DIBasicType, (unsigned Tag, StringRef Name),
- (Tag, Name, 0, 0, 0, FlagZero))
+ (Tag, Name, 0, 0, 0, FlagZero, {}))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, StringRef Name, uint64_t SizeInBits),
- (Tag, Name, SizeInBits, 0, 0, FlagZero))
+ (Tag, Name, SizeInBits, 0, 0, FlagZero, {}))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, MDString *Name, uint64_t SizeInBits),
- (Tag, Name, SizeInBits, 0, 0, FlagZero))
+ (Tag, Name, SizeInBits, 0, 0, FlagZero, {}))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, StringRef Name, uint64_t SizeInBits,
- uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
- (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
+ uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
+ DINodeArray Annotations = {}),
+ (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags,
+ Annotations))
DEFINE_MDNODE_GET(DIBasicType,
(unsigned Tag, MDString *Name, uint64_t SizeInBits,
- uint32_t AlignInBits, unsigned Encoding, DIFlags Flags),
- (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags))
+ uint32_t AlignInBits, unsigned Encoding, DIFlags Flags,
+ Metadata *Annotations = nullptr),
+ (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags,
+ Annotations))
TempDIBasicType clone() const { return cloneImpl(); }
@@ -873,6 +878,16 @@ class DIBasicType : public DIType {
/// neither signed nor unsigned.
std::optional<Signedness> getSignedness() const;
+ Metadata *getRawAnnotations() const { return getOperand(3); }
+
+ DINodeArray getAnnotations() const {
+ return cast_or_null<MDTuple>(getRawAnnotations());
+ }
+
+ void replaceAnnotations(DINodeArray Annotations) {
+ replaceOperandWith(3, Annotations.get());
+ }
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DIBasicTypeKind;
}
@@ -1112,6 +1127,10 @@ class DIDerivedType : public DIType {
}
Metadata *getRawAnnotations() const { return getOperand(5); }
+ void replaceAnnotations(DINodeArray Annotations) {
+ replaceOperandWith(5, Annotations.get());
+ }
+
/// Get casted version of extra data.
/// @{
DIType *getClassType() const;
@@ -1339,6 +1358,10 @@ class DICompositeType : public DIType {
return cast_or_null<MDTuple>(getRawAnnotations());
}
+ void replaceAnnotations(DINodeArray Annotations) {
+ replaceOperandWith(13, Annotations.get());
+ }
+
/// Replace operands.
///
/// If this \a isUniqued() and not \a isResolved(), on a uniquing collision
@@ -1385,26 +1408,30 @@ class DISubroutineType : public DIType {
static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags,
uint8_t CC, DITypeRefArray TypeArray,
- StorageType Storage,
+ DINodeArray Annotations, StorageType Storage,
bool ShouldCreate = true) {
- return getImpl(Context, Flags, CC, TypeArray.get(), Storage, ShouldCreate);
+ return getImpl(Context, Flags, CC, TypeArray.get(), Annotations.get(),
+ Storage, ShouldCreate);
}
static DISubroutineType *getImpl(LLVMContext &Context, DIFlags Flags,
uint8_t CC, Metadata *TypeArray,
- StorageType Storage,
+ Metadata *Annotations, StorageType Storage,
bool ShouldCreate = true);
TempDISubroutineType cloneImpl() const {
- return getTemporary(getContext(), getFlags(), getCC(), getTypeArray());
+ return getTemporary(getContext(), getFlags(), getCC(), getTypeArray(),
+ getAnnotations());
}
public:
DEFINE_MDNODE_GET(DISubroutineType,
- (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray),
- (Flags, CC, TypeArray))
+ (DIFlags Flags, uint8_t CC, DITypeRefArray TypeArray,
+ DINodeArray Annotations = nullptr),
+ (Flags, CC, TypeArray, Annotations))
DEFINE_MDNODE_GET(DISubroutineType,
- (DIFlags Flags, uint8_t CC, Metadata *TypeArray),
- (Flags, CC, TypeArray))
+ (DIFlags Flags, uint8_t CC, Metadata *TypeArray,
+ Metadata *Annotations = nullptr),
+ (Flags, CC, TypeArray, Annotations))
TempDISubroutineType clone() const { return cloneImpl(); }
// Returns a new temporary DISubroutineType with updated CC
@@ -1422,6 +1449,15 @@ class DISubroutineType : public DIType {
Metadata *getRawTypeArray() const { return getOperand(3); }
+ Metadata *getRawAnnotations() const { return getOperand(4); }
+ DINodeArray getAnnotations() const {
+ return cast_or_null<MDTuple>(getRawAnnotations());
+ }
+
+ void replaceAnnotations(DINodeArray Annotations) {
+ replaceOperandWith(4, Annotations.get());
+ }
+
static bool classof(const Metadata *MD) {
return MD->getMetadataID() == DISubroutineTypeKind;
}
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 07c8aa23fc5e2..3f146480312c6 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5248,7 +5248,7 @@ bool LLParser::parseDIEnumerator(MDNode *&Result, bool IsDistinct) {
/// parseDIBasicType:
/// ::= !DIBasicType(tag: DW_TAG_base_type, name: "int", size: 32, align: 32,
-/// encoding: DW_ATE_encoding, flags: 0)
+/// encoding: DW_ATE_encoding, flags: 0, annotations: !1)
bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
OPTIONAL(tag, DwarfTagField, (dwarf::DW_TAG_base_type)); \
@@ -5256,12 +5256,14 @@ bool LLParser::parseDIBasicType(MDNode *&Result, bool IsDistinct) {
OPTIONAL(size, MDUnsignedField, (0, UINT64_MAX)); \
OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \
OPTIONAL(encoding, DwarfAttEncodingField, ); \
- OPTIONAL(flags, DIFlagField, );
+ OPTIONAL(flags, DIFlagField, ); \
+ OPTIONAL(annotations, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
- Result = GET_OR_DISTINCT(DIBasicType, (Context, tag.Val, name.Val, size.Val,
- align.Val, encoding.Val, flags.Val));
+ Result = GET_OR_DISTINCT(DIBasicType,
+ (Context, tag.Val, name.Val, size.Val, align.Val,
+ encoding.Val, flags.Val, annotations.Val));
return false;
}
@@ -5398,12 +5400,13 @@ bool LLParser::parseDISubroutineType(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
OPTIONAL(flags, DIFlagField, ); \
OPTIONAL(cc, DwarfCCField, ); \
- REQUIRED(types, MDField, );
+ REQUIRED(types, MDField, ); \
+ OPTIONAL(annotations, MDField, );
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
- Result = GET_OR_DISTINCT(DISubroutineType,
- (Context, flags.Val, cc.Val, types.Val));
+ Result = GET_OR_DISTINCT(DISubroutineType, (Context, flags.Val, cc.Val,
+ types.Val, annotations.Val));
return false;
}
diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
index 9102f3a60cffc..bc06c55f1662c 100644
--- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
+++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp
@@ -1527,7 +1527,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_BASIC_TYPE: {
- if (Record.size() < 6 || Record.size() > 7)
+ if (Record.size() < 6 || Record.size() > 8)
return error("Invalid record");
IsDistinct = Record[0];
@@ -1535,10 +1535,14 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
? static_cast<DINode::DIFlags>(Record[6])
: DINode::FlagZero;
+ Metadata *Annotations = nullptr;
+ if (Record.size() > 7 && Record[7])
+ Annotations = getMDOrNull(Record[7]);
+
MetadataList.assignValue(
GET_OR_DISTINCT(DIBasicType,
(Context, Record[1], getMDString(Record[2]), Record[3],
- Record[4], Record[5], Flags)),
+ Record[4], Record[5], Flags, Annotations)),
NextMetadataNo);
NextMetadataNo++;
break;
@@ -1703,7 +1707,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
break;
}
case bitc::METADATA_SUBROUTINE_TYPE: {
- if (Record.size() < 3 || Record.size() > 4)
+ if (Record.size() < 3 || Record.size() > 5)
return error("Invalid record");
bool IsOldTypeRefArray = Record[0] < 2;
unsigned CC = (Record.size() > 3) ? Record[3] : 0;
@@ -1713,9 +1717,13 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Metadata *Types = getMDOrNull(Record[2]);
if (LLVM_UNLIKELY(IsOldTypeRefArray))
Types = MetadataList.upgradeTypeRefArray(Types);
+ Metadata *Annotations = nullptr;
+ if (Record.size() > 4 && Record[4])
+ Annotations = getMDOrNull(Record[4]);
MetadataList.assignValue(
- GET_OR_DISTINCT(DISubroutineType, (Context, Flags, CC, Types)),
+ GET_OR_DISTINCT(DISubroutineType,
+ (Context, Flags, CC, Types, Annotations)),
NextMetadataNo);
NextMetadataNo++;
break;
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 3c99bde278392..0a48922a42c4b 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -1826,6 +1826,7 @@ void ModuleBitcodeWriter::writeDIBasicType(const DIBasicType *N,
Record.push_back(N->getAlignInBits());
Record.push_back(N->getEncoding());
Record.push_back(N->getFlags());
+ Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations()));
Stream.EmitRecord(bitc::METADATA_BASIC_TYPE, Record, Abbrev);
Record.clear();
@@ -1921,6 +1922,7 @@ void ModuleBitcodeWriter::writeDISubroutineType(
Record.push_back(N->getFlags());
Record.push_back(VE.getMetadataOrNullID(N->getTypeArray().get()));
Record.push_back(N->getCC());
+ Record.push_back(VE.getMetadataOrNullID(N->getRawAnnotations()));
Stream.EmitRecord(bitc::METADATA_SUBROUTINE_TYPE, Record, Abbrev);
Record.clear();
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 6c04fa1c67a95..08be3a51862ca 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -712,7 +712,9 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) {
if (!Name.empty())
addString(Buffer, dwarf::DW_AT_name, Name);
- // An unspecified type only has a name attribute.
+ addAnnotation(Buffer, BTy->getAnnotations());
+
+ // An unspecified type only has a name attribute & annotations.
if (BTy->getTag() == dwarf::DW_TAG_unspecified_type)
return;
@@ -881,6 +883,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) {
if (CTy->isRValueReference())
addFlag(Buffer, dwarf::DW_AT_rvalue_reference);
+
+ addAnnotation(Buffer, CTy->getAnnotations());
}
void DwarfUnit::addAnnotation(DIE &Buffer, DINodeArray Annotations) {
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 7a5f18fe2cbd5..55ba180d50f7f 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2119,9 +2119,9 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N,
}
static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
- AsmWriterContext &) {
+ AsmWriterContext &WriterCtx) {
Out << "!DIBasicType(";
- MDFieldPrinter Printer(Out);
+ MDFieldPrinter Printer(Out, WriterCtx);
if (N->getTag() != dwarf::DW_TAG_base_type)
Printer.printTag(N);
Printer.printString("name", N->getName());
@@ -2130,6 +2130,7 @@ static void writeDIBasicType(raw_ostream &Out, const DIBasicType *N,
Printer.printDwarfEnum("encoding", N->getEncoding(),
dwarf::AttributeEncodingString);
Printer.printDIFlags("flags", N->getFlags());
+ Printer.printMetadata("annotations", N->getRawAnnotations());
Out << ")";
}
@@ -2225,6 +2226,7 @@ static void writeDISubroutineType(raw_ostream &Out, const DISubroutineType *N,
Printer.printDwarfEnum("cc", N->getCC(), dwarf::ConventionString);
Printer.printMetadata("types", N->getRawTypeArray(),
/* ShouldSkipNull */ false);
+ Printer.printMetadata("annotations", N->getRawAnnotations());
Out << ")";
}
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 9bd1d7880c9f8..e0555466805ff 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -663,12 +663,12 @@ DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, const APInt &Value,
DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
MDString *Name, uint64_t SizeInBits,
uint32_t AlignInBits, unsigned Encoding,
- DIFlags Flags, StorageType Storage,
- bool ShouldCreate) {
+ DIFlags Flags, Metadata *Annotations,
+ StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIBasicType,
- (Tag, Name, SizeInBits, AlignInBits, Encoding, Flags));
- Metadata *Ops[] = {nullptr, nullptr, Name};
+ DEFINE_GETIMPL_LOOKUP(DIBasicType, (Tag, Name, SizeInBits, AlignInBits,
+ Encoding, Flags, Annotations));
+ Metadata *Ops[] = {nullptr, nullptr, Name, Annotations};
DEFINE_GETIMPL_STORE(DIBasicType,
(Tag, SizeInBits, AlignInBits, Encoding, Flags), Ops);
}
@@ -872,10 +872,11 @@ DISubroutineType::DISubroutineType(LLVMContext &C, StorageType Storage,
DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
uint8_t CC, Metadata *TypeArray,
+ Metadata *Annotations,
StorageType Storage,
bool ShouldCreate) {
- DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray));
- Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray};
+ DEFINE_GETIMPL_LOOKUP(DISubroutineType, (Flags, CC, TypeArray, Annotations));
+ Metadata *Ops[] = {nullptr, nullptr, nullptr, TypeArray, Annotations};
DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);
}
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 392e0d16f1761..8fb55d9c719d1 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -465,25 +465,29 @@ template <> struct MDNodeKeyImpl<DIBasicType> {
uint32_t AlignInBits;
unsigned Encoding;
unsigned Flags;
+ Metadata *Annotations;
MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits,
- uint32_t AlignInBits, unsigned Encoding, unsigned Flags)
+ uint32_t AlignInBits, unsigned Encoding, unsigned Flags,
+ Metadata *Annotations)
: Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),
- Encoding(Encoding), Flags(Flags) {}
+ Encoding(Encoding), Flags(Flags), Annotations(Annotations) {}
MDNodeKeyImpl(const DIBasicType *N)
: Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()),
AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()),
- Flags(N->getFlags()) {}
+ Flags(N->getFlags()), Annotations(N->getRawAnnotations()) {}
bool isKeyOf(const DIBasicType *RHS) const {
return Tag == RHS->getTag() && Name == RHS->getRawName() &&
SizeInBits == RHS->getSizeInBits() &&
AlignInBits == RHS->getAlignInBits() &&
- Encoding == RHS->getEncoding() && Flags == RHS->getFlags();
+ Encoding == RHS->getEncoding() && Flags == RHS->getFlags() &&
+ Annotations == RHS->getRawAnnotations();
}
unsigned getHashValue() const {
- return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);
+ return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding,
+ Annotations);
}
};
@@ -712,18 +716,24 @@ template <> struct MDNodeKeyImpl<DISubroutineType> {
unsigned Flags;
uint8_t CC;
Metadata *TypeArray;
+ Metadata *Annotations;
- MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)
- : Flags(Flags), CC(CC), TypeArray(TypeArray) {}
+ MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray,
+ Metadata *Annotations)
+ : Flags(Flags), CC(CC), TypeArray(TypeArray), Annotations(Annotations) {}
MDNodeKeyImpl(const DISubroutineType *N)
- : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}
+ : Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()),
+ Annotations(N->getRawAnnotations()) {}
bool isKeyOf(const DISubroutineType *RHS) const {
return Flags == RHS->getFlags() && CC == RHS->getCC() &&
- TypeArray == RHS->getRawTypeArray();
+ TypeArray == RHS->getRawTypeArray() &&
+ Annotations == RHS->getRawAnnotations();
}
- unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }
+ unsigned getHashValue() const {
+ return hash_combine(Flags, CC, TypeArray, Annotations);
+ }
};
template <> struct MDNodeKeyImpl<DIFile> {
diff --git a/llvm/test/Bitcode/attr-btf_tag-dibasic.ll b/llvm/test/Bitcode/attr-btf_tag-dibasic.ll
new file mode 100644
index 0000000000000..7a73f921466d9
--- /dev/null
+++ b/llvm/test/Bitcode/attr-btf_tag-dibasic.ll
@@ -0,0 +1,36 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+;
+; Source:
+; #define __tag1 __attribute__((btf_type_tag("tag1")))
+; int __tag1 g;
+; Compilation flag:
+; clang -S -g -emit-llvm test.c
+
+ at g = dso_local global i32 0, align 4, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!8, !9, !10, !11, !12, !13, !14}
+!llvm.ident = !{!15}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "79feb01d60b549b43abc493c324fe2a8")
+!4 = !{!0}
+!5 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !6)
+!6 = !{!7}
+!7 = !{!"btf:type_tag", !"tag1"}
+
+; CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+; CHECK: ![[L1]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L2:[0-9]+]])
+; CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
+; CHECK: ![[L3]] = !{!"btf:type_tag", !"tag1"}
+
+!8 = !{i32 7, !"Dwarf Version", i32 5}
+!9 = !{i32 2, !"Debug Info Version", i32 3}
+!10 = !{i32 1, !"wchar_size", i32 4}
+!11 = !{i32 8, !"PIC Level", i32 2}
+!12 = !{i32 7, !"PIE Level", i32 2}
+!13 = !{i32 7, !"uwtable", i32 2}
+!14 = !{i32 7, !"frame-pointer", i32 2}
+!15 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"}
diff --git a/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll b/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll
new file mode 100644
index 0000000000000..277348c3eb461
--- /dev/null
+++ b/llvm/test/Bitcode/attr-btf_tag-disubroutine.ll
@@ -0,0 +1,41 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+;
+; Source:
+; #define __tag1 __attribute__((btf_type_tag("tag1")))
+; int (__tag1 * g)(void);
+
+; Compilation flag:
+; clang -S -g -emit-llvm test.c
+
+ at g = dso_local global ptr null, align 8, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!11, !12, !13, !14, !15, !16, !17}
+!llvm.ident = !{!18}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !5, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "2ed8742fd12b44b948de1ac5e433bd63")
+!4 = !{!0}
+!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
+!6 = !DISubroutineType(types: !7, annotations: !9)
+!7 = !{!8}
+!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!9 = !{!10}
+!10 = !{!"btf:type_tag", !"tag1"}
+
+; CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+; CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]])
+; CHECK: ![[L2]] = !DISubroutineType(types: ![[#]], annotations: ![[L3:[0-9]+]])
+; CHECK: ![[L3]] = !{![[L4:[0-9]+]]}
+; CHECK: ![[L4]] = !{!"btf:type_tag", !"tag1"}
+
+!11 = !{i32 7, !"Dwarf Version", i32 5}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{i32 8, !"PIC Level", i32 2}
+!15 = !{i32 7, !"PIE Level", i32 2}
+!16 = !{i32 7, !"uwtable", i32 2}
+!17 = !{i32 7, !"frame-pointer", i32 2}
+!18 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git c15ba1bb9498fa04f6c374337313df43486c9713)"}
diff --git a/llvm/test/DebugInfo/attr-btf_type_tag.ll b/llvm/test/DebugInfo/attr-btf_type_tag.ll
index 47a2aa59106d1..329b95cb5d63b 100644
--- a/llvm/test/DebugInfo/attr-btf_type_tag.ll
+++ b/llvm/test/DebugInfo/attr-btf_type_tag.ll
@@ -4,59 +4,121 @@
; Source:
; #define __tag1 __attribute__((btf_type_tag("tag1")))
; #define __tag2 __attribute__((btf_type_tag("tag2")))
+; #define __tag3 __attribute__((btf_type_tag("tag3")))
+; #define __tag4 __attribute__((btf_type_tag("tag4")))
+;
+; int __tag1 a;
+; int * __tag2 b;
+; void __tag3 *c;
+; void (__tag4 *d)(void);
+;
;
-; int * __tag1 * __tag2 *g;
; Compilation flag:
; clang -target x86_64 -g -S -emit-llvm t.c
+;
+; Note: only "btf:type_tag" annotations are checked for brevity.
- at g = dso_local global ptr null, align 8, !dbg !0
+ at a = dso_local global i32 0, align 4, !dbg !0
+ at b = dso_local global ptr null, align 8, !dbg !5
+ at c = dso_local global ptr null, align 8, !dbg !11
+ at d = dso_local global ptr null, align 8, !dbg !19
!llvm.dbg.cu = !{!2}
-!llvm.module.flags = !{!13, !14, !15, !16, !17}
-!llvm.ident = !{!18}
+!llvm.module.flags = !{!31, !32, !33, !34, !35}
+!llvm.ident = !{!36}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
-!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 4, type: !5, isLocal: false, isDefinition: true)
-!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 14.0.0 (https://github.com/llvm/llvm-project.git 2c240a5eefae1a945dfd36cdaa0c677eca90dd82)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
-!3 = !DIFile(filename: "t.c", directory: "/home/yhs/work/tests/llvm/btf_tag_type")
-!4 = !{!0}
-!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64, annotations: !11)
-!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, annotations: !9)
-!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64)
+!1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 6, type: !28, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C11, file: !3, producer: "clang version 17.0.0 (https://github.com/llvm/llvm-project.git ffde01565bce81795ba0442108742557a9a4562d)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.c", directory: "/home/eddy/work/tmp", checksumkind: CSK_MD5, checksum: "71845c02e58f6b1a8b0162797b4d3f37")
+!4 = !{!0, !5, !11, !19}
+!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
+
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_name ("a")
+; CHECK-NEXT: DW_AT_type (0x[[T1:[0-9a-f]+]] "int")
+
+; CHECK: 0x[[T1]]: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name ("int")
+
+; CHECK: DW_TAG_LLVM_annotation
+; CHECK-NEXT: DW_AT_name ("btf:type_tag")
+; CHECK-NEXT: DW_AT_const_value ("tag1")
+
+!6 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 7, type: !7, isLocal: false, isDefinition: true)
+!7 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !8, size: 64, annotations: !9)
!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!9 = !{!10}
-!10 = !{!"btf_type_tag", !"tag1"}
-!11 = !{!12}
-!12 = !{!"btf_type_tag", !"tag2"}
+!10 = !{!"btf:type_tag", !"tag2"}
+!11 = !DIGlobalVariableExpression(var: !12, expr: !DIExpression())
+
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_name ("b")
+; CHECK-NEXT: DW_AT_type (0x[[T2:[0-9a-f]+]] "int *")
+
+; CHECK: 0x[[T2]]: DW_TAG_pointer_type
+; CHECK-NEXT: DW_AT_type (0x[[T3:[0-9a-f]+]] "int")
+
+; CHECK: DW_TAG_LLVM_annotation
+; CHECK-NEXT: DW_AT_name ("btf:type_tag")
+; CHECK-NEXT: DW_AT_const_value ("tag2")
+
+; CHECK: 0x[[T3]]: DW_TAG_base_type
+; CHECK-NEXT: DW_AT_name ("int")
+; CHECK-NEXT: DW_AT_encoding (DW_ATE_signed)
+
+!12 = distinct !DIGlobalVariable(name: "c", scope: !2, file: !3, line: 8, type: !13, isLocal: false, isDefinition: true)
+!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, annotations: !17)
+!14 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: !15)
+!15 = !{!16}
+!16 = !{!"btf:type_tag", !"tag3"}
+!17 = !{!18}
+!18 = !{!"btf_type_tag", !"tag3"}
+
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_name ("c")
+; CHECK-NEXT: DW_AT_type (0x[[T4:[0-9a-f]+]] "void *")
-; CHECK: DW_TAG_variable
-; CHECK-NEXT: DW_AT_name ("g")
-; CHECK-NEXT: DW_AT_type (0x[[T1:[0-9a-f]+]] "int ***")
+; CHECK: 0x[[T4]]: DW_TAG_pointer_type
+; CHECK-NEXT: DW_AT_type (0x[[T5:[0-9a-f]+]] "void")
-; CHECK: 0x[[T1]]: DW_TAG_pointer_type
-; CHECK-NEXT: DW_AT_type (0x[[T2:[0-9a-f]+]] "int **")
+; CHECK: 0x[[T5]]: DW_TAG_unspecified_type
+; CHECK-NEXT: DW_AT_name ("void")
-; CHECK: DW_TAG_LLVM_annotation
-; CHECK-NEXT: DW_AT_name ("btf_type_tag")
-; CHECK-NEXT: DW_AT_const_value ("tag2")
+; CHECK: DW_TAG_LLVM_annotation
+; CHECK-NEXT: DW_AT_name ("btf:type_tag")
+; CHECK-NEXT: DW_AT_const_value ("tag3")
-; CHECK: NULL
+!19 = !DIGlobalVariableExpression(var: !20, expr: !DIExpression())
+!20 = distinct !DIGlobalVariable(name: "d", scope: !2, file: !3, line: 9, type: !21, isLocal: false, isDefinition: true)
+!21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !22, size: 64, annotations: !26)
+!22 = !DISubroutineType(types: !23, annotations: !24)
+!23 = !{null}
+!24 = !{!25}
+!25 = !{!"btf:type_tag", !"tag4"}
+!26 = !{!27}
+!27 = !{!"btf_type_tag", !"tag4"}
+!28 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed, annotations: !29)
+!29 = !{!30}
+!30 = !{!"btf:type_tag", !"tag1"}
-; CHECK: 0x[[T2]]: DW_TAG_pointer_type
-; CHECK-NEXT: DW_AT_type (0x[[T3:[0-9a-f]+]] "int *")
+; CHECK: DW_TAG_variable
+; CHECK-NEXT: DW_AT_name ("d")
+; CHECK-NEXT: DW_AT_type (0x[[T6:[0-9a-f]+]] "void (*)(")
-; CHECK: DW_TAG_LLVM_annotation
-; CHECK-NEXT: DW_AT_name ("btf_type_tag")
-; CHECK-NEXT: DW_AT_const_value ("tag1")
+; CHECK: 0x[[T6]]: DW_TAG_pointer_type
+; CHECK-NEXT: DW_AT_type (0x[[T7:[0-9a-f]+]] "void (")
-; CHECK: NULL
+; CHECK: 0x[[T7]]: DW_TAG_subroutine_type
+; CHECK-NEXT: DW_AT_prototyped (true)
-; CHECK: 0x[[T3]]: DW_TAG_pointer_type
-; CHECK-NEXT: DW_AT_type (0x{{[0-9a-f]+}} "int")
+; CHECK: DW_TAG_LLVM_annotation
+; CHECK-NEXT: DW_AT_name ("btf:type_tag")
+; CHECK-NEXT: DW_AT_const_value ("tag4")
-!13 = !{i32 7, !"Dwarf Version", i32 4}
-!14 = !{i32 2, !"Debug Info Version", i32 3}
-!15 = !{i32 1, !"wchar_size", i32 4}
-!16 = !{i32 7, !"uwtable", i32 1}
-!17 = !{i32 7, !"frame-pointer", i32 2}
-!18 = !{!"clang version 14.0.0 (https://github.com/llvm/llvm-project.git 2c240a5eefae1a945dfd36cdaa0c677eca90dd82)"}
+!31 = !{i32 7, !"Dwarf Version", i32 5}
+!32 = !{i32 2, !"Debug Info Version", i32 3}
+!33 = !{i32 1, !"wchar_size", i32 4}
+!34 = !{i32 7, !"uwtable", i32 2}
+!35 = !{i32 7, !"frame-pointer", i32 2}
+!36 = !{!"clang version 17.0.0 (https://github.com/llvm/llvm-project.git ffde01565bce81795ba0442108742557a9a4562d)"}
>From fbc598bcb46f6029bb2285c4070b0955c164886d Mon Sep 17 00:00:00 2001
From: Eduard Zingerman <eddyz87 at gmail.com>
Date: Tue, 14 Feb 2023 01:19:50 +0200
Subject: [PATCH 2/3] [DebugInfo][BPF] Add 'btf:type_tag' annotation in DWARF
This commit is a follow-up for BPF mailing list discussion at [1].
It changes the way `__attribute__((btf_type_tag("...")))`s are
represented in DWARF.
Prior to this commit type tags could only be attached to pointers.
Such attachments associated the tags with a pointee type.
E.g. for the following C code:
int __attribute__((btf_type_tag("tag1"))) *g;
Generated DWARF looked as follows:
0x0000001e: DW_TAG_variable
DW_AT_name ("g")
DW_AT_type (0x00000029 "int *")
0x00000029: DW_TAG_pointer_type
DW_AT_type (0x00000032 "int")
0x0000002e: DW_TAG_LLVM_annotation
DW_AT_name ("btf_type_tag")
DW_AT_const_value ("tag1")
0x00000032: DW_TAG_base_type
DW_AT_name ("int")
The goal of this commit is to allow attachment of type tags to the
tagged types instead. E.g. for the same example DWARF should look as
follows:
0x0000001e: DW_TAG_variable
DW_AT_name ("g")
DW_AT_type (0x00000029 "int *")
0x00000029: DW_TAG_pointer_type
DW_AT_type (0x00000032 "int")
0x00000032: DW_TAG_base_type
DW_AT_name ("int")
0x00000036: DW_TAG_LLVM_annotation
DW_AT_name ("btf:type_tag")
DW_AT_const_value ("tag1")
A new tag name, `btf:type_tag`, is used so that DWARF consumers
could distinguish between old and new attachment semantics.
This feature is mostly used by Linux Kernel in combination with tool
named pahole [2]. Reasonably recent versions of pahole generate
errors (1.23, 1.24) or warnings (1.25) when `DW_TAG_LLVM_annotation`
is attached to `DW_TAG_base_type` or `DW_TAG_unspecified_type`.
Hence the `btf:type_tag` generation is controlled by a hidden option
`-mllvm -btf-type-tag-v2`. The goal is to provide a way for tooling to
work on adding support `btf:type_tag` and eventually replace
`btf_type_tag` by `btf:type_tag`, removing the above option.
The commit includes the following changes:
- Changes in debug info generation:
- New method `DIBuilder::createAnnotationsPlaceholder()` is added,
it creates a temporary `DIDerivedType` that plays as annotations
placeholder while debug info metadata is being constructed;
- New overload for `CGDebugInfo::CreateType` method is added:
llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty,
llvm::DIFile *Unit);
This overload collects BTF type tags in `Ty`, creates annotations
placeholder pointing to the base type of `Ty`, registers the
placeholder in the `CGDebugInfo::AnnotationsPlaceholder` vector.
- `CGDebugInfo::finalize()` is updated to do the following for each
annotation placeholder:
- clone underlying base type;
- attach annotations the clone using `replaceAnnotations()` call;
- replace all placeholder usages by a clone.
Such scheme allows to deal with type cycles.
- Changes in AST construction:
- `ASTContext::getBTFTagAttributedType()` is updated to ensure that
`BTFTagAttributedType` always wraps `QualType` w/o local
constant/volatile/restricted qualifiers. This simplifies debug info
generation.
[1] https://lore.kernel.org/bpf/87r0w9jjoq.fsf@oracle.com/
[2] https://git.kernel.org/pub/scm/devel/pahole/pahole.git/
This was previously tracked as differential revision:
https://reviews.llvm.org/D143967
---
clang/lib/CodeGen/CGDebugInfo.cpp | 204 +++++++++++++++---
clang/lib/CodeGen/CGDebugInfo.h | 3 +
.../test/CodeGen/attr-btf_type_tag-circular.c | 18 ++
clang/test/CodeGen/attr-btf_type_tag-const.c | 41 ++++
.../test/CodeGen/attr-btf_type_tag-func-ptr.c | 19 +-
clang/test/CodeGen/attr-btf_type_tag-func.c | 50 +++--
.../test/CodeGen/attr-btf_type_tag-restrict.c | 21 ++
.../CodeGen/attr-btf_type_tag-similar-type.c | 47 ++--
.../CodeGen/attr-btf_type_tag-typedef-field.c | 66 ++++--
clang/test/CodeGen/attr-btf_type_tag-var.c | 77 +++++--
clang/test/CodeGen/attr-btf_type_tag-void.c | 12 ++
.../test/CodeGen/attr-btf_type_tag-volatile.c | 18 ++
llvm/include/llvm/IR/DIBuilder.h | 3 +
llvm/lib/IR/DIBuilder.cpp | 11 +
14 files changed, 493 insertions(+), 97 deletions(-)
create mode 100644 clang/test/CodeGen/attr-btf_type_tag-circular.c
create mode 100644 clang/test/CodeGen/attr-btf_type_tag-const.c
create mode 100644 clang/test/CodeGen/attr-btf_type_tag-restrict.c
create mode 100644 clang/test/CodeGen/attr-btf_type_tag-void.c
create mode 100644 clang/test/CodeGen/attr-btf_type_tag-volatile.c
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 5f6f911c7a6d6..e7db38ad85c3a 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -56,6 +56,16 @@
using namespace clang;
using namespace clang::CodeGen;
+// Temporarily hide new format for btf_type_tags / DW_TAG_LLVM_annotation
+// behind an option to allow transitory period for tooling dependent on
+// this annotation. The goal is to remove this flag after transitory period.
+static llvm::cl::opt<bool> BTFTypeTagV2(
+ "btf-type-tag-v2", llvm::cl::Hidden,
+ llvm::cl::desc("For __attribute__((btf_type_tag(...))) generate "
+ "DW_TAG_LLVM_annotation tags with DW_AT_name 'btf:type_tag' "
+ "attached to annotated type itself"),
+ llvm::cl::init(false));
+
static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
auto TI = Ctx.getTypeInfo(Ty);
return TI.isAlignRequired() ? TI.Align : 0;
@@ -1185,6 +1195,129 @@ CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
return RetTy;
}
+static QualType collectBTFTypeTagAnnotations(
+ llvm::LLVMContext &Context, llvm::DIBuilder &DBuilder,
+ llvm::SmallVectorImpl<llvm::Metadata *> &Annots,
+ const BTFTagAttributedType *BTFAttrTy, const char *TagName) {
+ QualType WrappedTy;
+
+ do {
+ StringRef TagValue = BTFAttrTy->getAttr()->getBTFTypeTag();
+ if (!TagValue.empty()) {
+ llvm::Metadata *Ops[] = {
+ llvm::MDString::get(Context, TagName),
+ llvm::MDString::get(Context, TagValue),
+ };
+ Annots.insert(Annots.begin(), llvm::MDNode::get(Context, Ops));
+ }
+ WrappedTy = BTFAttrTy->getWrappedType();
+ BTFAttrTy = dyn_cast<BTFTagAttributedType>(WrappedTy);
+ } while (BTFAttrTy);
+
+ return WrappedTy;
+}
+
+static bool retreiveCVR(llvm::DIDerivedType *DTy, QualifierCollector &Qc) {
+ switch (DTy->getTag()) {
+ case llvm::dwarf::DW_TAG_const_type:
+ Qc.addConst();
+ return true;
+ case llvm::dwarf::DW_TAG_volatile_type:
+ Qc.addVolatile();
+ return true;
+ case llvm::dwarf::DW_TAG_restrict_type:
+ Qc.addRestrict();
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Tags returned by QualifierCollector::getNextQualifier() should be
+// applied in the reverse order, thus use recursive function.
+static llvm::DIType *applyQualifiers(llvm::DIBuilder &DBuilder,
+ llvm::DIType *Ty, QualifierCollector &Qc) {
+ llvm::dwarf::Tag Tag = getNextQualifier(Qc);
+ if (!Tag)
+ return Ty;
+ Ty = applyQualifiers(DBuilder, Ty, Qc);
+ return DBuilder.createQualifiedType(Tag, Ty);
+}
+
+static bool isAnnotationsPlaceholder(llvm::DIDerivedType *DTy) {
+ return DTy->isTemporary() &&
+ DTy->getTag() == llvm::dwarf::DW_TAG_LLVM_annotation;
+}
+
+llvm::DIType *CGDebugInfo::CreateType(const BTFTagAttributedType *Ty,
+ llvm::DIFile *Unit) {
+ SmallVector<llvm::Metadata *, 4> Annotations;
+ auto WrappedTy = collectBTFTypeTagAnnotations(
+ CGM.getLLVMContext(), DBuilder, Annotations, Ty, "btf:type_tag");
+
+ if (!BTFTypeTagV2 || Annotations.empty())
+ return getOrCreateType(WrappedTy, Unit);
+
+ // After discussion with GCC BPF team in [1] it was decided to avoid
+ // attaching BTF type tags to const/volatile/restrict DWARF DIEs.
+ // So, strip qualifiers from WrappedTy and apply those to a final
+ // annotations placeholder instance at the end of this function.
+ //
+ // [1] https://reviews.llvm.org/D143967
+ QualifierCollector Qc;
+ Qc.addCVRQualifiers(WrappedTy.getLocalCVRQualifiers());
+ WrappedTy.removeLocalFastQualifiers(Qualifiers::CVRMask);
+
+ llvm::DIType *WrappedDI = getOrCreateType(WrappedTy, Unit);
+ if (!WrappedDI)
+ WrappedDI = DBuilder.createUnspecifiedType("void");
+
+ // Stripping local CVR qualifiers might not be enough in cases like this:
+ //
+ // #define __tag __attribute__((btf_type_tag("tag")))
+ // const int *foo;
+ // const int *bar(void) {
+ // return (typeof(*foo) __tag *)(0);
+ // }
+ //
+ // Here the AST looks like:
+ //
+ // BTFTagAttributedType
+ // | 'typeof (*foo) __attribute__((btf_type_tag("tag")))' sugar
+ // `-TypeOfExprType 'typeof (*foo)' sugar
+ // |-ParenExpr 'const int' lvalue
+ // | `- ...
+ // `-QualType 'const int' const
+ // `-BuiltinType 'int'
+ //
+ // The BTFTagAttributedType is applied to TypeOfExpr.
+ // For TypeOfExpr the getOrCreateType(), would return instance of
+ // DIDerivedType with tag DW_TAG_const_type.
+ //
+ // To avoid repeating UnwrapTypeForDebugInfo() logic here just
+ // rebuild CVR metadata nodes if necessary.
+ // The above local CVR qualifiers processing is redundant,
+ // but avoids rebuilding metadata nodes in the most common case.
+ while (auto *DTy = dyn_cast<llvm::DIDerivedType>(WrappedDI)) {
+ if (!retreiveCVR(DTy, Qc))
+ break;
+ WrappedDI = DTy->getBaseType();
+ }
+
+ if (auto *DTy = dyn_cast<llvm::DIDerivedType>(WrappedDI))
+ if (isAnnotationsPlaceholder(DTy)) {
+ WrappedDI = DTy->getBaseType();
+ for (llvm::Metadata *O : DTy->getAnnotations()->operands())
+ Annotations.push_back(O);
+ }
+
+ auto *Placeholder = DBuilder.createAnnotationsPlaceholder(
+ WrappedDI, DBuilder.getOrCreateArray(Annotations));
+ AnnotationPlaceholders.push_back(Placeholder);
+
+ return applyQualifiers(DBuilder, Placeholder, Qc);
+}
+
llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
const Type *Ty,
QualType PointeeTy,
@@ -1197,32 +1330,23 @@ llvm::DIType *CGDebugInfo::CreatePointerLikeType(llvm::dwarf::Tag Tag,
CGM.getTarget().getDWARFAddressSpace(
CGM.getTypes().getTargetAddressSpace(PointeeTy));
- SmallVector<llvm::Metadata *, 4> Annots;
- auto *BTFAttrTy = dyn_cast<BTFTagAttributedType>(PointeeTy);
- while (BTFAttrTy) {
- StringRef Tag = BTFAttrTy->getAttr()->getBTFTypeTag();
- if (!Tag.empty()) {
- llvm::Metadata *Ops[2] = {
- llvm::MDString::get(CGM.getLLVMContext(), StringRef("btf_type_tag")),
- llvm::MDString::get(CGM.getLLVMContext(), Tag)};
- Annots.insert(Annots.begin(),
- llvm::MDNode::get(CGM.getLLVMContext(), Ops));
- }
- BTFAttrTy = dyn_cast<BTFTagAttributedType>(BTFAttrTy->getWrappedType());
- }
-
llvm::DINodeArray Annotations = nullptr;
- if (Annots.size() > 0)
- Annotations = DBuilder.getOrCreateArray(Annots);
+ auto *BTFAttrTy = dyn_cast<BTFTagAttributedType>(PointeeTy.getTypePtr());
+ if (!BTFTypeTagV2 && BTFAttrTy) {
+ SmallVector<llvm::Metadata *, 4> AnnotationsVec;
+ collectBTFTypeTagAnnotations(CGM.getLLVMContext(), DBuilder, AnnotationsVec,
+ BTFAttrTy, "btf_type_tag");
+ Annotations = DBuilder.getOrCreateArray(AnnotationsVec);
+ }
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
Size, Align, DWARFAddressSpace);
- else
- return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
- Align, DWARFAddressSpace, StringRef(),
- Annotations);
+
+ return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
+ Align, DWARFAddressSpace, StringRef(),
+ Annotations);
}
llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
@@ -3543,9 +3667,6 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
case Type::Attributed:
T = cast<AttributedType>(T)->getEquivalentType();
break;
- case Type::BTFTagAttributed:
- T = cast<BTFTagAttributedType>(T)->getWrappedType();
- break;
case Type::CountAttributed:
T = cast<CountAttributedType>(T)->desugar();
break;
@@ -3745,10 +3866,12 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
case Type::TemplateSpecialization:
return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
+ case Type::BTFTagAttributed:
+ return CreateType(cast<BTFTagAttributedType>(Ty), Unit);
+
case Type::CountAttributed:
case Type::Auto:
case Type::Attributed:
- case Type::BTFTagAttributed:
case Type::Adjusted:
case Type::Decayed:
case Type::DeducedTemplateSpecialization:
@@ -6005,6 +6128,35 @@ void CGDebugInfo::setDwoId(uint64_t Signature) {
TheCU->setDWOId(Signature);
}
+static llvm::DIType *copyAnnotations(llvm::DIBuilder &DBuilder,
+ llvm::DIDerivedType *Placeholder) {
+ auto *WrappedDI = Placeholder->getBaseType();
+ SmallVector<llvm::Metadata *, 4> Annotations;
+
+ for (const llvm::Metadata *O : Placeholder->getAnnotations()->operands())
+ Annotations.push_back(const_cast<llvm::Metadata *>(O));
+
+ auto AddAnnotations = [&](auto *Type) {
+ if (llvm::DINodeArray OldAnnotations = Type->getAnnotations())
+ for (const llvm::Metadata *O : OldAnnotations->operands())
+ Annotations.push_back(const_cast<llvm::Metadata *>(O));
+ auto Clone = Type->clone();
+ Clone->replaceAnnotations(DBuilder.getOrCreateArray(Annotations));
+ return llvm::MDNode::replaceWithPermanent(std::move(Clone));
+ };
+
+ if (auto *Ty = dyn_cast<llvm::DIBasicType>(WrappedDI))
+ return AddAnnotations(Ty);
+ if (auto *Ty = dyn_cast<llvm::DICompositeType>(WrappedDI))
+ return AddAnnotations(Ty);
+ if (auto *Ty = dyn_cast<llvm::DIDerivedType>(WrappedDI))
+ return AddAnnotations(Ty);
+ if (auto *Ty = dyn_cast<llvm::DISubroutineType>(WrappedDI))
+ return AddAnnotations(Ty);
+
+ return WrappedDI;
+}
+
void CGDebugInfo::finalize() {
// Creating types might create further types - invalidating the current
// element and the size(), so don't cache/reference them.
@@ -6078,6 +6230,10 @@ void CGDebugInfo::finalize() {
if (auto MD = TypeCache[RT])
DBuilder.retainType(cast<llvm::DIType>(MD));
+ for (auto &Placeholder : AnnotationPlaceholders)
+ DBuilder.replaceTemporary(llvm::TempDIType(Placeholder),
+ copyAnnotations(DBuilder, Placeholder));
+
DBuilder.finalize();
}
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index da466837aa3c3..ce0b5b1a04dcc 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -171,6 +171,8 @@ class CGDebugInfo {
/// The key is coroutine real parameters, value is DIVariable in LLVM IR.
Param2DILocTy ParamDbgMappings;
+ std::vector<llvm::DIDerivedType *> AnnotationPlaceholders;
+
/// Helper functions for getOrCreateType.
/// @{
/// Currently the checksum of an interface includes the number of
@@ -218,6 +220,7 @@ class CGDebugInfo {
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
+ llvm::DIType *CreateType(const BTFTagAttributedType *Ty, llvm::DIFile *F);
/// Get enumeration type.
llvm::DIType *CreateEnumType(const EnumType *Ty);
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
diff --git a/clang/test/CodeGen/attr-btf_type_tag-circular.c b/clang/test/CodeGen/attr-btf_type_tag-circular.c
new file mode 100644
index 0000000000000..4bcb20e63bead
--- /dev/null
+++ b/clang/test/CodeGen/attr-btf_type_tag-circular.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+
+struct st {
+ struct st __tag1 *self;
+} g;
+
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK: ![[L1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2:[0-9]+]])
+// CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
+// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_member, name: "self", scope: ![[L1]], file: ![[#]], line: [[#]], baseType: ![[L4:[0-9]+]], size: [[#]])
+// CHECK: ![[L4]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5:[0-9]+]], size: [[#]])
+// CHECK: ![[L5]] = !DICompositeType(tag: DW_TAG_structure_type, name: "st", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L2]], annotations: ![[L7:[0-9]+]])
+// CHECK: ![[L7]] = !{![[L8:[0-9]+]]}
+// CHECK: ![[L8]] = !{!"btf:type_tag", !"tag1"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-const.c b/clang/test/CodeGen/attr-btf_type_tag-const.c
new file mode 100644
index 0000000000000..94d9c05f5345a
--- /dev/null
+++ b/clang/test/CodeGen/attr-btf_type_tag-const.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+
+// Check that BTF type tags are not attached to DW_TAG_const_type DIEs
+// in presence of "sugar" expressions that are transparent for
+// CGDebugInfo.cpp:UnwrapTypeForDebugInfo(), but are not transparent
+// for local qualifiers.
+//
+// For details see:
+// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile)
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+#define __tag3 __attribute__((btf_type_tag("tag3")))
+
+const int *foo;
+typeof(*foo) __tag1 bar;
+
+// CHECK: distinct !DIGlobalVariable(name: "bar", {{.*}}, type: ![[L01:[0-9]+]], {{.*}})
+// CHECK: ![[L01]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L02:[0-9]+]])
+// CHECK: ![[L02]] = !DIBasicType(name: "int", {{.*}}, annotations: ![[L03:[0-9]+]])
+// CHECK: ![[L03]] = !{![[L04:[0-9]+]]}
+// CHECK: ![[L04]] = !{!"btf:type_tag", !"tag1"}
+
+const int __tag2 *buz;
+
+// CHECK: distinct !DIGlobalVariable(name: "buz", {{.*}}, type: ![[L05:[0-9]+]], {{.*}})
+// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], {{.*}})
+// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L08:[0-9]+]])
+// CHECK: ![[L08]] = !DIBasicType(name: "int", size: [[#]], {{.*}}, annotations: ![[L09:[0-9]+]])
+// CHECK: ![[L09]] = !{![[L10:[0-9]+]]}
+// CHECK: ![[L10]] = !{!"btf:type_tag", !"tag2"}
+
+typeof(*buz) __tag3 quux;
+
+// CHECK: distinct !DIGlobalVariable(name: "quux", {{.*}}, type: ![[L12:[0-9]+]], {{.*}})
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L13:[0-9]+]])
+// CHECK: ![[L13]] = !DIBasicType(name: "int", {{.*}}, annotations: ![[L14:[0-9]+]])
+// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L10]]}
+// CHECK: ![[L15]] = !{!"btf:type_tag", !"tag3"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
index 26935c882a017..8567864692202 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-func-ptr.c
@@ -1,4 +1,8 @@
// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefix CHECK-V2 %s
struct t {
int (__attribute__((btf_type_tag("rcu"))) *f)();
@@ -8,8 +12,13 @@ int foo(struct t *arg) {
return arg->a;
}
-// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f"
-// CHECK-SAME: baseType: ![[L18:[0-9]+]]
-// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L21:[0-9]+]])
-// CHECK: ![[L21]] = !{![[L22:[0-9]+]]}
-// CHECK: ![[L22]] = !{!"btf_type_tag", !"rcu"}
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L1:[0-9]+]], size: [[#]])
+// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L2:[0-9]+]])
+// CHECK: ![[L2]] = !{![[L3:[0-9]+]]}
+// CHECK: ![[L3]] = !{!"btf_type_tag", !"rcu"}
+
+// CHECK-V2: !DIDerivedType(tag: DW_TAG_member, name: "f", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L1:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L2]] = !DISubroutineType(types: ![[#]], annotations: ![[L4:[0-9]+]])
+// CHECK-V2: ![[L4]] = !{![[L5:[0-9]+]]}
+// CHECK-V2: ![[L5]] = !{!"btf:type_tag", !"rcu"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-func.c b/clang/test/CodeGen/attr-btf_type_tag-func.c
index dbb8864759148..890d3ab35428b 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-func.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-func.c
@@ -1,5 +1,17 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 -debug-info-kind=limited \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK-V2 %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 \
+// RUN: -debug-info-kind=limited -mllvm -btf-type-tag-v2 -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK-V2 %s
#if DOUBLE_BRACKET_ATTRS
#define __tag1 [[clang::btf_type_tag("tag1")]]
@@ -15,14 +27,26 @@
int __tag1 * __tag2 *foo(int __tag1 * __tag2 *arg) { return arg; }
-// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L9:[0-9]+]]
-// CHECK: ![[L9]] = !DISubroutineType(types: ![[L10:[0-9]+]]
-// CHECK: ![[L10]] = !{![[L11:[0-9]+]], ![[L11]]}
-// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L12:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]]
-// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L14:[0-9]+]]
-// CHECK: ![[L13]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
-// CHECK: ![[L14]] = !{![[L15:[0-9]+]]}
-// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L16]] = !{![[L17:[0-9]+]]}
-// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L11]])
+// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], {{.*}})
+// CHECK: ![[L01]] = !DISubroutineType(types: ![[L02:[0-9]+]])
+// CHECK: ![[L02]] = !{![[L03:[0-9]+]], ![[L03]]}
+// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L04:[0-9]+]], size: [[#]], annotations: ![[L05:[0-9]+]])
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]])
+// CHECK: ![[L06]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: ![[L07]] = !{![[L11:[0-9]+]]}
+// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L05]] = !{![[L12:[0-9]+]]}
+// CHECK: ![[L12]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L03]])
+
+// CHECK-V2: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], {{.*}})
+// CHECK-V2: ![[L01]] = !DISubroutineType(types: ![[L02:[0-9]+]])
+// CHECK-V2: ![[L02]] = !{![[L03:[0-9]+]], ![[L03]]}
+// CHECK-V2: ![[L03]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L04:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]])
+// CHECK-V2: ![[L06]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L08:[0-9]+]])
+// CHECK-V2: ![[L08]] = !{![[L09:[0-9]+]]}
+// CHECK-V2: ![[L09]] = !{!"btf:type_tag", !"tag1"}
+// CHECK-V2: ![[L07]] = !{![[L10:[0-9]+]]}
+// CHECK-V2: ![[L10]] = !{!"btf:type_tag", !"tag2"}
+// CHECK-V2: !DILocalVariable(name: "arg", arg: 1, scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L03]])
diff --git a/clang/test/CodeGen/attr-btf_type_tag-restrict.c b/clang/test/CodeGen/attr-btf_type_tag-restrict.c
new file mode 100644
index 0000000000000..9c96221fc9706
--- /dev/null
+++ b/clang/test/CodeGen/attr-btf_type_tag-restrict.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+
+// See attr-btf_type_tag-const.c for reasoning behind this test.
+// Alternatively, see the following method:
+// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile)
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+
+void foo(int * restrict bar, typeof(bar) __tag1 buz) {}
+
+// CHECK: ![[#]] = !DISubroutineType(types: ![[L1:[0-9]+]])
+// CHECK: ![[L1]] = !{null, ![[L2:[0-9]+]], ![[L3:[0-9]+]]}
+// CHECK: ![[L2]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: ![[L4:[0-9]+]])
+// CHECK: ![[L4]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5:[0-9]+]], {{.*}})
+// CHECK: ![[L5]] = !DIBasicType(name: "int", {{.*}}, encoding: DW_ATE_signed)
+// CHECK: ![[L3]] = !DIDerivedType(tag: DW_TAG_restrict_type, baseType: ![[L6:[0-9]+]])
+// CHECK: ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L5]], {{.*}}, annotations: ![[L7:[0-9]+]])
+// CHECK: ![[L7]] = !{![[L8:[0-9]+]]}
+// CHECK: ![[L8]] = !{!"btf:type_tag", !"tag1"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-similar-type.c b/clang/test/CodeGen/attr-btf_type_tag-similar-type.c
index 3960d6f5c93fb..25a99c076619b 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-similar-type.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-similar-type.c
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck --check-prefixes=CHECK-V2 %s
struct map_value {
int __attribute__((btf_type_tag("tag1"))) __attribute__((btf_type_tag("tag3"))) *a;
@@ -12,15 +17,31 @@ int test(struct map_value *arg)
return *arg->a;
}
-// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L14:[0-9]+]]
-// CHECK: ![[L14]] = !{![[L15:[0-9]+]], ![[L20:[0-9]+]]}
-// CHECK: ![[L15]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]]
-// CHECK: ![[L16]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L17:[0-9]+]]
-// CHECK: ![[L17]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]}
-// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag3"}
-// CHECK: ![[L20]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L21:[0-9]+]]
-// CHECK: ![[L21:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[#]], size: [[#]], annotations: ![[L22:[0-9]+]]
-// CHECK: ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
-// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag4"}
+// CHECK: ![[L05:[0-9]+]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L01:[0-9]+]])
+// CHECK: ![[L01]] = !{![[L02:[0-9]+]], ![[L03:[0-9]+]]}
+// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L04:[0-9]+]], size: [[#]])
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L05]], size: [[#]], annotations: ![[L06:[0-9]+]])
+// CHECK: ![[L06]] = !{![[L10:[0-9]+]], ![[L11:[0-9]+]]}
+// CHECK: ![[L10]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L11]] = !{!"btf_type_tag", !"tag3"}
+// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L12:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L05]], size: [[#]], annotations: ![[L14:[0-9]+]])
+// CHECK: ![[L14]] = !{![[L18:[0-9]+]], ![[L19:[0-9]+]]}
+// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag4"}
+
+// CHECK-V2: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_value", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L01:[0-9]+]])
+// CHECK-V2: ![[L01]] = !{![[L02:[0-9]+]], ![[L03:[0-9]+]]}
+// CHECK-V2: ![[L02]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L04:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L04]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L05:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L05]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L07:[0-9]+]])
+// CHECK-V2: ![[L07]] = !{![[L08:[0-9]+]], ![[L09:[0-9]+]]}
+// CHECK-V2: ![[L08]] = !{!"btf:type_tag", !"tag1"}
+// CHECK-V2: ![[L09]] = !{!"btf:type_tag", !"tag3"}
+// CHECK-V2: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L12:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK-V2: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L13]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L15:[0-9]+]])
+// CHECK-V2: ![[L15]] = !{![[L16:[0-9]+]], ![[L17:[0-9]+]]}
+// CHECK-V2: ![[L16]] = !{!"btf:type_tag", !"tag2"}
+// CHECK-V2: ![[L17]] = !{!"btf:type_tag", !"tag4"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
index 5c8955fbf89a8..ceb4e83aa428b 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-typedef-field.c
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck %s --check-prefixes CHECK-V2
#define __tag1 __attribute__((btf_type_tag("tag1")))
#define __tag2 __attribute__((btf_type_tag("tag2")))
@@ -14,22 +19,43 @@ int *foo1(struct t *a1) {
return (int *)a1->c;
}
-// CHECK: ![[L4:[0-9]+]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L16:[0-9]+]])
-// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L24:[0-9]+]], ![[L31:[0-9]+]]}
-// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L18:[0-9]+]], size: [[#]])
-// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L19:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]])
-// CHECK: ![[L19]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L4]], size: [[#]], annotations: ![[L20:[0-9]+]])
-// CHECK: ![[L20]] = !{![[L21:[0-9]+]]}
-// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L22]] = !{![[L23:[0-9]+]]}
-// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: ![[L24]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L25:[0-9]+]]
-// CHECK: ![[L25]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L26:[0-9]+]])
-// CHECK: ![[L26]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L27:[0-9]+]], size: [[#]], annotations: ![[L30:[0-9]+]])
-// CHECK: ![[L27]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L28:[0-9]+]])
-// CHECK: ![[L28]] = !DISubroutineType(types: ![[L29:[0-9]+]])
-// CHECK: ![[L29]] = !{null, ![[L4]]}
-// CHECK: ![[L30]] = !{![[L21]], ![[L23]]}
-// CHECK: ![[L31]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]]1, baseType: ![[L32:[0-9]+]]
-// CHECK: ![[L32]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: ![[L01:[0-9]+]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L02:[0-9]+]])
+// CHECK: ![[L02]] = !{![[L03:[0-9]+]], ![[L04:[0-9]+]], ![[L05:[0-9]+]]}
+// CHECK: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L06:[0-9]+]], size: [[#]])
+// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L07:[0-9]+]], size: [[#]], annotations: ![[L08:[0-9]+]])
+// CHECK: ![[L07]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L01]], size: [[#]], annotations: ![[L10:[0-9]+]])
+// CHECK: ![[L10]] = !{![[L14:[0-9]+]]}
+// CHECK: ![[L14]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L08]] = !{![[L15:[0-9]+]]}
+// CHECK: ![[L15]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK: ![[L16]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L17:[0-9]+]])
+// CHECK: ![[L17]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L18:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]])
+// CHECK: ![[L18]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L20:[0-9]+]])
+// CHECK: ![[L20]] = !DISubroutineType(types: ![[L22:[0-9]+]])
+// CHECK: ![[L22]] = !{null, ![[L01]]}
+// CHECK: ![[L19]] = !{![[L14]], ![[L15]]}
+// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L23:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK: ![[L23]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed)
+
+// CHECK-V2: ![[L01:[0-9]+]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK-V2: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: ![[#]], line: [[#]], size: [[#]], elements: ![[L02:[0-9]+]])
+// CHECK-V2: ![[L02]] = !{![[L03:[0-9]+]], ![[L04:[0-9]+]], ![[L05:[0-9]+]]}
+// CHECK-V2: ![[L03]] = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L06:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L06]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L07:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L07]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L09:[0-9]+]], size: [[#]], annotations: ![[L08:[0-9]+]])
+// CHECK-V2: ![[L09]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L10:[0-9]+]])
+// CHECK-V2: ![[L10]] = !{![[L14:[0-9]+]]}
+// CHECK-V2: ![[L14]] = !{!"btf:type_tag", !"tag1"}
+// CHECK-V2: ![[L08]] = !{![[L15:[0-9]+]]}
+// CHECK-V2: ![[L15]] = !{!"btf:type_tag", !"tag2"}
+// CHECK-V2: ![[L04]] = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L16:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK-V2: ![[L16]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn2_t", file: ![[#]], line: [[#]], baseType: ![[L17:[0-9]+]])
+// CHECK-V2: ![[L17]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L18:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L18]] = !DIDerivedType(tag: DW_TAG_typedef, name: "__fn_t", file: ![[#]], line: [[#]], baseType: ![[L20:[0-9]+]], annotations: ![[L19:[0-9]+]])
+// CHECK-V2: ![[L20]] = !DISubroutineType(types: ![[L22:[0-9]+]])
+// CHECK-V2: ![[L22]] = !{null, ![[L01]]}
+// CHECK-V2: ![[L19]] = !{![[L14]], ![[L15]]}
+// CHECK-V2: ![[L05]] = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[L23:[0-9]+]], size: [[#]], offset: [[#]])
+// CHECK-V2: ![[L23]] = !DIBasicType(name: "long", size: [[#]], encoding: DW_ATE_signed)
diff --git a/clang/test/CodeGen/attr-btf_type_tag-var.c b/clang/test/CodeGen/attr-btf_type_tag-var.c
index ed729e245fbcb..eca61b8742fb1 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-var.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-var.c
@@ -1,5 +1,17 @@
-// RUN: %clang_cc1 -triple %itanium_abi_triple -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 \
+// RUN: -debug-info-kind=limited -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK-V2 %s
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -DDOUBLE_BRACKET_ATTRS=1 -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s \
+// RUN: | FileCheck --check-prefixes CHECK-V2 %s
#if DOUBLE_BRACKET_ATTRS
#define __tag1 [[clang::btf_type_tag("tag1")]]
@@ -21,23 +33,44 @@ const volatile int __tag1 __tag2 * __tag3 __tag4 const volatile * __tag5 __tag6
const int __tag1 __tag2 volatile * const __tag3 __tag4 volatile * __tag5 __tag6 const volatile * g;
#endif
-// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L6:[0-9]+]]
-// CHECK: ![[L6]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L7:[0-9]+]], size: [[#]], annotations: ![[L22:[0-9]+]]
-// CHECK: ![[L7]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L8:[0-9]+]]
-// CHECK: ![[L8]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L9:[0-9]+]]
-// CHECK: ![[L9]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L19:[0-9]+]]
-// CHECK: ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L11:[0-9]+]]
-// CHECK: ![[L11]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L12:[0-9]+]]
-// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L13:[0-9]+]], size: [[#]], annotations: ![[L16:[0-9]+]]
-// CHECK: ![[L13]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L14:[0-9]+]]
-// CHECK: ![[L14]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L15:[0-9]+]]
-// CHECK: ![[L15]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed
-// CHECK: ![[L16]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]]}
-// CHECK: ![[L17]] = !{!"btf_type_tag", !"tag1"}
-// CHECK: ![[L18]] = !{!"btf_type_tag", !"tag2"}
-// CHECK: ![[L19]] = !{![[L20:[0-9]+]], ![[L21:[0-9]+]]}
-// CHECK: ![[L20]] = !{!"btf_type_tag", !"tag3"}
-// CHECK: ![[L21]] = !{!"btf_type_tag", !"tag4"}
-// CHECK: ![[L22]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
-// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag5"}
-// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag6"}
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK: ![[L01]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L02:[0-9]+]], size: [[#]], annotations: ![[L03:[0-9]+]])
+// CHECK: ![[L02]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L04:[0-9]+]])
+// CHECK: ![[L04]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L05:[0-9]+]])
+// CHECK: ![[L05]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]])
+// CHECK: ![[L06]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L08:[0-9]+]])
+// CHECK: ![[L08]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L09:[0-9]+]])
+// CHECK: ![[L09]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L11:[0-9]+]])
+// CHECK: ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L12:[0-9]+]])
+// CHECK: ![[L12]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L13:[0-9]+]])
+// CHECK: ![[L13]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed)
+// CHECK: ![[L11]] = !{![[L19:[0-9]+]], ![[L20:[0-9]+]]}
+// CHECK: ![[L19]] = !{!"btf_type_tag", !"tag1"}
+// CHECK: ![[L20]] = !{!"btf_type_tag", !"tag2"}
+// CHECK: ![[L07]] = !{![[L23:[0-9]+]], ![[L24:[0-9]+]]}
+// CHECK: ![[L23]] = !{!"btf_type_tag", !"tag3"}
+// CHECK: ![[L24]] = !{!"btf_type_tag", !"tag4"}
+// CHECK: ![[L03]] = !{![[L25:[0-9]+]], ![[L26:[0-9]+]]}
+// CHECK: ![[L25]] = !{!"btf_type_tag", !"tag5"}
+// CHECK: ![[L26]] = !{!"btf_type_tag", !"tag6"}
+
+// CHECK-V2: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L01:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK-V2: ![[L01]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L02:[0-9]+]], size: [[#]])
+// CHECK-V2: ![[L02]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L04:[0-9]+]])
+// CHECK-V2: ![[L04]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L05:[0-9]+]])
+// CHECK-V2: ![[L05]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L06:[0-9]+]], size: [[#]], annotations: ![[L07:[0-9]+]])
+// CHECK-V2: ![[L06]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L08:[0-9]+]])
+// CHECK-V2: ![[L08]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L09:[0-9]+]])
+// CHECK-V2: ![[L09]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L10:[0-9]+]], size: [[#]], annotations: ![[L11:[0-9]+]])
+// CHECK-V2: ![[L10]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: ![[L12:[0-9]+]])
+// CHECK-V2: ![[L12]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L13:[0-9]+]])
+// CHECK-V2: ![[L13]] = !DIBasicType(name: "int", size: [[#]], encoding: DW_ATE_signed, annotations: ![[L14:[0-9]+]])
+// CHECK-V2: ![[L14]] = !{![[L15:[0-9]+]], ![[L16:[0-9]+]]}
+// CHECK-V2: ![[L15]] = !{!"btf:type_tag", !"tag1"}
+// CHECK-V2: ![[L16]] = !{!"btf:type_tag", !"tag2"}
+// CHECK-V2: ![[L11]] = !{![[L17:[0-9]+]], ![[L18:[0-9]+]]}
+// CHECK-V2: ![[L17]] = !{!"btf:type_tag", !"tag3"}
+// CHECK-V2: ![[L18]] = !{!"btf:type_tag", !"tag4"}
+// CHECK-V2: ![[L07]] = !{![[L21:[0-9]+]], ![[L22:[0-9]+]]}
+// CHECK-V2: ![[L21]] = !{!"btf:type_tag", !"tag5"}
+// CHECK-V2: ![[L22]] = !{!"btf:type_tag", !"tag6"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-void.c b/clang/test/CodeGen/attr-btf_type_tag-void.c
new file mode 100644
index 0000000000000..9fe49370d2f2c
--- /dev/null
+++ b/clang/test/CodeGen/attr-btf_type_tag-void.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+void __tag1 *g;
+
+// CHECK: distinct !DIGlobalVariable(name: "g", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[L1:[0-9]+]], isLocal: false, isDefinition: true)
+// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[L2:[0-9]+]], size: [[#]])
+// CHECK: ![[L2]] = !DIBasicType(tag: DW_TAG_unspecified_type, name: "void", annotations: ![[L4:[0-9]+]])
+// CHECK: ![[L4]] = !{![[L5:[0-9]+]]}
+// CHECK: ![[L5]] = !{!"btf:type_tag", !"tag1"}
diff --git a/clang/test/CodeGen/attr-btf_type_tag-volatile.c b/clang/test/CodeGen/attr-btf_type_tag-volatile.c
new file mode 100644
index 0000000000000..e0039fb23fba2
--- /dev/null
+++ b/clang/test/CodeGen/attr-btf_type_tag-volatile.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 \
+// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
+// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+
+// See attr-btf_type_tag-const.c for reasoning behind this test.
+// Alternatively, see the following method:
+// CGDebugInfo::CreateType(const BTFTagAttributedType, llvm::DIFile)
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+
+volatile int foo;
+typeof(foo) __tag1 bar;
+
+// CHECK: ![[#]] = distinct !DIGlobalVariable(name: "bar", {{.*}}, type: ![[L1:[0-9]+]], {{.*}})
+// CHECK: ![[L1]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: ![[L2:[0-9]+]])
+// CHECK: ![[L2]] = !DIBasicType(name: "int", size: [[#]], {{.*}}, annotations: ![[L3:[0-9]+]])
+// CHECK: ![[L3]] = !{![[L4:[0-9]+]]}
+// CHECK: ![[L4]] = !{!"btf:type_tag", !"tag1"}
diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h
index 97ea38f041baa..03d16a1a2ad07 100644
--- a/llvm/include/llvm/IR/DIBuilder.h
+++ b/llvm/include/llvm/IR/DIBuilder.h
@@ -328,6 +328,9 @@ namespace llvm {
DINode::DIFlags Flags = DINode::FlagZero,
DINodeArray Annotations = nullptr);
+ DIDerivedType *createAnnotationsPlaceholder(DIType *Ty,
+ DINodeArray Annotations);
+
/// Create debugging information entry for a 'friend'.
DIDerivedType *createFriend(DIType *Ty, DIType *FriendTy);
diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp
index f39149ae0dad4..457de32a0507f 100644
--- a/llvm/lib/IR/DIBuilder.cpp
+++ b/llvm/lib/IR/DIBuilder.cpp
@@ -367,6 +367,17 @@ DIBuilder::createTemplateAlias(DIType *Ty, StringRef Name, DIFile *File,
TParams.get(), Annotations);
}
+DIDerivedType *
+DIBuilder::createAnnotationsPlaceholder(DIType *Ty, DINodeArray Annotations) {
+ auto *RetTy = DIDerivedType::getTemporary(
+ VMContext, dwarf::DW_TAG_LLVM_annotation, "", nullptr, 0,
+ nullptr, Ty, 0, 0, 0, std::nullopt, std::nullopt,
+ DINode::FlagZero, nullptr, Annotations)
+ .release();
+ trackIfUnresolved(RetTy);
+ return RetTy;
+}
+
DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
assert(Ty && "Invalid type!");
assert(FriendTy && "Invalid friend type!");
>From 57822bc234fae7ec2eae17d8da396d63e92dedce Mon Sep 17 00:00:00 2001
From: Eduard Zingerman <eddyz87 at gmail.com>
Date: Tue, 4 Jun 2024 23:57:48 -0700
Subject: [PATCH 3/3] [BPF] '-S -emit-llvm -> -emit-llvm' for
attr-btf_type_tag-*.c tests
Newly added btf_type_tag related tests use 'clang -S -emit-llvm',
which is now not accepted by 'clang'.
Fix these tests by using only '-emit-llvm'.
To be squashed with the main commit when when branch would be merged.
---
clang/test/CodeGen/attr-btf_type_tag-circular.c | 2 +-
clang/test/CodeGen/attr-btf_type_tag-const.c | 2 +-
clang/test/CodeGen/attr-btf_type_tag-restrict.c | 2 +-
clang/test/CodeGen/attr-btf_type_tag-void.c | 2 +-
clang/test/CodeGen/attr-btf_type_tag-volatile.c | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/clang/test/CodeGen/attr-btf_type_tag-circular.c b/clang/test/CodeGen/attr-btf_type_tag-circular.c
index 4bcb20e63bead..ca2a1a07fd4c8 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-circular.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-circular.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 \
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
-// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck %s
#define __tag1 __attribute__((btf_type_tag("tag1")))
diff --git a/clang/test/CodeGen/attr-btf_type_tag-const.c b/clang/test/CodeGen/attr-btf_type_tag-const.c
index 94d9c05f5345a..5e25a95e91f5c 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-const.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-const.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 \
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
-// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck %s
// Check that BTF type tags are not attached to DW_TAG_const_type DIEs
// in presence of "sugar" expressions that are transparent for
diff --git a/clang/test/CodeGen/attr-btf_type_tag-restrict.c b/clang/test/CodeGen/attr-btf_type_tag-restrict.c
index 9c96221fc9706..ce25fbcae41a1 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-restrict.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-restrict.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 \
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
-// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck %s
// See attr-btf_type_tag-const.c for reasoning behind this test.
// Alternatively, see the following method:
diff --git a/clang/test/CodeGen/attr-btf_type_tag-void.c b/clang/test/CodeGen/attr-btf_type_tag-void.c
index 9fe49370d2f2c..0f580f0119e10 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-void.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-void.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 \
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
-// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck %s
#define __tag1 __attribute__((btf_type_tag("tag1")))
void __tag1 *g;
diff --git a/clang/test/CodeGen/attr-btf_type_tag-volatile.c b/clang/test/CodeGen/attr-btf_type_tag-volatile.c
index e0039fb23fba2..109e42167107c 100644
--- a/clang/test/CodeGen/attr-btf_type_tag-volatile.c
+++ b/clang/test/CodeGen/attr-btf_type_tag-volatile.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 \
// RUN: -triple %itanium_abi_triple -debug-info-kind=limited \
-// RUN: -mllvm -btf-type-tag-v2 -S -emit-llvm -o - %s | FileCheck %s
+// RUN: -mllvm -btf-type-tag-v2 -emit-llvm -o - %s | FileCheck %s
// See attr-btf_type_tag-const.c for reasoning behind this test.
// Alternatively, see the following method:
More information about the cfe-commits
mailing list