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 @@ -4832,12 +4832,16 @@ } AppendAddressSpaceXDeref(AddressSpace, Expr); + llvm::DINodeArray Annotations = nullptr; + if (D->hasAttr()) + Annotations = CollectBTFTagAnnotations(D); + GVE = DBuilder.createGlobalVariableExpression( DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit), Var->hasLocalLinkage(), true, Expr.empty() ? nullptr : DBuilder.createExpression(Expr), getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, - Align); + Align, Annotations); Var->addDebugInfo(GVE); } DeclCache[D->getCanonicalDecl()].reset(GVE); diff --git a/clang/test/CodeGen/attr-btf_tag-diglobalvariable.c b/clang/test/CodeGen/attr-btf_tag-diglobalvariable.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_tag-diglobalvariable.c @@ -0,0 +1,29 @@ +// 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; +}; +struct t1 g1 __tag1 __tag2; + +extern struct t1 g2 __tag1 __tag2; +struct t1 g2; + +// CHECK: distinct !DIGlobalVariable(name: "g1", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], isLocal: false, isDefinition: true, annotations: ![[ANNOT:[0-9]+]]) +// CHECK: distinct !DIGlobalVariable(name: "g2", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], isLocal: false, isDefinition: true, annotations: ![[ANNOT]]) +// CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +// CHECK: ![[TAG1]] = !{!"btf_tag", !"tag1"} +// CHECK: ![[TAG2]] = !{!"btf_tag", !"tag2"} + +extern struct t1 g3 __tag1; +struct t1 g3 __tag2; + +// CHECK: distinct !DIGlobalVariable(name: "g3", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], isLocal: false, isDefinition: true, annotations: ![[ANNOT]]) + +extern struct t1 g4; +struct t1 g4 __tag1 __tag2; + +// CHECK: distinct !DIGlobalVariable(name: "g4", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], isLocal: false, isDefinition: true, annotations: ![[ANNOT]]) diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -636,7 +636,8 @@ DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DIType *Ty, bool IsLocalToUnit, bool isDefined = true, DIExpression *Expr = nullptr, MDNode *Decl = nullptr, - MDTuple *TemplateParams = nullptr, uint32_t AlignInBits = 0); + MDTuple *TemplateParams = nullptr, uint32_t AlignInBits = 0, + DINodeArray Annotations = nullptr); /// Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. 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 @@ -2967,25 +2967,28 @@ StringRef LinkageName, DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, - uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) { + uint32_t AlignInBits, DINodeArray Annotations, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - cast_or_null(TemplateParams), AlignInBits, Storage, - ShouldCreate); + cast_or_null(TemplateParams), AlignInBits, + Annotations.get(), Storage, ShouldCreate); } static DIGlobalVariable * getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true); + uint32_t AlignInBits, Metadata *Annotations, StorageType Storage, + bool ShouldCreate = true); TempDIGlobalVariable cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getStaticDataMemberDeclaration(), - getTemplateParams(), getAlignInBits()); + getTemplateParams(), getAlignInBits(), + getAnnotations()); } public: @@ -2994,19 +2997,21 @@ DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, - MDTuple *TemplateParams, uint32_t AlignInBits), + MDTuple *TemplateParams, uint32_t AlignInBits, + DINodeArray Annotations), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, TemplateParams, - AlignInBits)) + AlignInBits, Annotations)) DEFINE_MDNODE_GET(DIGlobalVariable, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, - Metadata *TemplateParams, uint32_t AlignInBits), + Metadata *TemplateParams, uint32_t AlignInBits, + Metadata *Annotations), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, TemplateParams, - AlignInBits)) + AlignInBits, Annotations)) TempDIGlobalVariable clone() const { return cloneImpl(); } @@ -3017,11 +3022,15 @@ DIDerivedType *getStaticDataMemberDeclaration() const { return cast_or_null(getRawStaticDataMemberDeclaration()); } + DINodeArray getAnnotations() const { + return cast_or_null(getRawAnnotations()); + } MDString *getRawLinkageName() const { return getOperandAs(5); } Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } Metadata *getRawTemplateParams() const { return getOperand(7); } MDTuple *getTemplateParams() const { return getOperandAs(7); } + Metadata *getRawAnnotations() const { return getOperand(8); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIGlobalVariableKind; 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 @@ -4971,7 +4971,8 @@ OPTIONAL(isDefinition, MDBoolField, (true)); \ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(annotations, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4979,7 +4980,8 @@ GET_OR_DISTINCT(DIGlobalVariable, (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, type.Val, isLocal.Val, isDefinition.Val, - declaration.Val, templateParams.Val, align.Val)); + declaration.Val, templateParams.Val, align.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 @@ -1874,13 +1874,18 @@ unsigned Version = Record[0] >> 1; if (Version == 2) { + Metadata *Annotations = nullptr; + if (Record.size() > 12) + Annotations = getMDOrNull(Record[12]); + MetadataList.assignValue( GET_OR_DISTINCT( DIGlobalVariable, (Context, getMDOrNull(Record[1]), getMDString(Record[2]), getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], getDITypeRefOrNull(Record[6]), Record[7], Record[8], - getMDOrNull(Record[9]), getMDOrNull(Record[10]), Record[11])), + getMDOrNull(Record[9]), getMDOrNull(Record[10]), Record[11], + Annotations)), NextMetadataNo); NextMetadataNo++; @@ -1893,7 +1898,8 @@ getMDString(Record[2]), getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], getDITypeRefOrNull(Record[6]), Record[7], Record[8], - getMDOrNull(Record[10]), nullptr, Record[11])), + getMDOrNull(Record[10]), nullptr, Record[11], + nullptr)), NextMetadataNo); NextMetadataNo++; @@ -1926,7 +1932,7 @@ (Context, getMDOrNull(Record[1]), getMDString(Record[2]), getMDString(Record[3]), getMDOrNull(Record[4]), Record[5], getDITypeRefOrNull(Record[6]), Record[7], Record[8], - getMDOrNull(Record[10]), nullptr, AlignInBits)); + getMDOrNull(Record[10]), nullptr, AlignInBits, nullptr)); DIGlobalVariableExpression *DGVE = nullptr; if (Attach || Expr) 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 @@ -1962,6 +1962,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration())); Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams())); Record.push_back(N->getAlignInBits()); + Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, 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 @@ -2300,6 +2300,7 @@ Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printInt("align", N->getAlignInBits()); + Printer.printMetadata("annotations", N->getRawAnnotations()); Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -703,13 +703,14 @@ DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, unsigned LineNumber, DIType *Ty, bool IsLocalToUnit, bool isDefined, DIExpression *Expr, - MDNode *Decl, MDTuple *TemplateParams, uint32_t AlignInBits) { + MDNode *Decl, MDTuple *TemplateParams, uint32_t AlignInBits, + DINodeArray Annotations) { checkGlobalVariableScope(Context); auto *GV = DIGlobalVariable::getDistinct( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, IsLocalToUnit, isDefined, cast_or_null(Decl), - TemplateParams, AlignInBits); + TemplateParams, AlignInBits, Annotations); if (!Expr) Expr = createExpression(); auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr); @@ -726,7 +727,8 @@ return DIGlobalVariable::getTemporary( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, IsLocalToUnit, false, - cast_or_null(Decl), TemplateParams, AlignInBits) + cast_or_null(Decl), TemplateParams, AlignInBits, + nullptr) .release(); } 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 @@ -984,13 +984,15 @@ Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, uint32_t AlignInBits, - StorageType Storage, bool ShouldCreate) { + Metadata *Annotations, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DIGlobalVariable, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - TemplateParams, AlignInBits)); + TemplateParams, AlignInBits, + Annotations)); Metadata *Ops[] = {Scope, Name, File, @@ -998,7 +1000,8 @@ Name, LinkageName, StaticDataMemberDeclaration, - TemplateParams}; + TemplateParams, + Annotations}; DEFINE_GETIMPL_STORE(DIGlobalVariable, (Line, IsLocalToUnit, IsDefinition, AlignInBits), 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 @@ -984,17 +984,19 @@ Metadata *StaticDataMemberDeclaration; Metadata *TemplateParams; uint32_t AlignInBits; + Metadata *Annotations; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits) + uint32_t AlignInBits, Metadata *Annotations) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), StaticDataMemberDeclaration(StaticDataMemberDeclaration), - TemplateParams(TemplateParams), AlignInBits(AlignInBits) {} + TemplateParams(TemplateParams), AlignInBits(AlignInBits), + Annotations(Annotations) {} MDNodeKeyImpl(const DIGlobalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -1002,7 +1004,7 @@ IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()), TemplateParams(N->getRawTemplateParams()), - AlignInBits(N->getAlignInBits()) {} + AlignInBits(N->getAlignInBits()), Annotations(N->getRawAnnotations()) {} bool isKeyOf(const DIGlobalVariable *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -1013,7 +1015,8 @@ StaticDataMemberDeclaration == RHS->getRawStaticDataMemberDeclaration() && TemplateParams == RHS->getRawTemplateParams() && - AlignInBits == RHS->getAlignInBits(); + AlignInBits == RHS->getAlignInBits() && + Annotations == RHS->getRawAnnotations(); } unsigned getHashValue() const { @@ -1026,7 +1029,7 @@ // TODO: make hashing work fine with such situations return hash_combine(Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, /* AlignInBits, */ - StaticDataMemberDeclaration); + StaticDataMemberDeclaration, Annotations); } }; diff --git a/llvm/test/Bitcode/attr-btf_tag-diglobalvariable.ll b/llvm/test/Bitcode/attr-btf_tag-diglobalvariable.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_tag-diglobalvariable.ll @@ -0,0 +1,37 @@ +; REQUIRES: x86-registered-target +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +%struct.t1 = type { i32 } + +@g1 = dso_local global %struct.t1 zeroinitializer, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!13, !14, !15, !16, !17} +!llvm.ident = !{!18} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "g1", scope: !2, file: !3, line: 7, type: !6, isLocal: false, isDefinition: true, annotations: !10) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 47af5574a87dc298b5c6c36ff6a969c8c77c8499)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "t.c", directory: "/home/yhs/work/tests/llvm/btf_tag") +!4 = !{} +!5 = !{!0} +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", file: !3, line: 4, size: 32, elements: !7) +!7 = !{!8} +!8 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !6, file: !3, line: 5, baseType: !9, size: 32) +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{!11, !12} +!11 = !{!"btf_tag", !"tag1"} +!12 = !{!"btf_tag", !"tag2"} + +; CHECK: distinct !DIGlobalVariable(name: "g1" +; CHECK-SAME: annotations: ![[ANNOT:[0-9]+]] +; CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +; CHECK: ![[TAG1]] = !{!"btf_tag", !"tag1"} +; CHECK: ![[TAG2]] = !{!"btf_tag", !"tag2"} + +!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 13.0.0 (https://github.com/llvm/llvm-project.git 47af5574a87dc298b5c6c36ff6a969c8c77c8499)"}