diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1499,6 +1499,11 @@ OffsetInBits, Align, tunit, RecordTy, RD); } + if (field->hasAttr()) { + auto FType = cast(FieldType); + FType->replaceAnnotations(CollectBTFTagAnnotations(field)); + } + elements.push_back(FieldType); } diff --git a/clang/test/CodeGen/attr-btf_tag-field.c b/clang/test/CodeGen/attr-btf_tag-field.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_tag-field.c @@ -0,0 +1,18 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -target x86_64 -g -S -emit-llvm -o - %s | FileCheck %s + +#define __tag1 __attribute__((btf_tag("tag1"))) +#define __tag2 __attribute__((btf_tag("tag2"))) + +struct t1 { + int a __tag1 __tag2; +}; + +int foo(struct t1 *arg) { + return arg->a; +} + +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "a", scope: ![[#]], file: ![[#]], line: [[#]], baseType: ![[#]], size: 32, annotations: ![[ANNOT:[0-9]+]]) +// CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +// CHECK: ![[TAG1]] = !{!"btf_tag", !"tag1"} +// CHECK: ![[TAG2]] = !{!"btf_tag", !"tag2"} diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -936,10 +936,12 @@ unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData, StorageType Storage, bool ShouldCreate = true) { + Metadata *ExtraData, DINodeArray Annotations, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - DWARFAddressSpace, Flags, ExtraData, Storage, ShouldCreate); + DWARFAddressSpace, Flags, ExtraData, Annotations.get(), + Storage, ShouldCreate); } static DIDerivedType *getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, unsigned Line, @@ -948,13 +950,15 @@ uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, Metadata *ExtraData, - StorageType Storage, bool ShouldCreate = true); + Metadata *Annotations, StorageType Storage, + bool ShouldCreate = true); TempDIDerivedType cloneImpl() const { return getTemporary(getContext(), getTag(), getName(), getFile(), getLine(), getScope(), getBaseType(), getSizeInBits(), getAlignInBits(), getOffsetInBits(), - getDWARFAddressSpace(), getFlags(), getExtraData()); + getDWARFAddressSpace(), getFlags(), getExtraData(), + getAnnotations()); } public: @@ -964,19 +968,21 @@ uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr), + Metadata *ExtraData = nullptr, + Metadata *Annotations = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)) + ExtraData, Annotations)) DEFINE_MDNODE_GET(DIDerivedType, (unsigned Tag, StringRef Name, DIFile *File, unsigned Line, DIScope *Scope, DIType *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, - Metadata *ExtraData = nullptr), + Metadata *ExtraData = nullptr, + DINodeArray Annotations = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)) + ExtraData, Annotations)) TempDIDerivedType clone() const { return cloneImpl(); } @@ -999,6 +1005,17 @@ Metadata *getExtraData() const { return getRawExtraData(); } Metadata *getRawExtraData() const { return getOperand(4); } + /// Get annotations associated with this derived type. + DINodeArray getAnnotations() const { + return cast_or_null(getRawAnnotations()); + } + Metadata *getRawAnnotations() const { return getOperand(5); } + + /// Replace annotations operand. + void replaceAnnotations(DINodeArray Annotations) { + replaceOperandWith(5, Annotations.get()); + } + /// Get casted version of extra data. /// @{ DIType *getClassType() const { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -4578,7 +4578,8 @@ OPTIONAL(offset, MDUnsignedField, (0, UINT64_MAX)); \ OPTIONAL(flags, DIFlagField, ); \ OPTIONAL(extraData, MDField, ); \ - OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); + OPTIONAL(dwarfAddressSpace, MDUnsignedField, (UINT32_MAX, UINT32_MAX)); \ + OPTIONAL(annotations, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4590,7 +4591,7 @@ (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val, size.Val, align.Val, offset.Val, DWARFAddressSpace, flags.Val, - extraData.Val)); + extraData.Val, annotations.Val)); return false; } diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1437,7 +1437,7 @@ break; } case bitc::METADATA_DERIVED_TYPE: { - if (Record.size() < 12 || Record.size() > 13) + if (Record.size() < 12 || Record.size() > 14) return error("Invalid record"); // DWARF address space is encoded as N->getDWARFAddressSpace() + 1. 0 means @@ -1446,6 +1446,10 @@ if (Record.size() > 12 && Record[12]) DWARFAddressSpace = Record[12] - 1; + Metadata *Annotations = nullptr; + if (Record.size() > 13 && Record[13]) + Annotations = getMDOrNull(Record[13]); + IsDistinct = Record[0]; DINode::DIFlags Flags = static_cast(Record[10]); MetadataList.assignValue( @@ -1455,7 +1459,8 @@ getDITypeRefOrNull(Record[5]), getDITypeRefOrNull(Record[6]), Record[7], Record[8], Record[9], DWARFAddressSpace, Flags, - getDITypeRefOrNull(Record[11]))), + getDITypeRefOrNull(Record[11]), + Annotations)), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1687,6 +1687,8 @@ else Record.push_back(0); + Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); + Stream.EmitRecord(bitc::METADATA_DERIVED_TYPE, Record, Abbrev); Record.clear(); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -2040,6 +2040,7 @@ if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace()) Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace, /* ShouldSkipZero */ false); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -582,13 +582,13 @@ unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, DIFlags Flags, Metadata *ExtraData, - StorageType Storage, bool ShouldCreate) { + Metadata *Annotations, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIDerivedType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags, - ExtraData)); - Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData}; + ExtraData, Annotations)); + Metadata *Ops[] = {File, Scope, Name, BaseType, ExtraData, Annotations}; DEFINE_GETIMPL_STORE( DIDerivedType, (Tag, Line, SizeInBits, AlignInBits, OffsetInBits, DWARFAddressSpace, Flags), Ops); diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -471,23 +471,24 @@ Optional DWARFAddressSpace; unsigned Flags; Metadata *ExtraData; + Metadata *Annotations; MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, Optional DWARFAddressSpace, unsigned Flags, - Metadata *ExtraData) + Metadata *ExtraData, Metadata *Annotations) : Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope), BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits), AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace), - Flags(Flags), ExtraData(ExtraData) {} + Flags(Flags), ExtraData(ExtraData), Annotations(Annotations) {} MDNodeKeyImpl(const DIDerivedType *N) : Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()), Scope(N->getRawScope()), BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()), OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()), DWARFAddressSpace(N->getDWARFAddressSpace()), Flags(N->getFlags()), - ExtraData(N->getRawExtraData()) {} + ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIDerivedType *RHS) const { return Tag == RHS->getTag() && Name == RHS->getRawName() && @@ -498,7 +499,8 @@ OffsetInBits == RHS->getOffsetInBits() && DWARFAddressSpace == RHS->getDWARFAddressSpace() && Flags == RHS->getFlags() && - ExtraData == RHS->getRawExtraData(); + ExtraData == RHS->getRawExtraData() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { diff --git a/llvm/test/Bitcode/attr-btf_tag-field.ll b/llvm/test/Bitcode/attr-btf_tag-field.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_tag-field.ll @@ -0,0 +1,36 @@ +; REQUIRES: x86-registered-target +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +%struct.t = type { i32 } + +@g = dso_local local_unnamed_addr global %struct.t zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!13, !14, !15, !16} +!llvm.ident = !{!17} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 1b8d548385089fd516c11cd69d20c4ad33cae328)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "struct.c", directory: "/home/yhs/work/tests/llvm/btf_tag") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, size: 32, elements: !7) +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3, line: 1, baseType: !9, size: 32, annotations: !10) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{!11, !12} +!11 = !{!"btf_tag", !"a"} +!12 = !{!"btf_tag", !"b"} + +; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "a" +; CHECK-SAME: annotations: ![[ANNOT:[0-9]+]] +; CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +; CHECK: ![[TAG1]] = !{!"btf_tag", !"a"} +; CHECK: ![[TAG2]] = !{!"btf_tag", !"b"} + +!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 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 1b8d548385089fd516c11cd69d20c4ad33cae328)"}