https://github.com/eddyz87 created https://github.com/llvm/llvm-project/pull/91423
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....@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 Note: the new place for annotation is DWARF was already agreed as a part of D143967, however the switch enabling or disabling this is a new addition. >From 4f3fbf2e4d831ea92d3bd5170e5e3c14b36fff5c Mon Sep 17 00:00:00 2001 From: Eduard Zingerman <eddy...@gmail.com> Date: Tue, 14 Feb 2023 00:49:33 +0200 Subject: [PATCH 1/2] [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....@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 42291d45da2be..1dfaa4aced791 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 34053a5ca9c8e..813454aefd9e1 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -5210,7 +5210,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)); \ @@ -5218,12 +5218,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; } @@ -5360,12 +5362,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 6d01e3b4d8218..d7b5c4f7f3a1f 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1798,6 +1798,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(); @@ -1893,6 +1894,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 56c288ee95b43..203f496536002 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -696,7 +696,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; @@ -865,6 +867,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 941f6a7a7d823..b37c01a10d025 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2096,9 +2096,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()); @@ -2107,6 +2107,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 << ")"; } @@ -2202,6 +2203,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 570515505607f..264d8e467fde0 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 399fe0dad26c7..86bfcce599e77 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 + +@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 + +@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. -@g = dso_local global ptr null, align 8, !dbg !0 +@a = dso_local global i32 0, align 4, !dbg !0 +@b = dso_local global ptr null, align 8, !dbg !5 +@c = dso_local global ptr null, align 8, !dbg !11 +@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 f75fc64d230ae73370b4f198ed471fe817bdd04c Mon Sep 17 00:00:00 2001 From: Eduard Zingerman <eddy...@gmail.com> Date: Tue, 14 Feb 2023 01:19:50 +0200 Subject: [PATCH 2/2] [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....@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 fac278f0e20a4..9518a75a3b1f1 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: @@ -5921,6 +6044,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. @@ -5994,6 +6146,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 d6db4d711366a..43a093c725f6a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -170,6 +170,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 @@ -217,6 +219,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..70cddb3ddf629 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!"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits