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 @@ -3951,10 +3951,13 @@ unsigned ScopeLine = getLineNumber(ScopeLoc); llvm::DISubroutineType *DIFnType = getOrCreateFunctionType(D, FnType, Unit); llvm::DISubprogram *Decl = nullptr; - if (D) + llvm::DINodeArray Annotations = nullptr; + if (D) { Decl = isa(D) ? getObjCMethodDeclaration(D, DIFnType, LineNo, Flags, SPFlags) : getFunctionDeclaration(D); + Annotations = CollectBTFTagAnnotations(D); + } // FIXME: The function declaration we're constructing here is mostly reusing // declarations from CXXMethodDecl and not constructing new ones for arbitrary @@ -3963,7 +3966,8 @@ // are emitted as CU level entities by the backend. llvm::DISubprogram *SP = DBuilder.createFunction( FDContext, Name, LinkageName, Unit, LineNo, DIFnType, ScopeLine, - FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl); + FlagsForDef, SPFlagsForDef, TParamsArray.get(), Decl, nullptr, + Annotations); Fn->setSubprogram(SP); // We might get here with a VarDecl in the case we're generating // code for the initialization of globals. Do not record these decls diff --git a/clang/test/CodeGen/attr-btf_tag-disubprogram.c b/clang/test/CodeGen/attr-btf_tag-disubprogram.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/attr-btf_tag-disubprogram.c @@ -0,0 +1,40 @@ +// 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; +}; + +int __tag1 __tag2 foo(struct t1 *arg) { + return arg->a; +} + +// CHECK: distinct !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], scopeLine: [[#]], flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], retainedNodes: ![[#]], annotations: ![[ANNOT:[0-9]+]]) +// CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +// CHECK: ![[TAG1]] = !{!"btf_tag", !"tag1"} +// CHECK: ![[TAG2]] = !{!"btf_tag", !"tag2"} + +int __tag1 __tag2 foo2(struct t1 *arg); +int foo2(struct t1 *arg) { + return arg->a; +} + +// CHECK: distinct !DISubprogram(name: "foo2", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], scopeLine: [[#]], flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], retainedNodes: ![[#]], annotations: ![[ANNOT]]) + +int __tag1 foo3(struct t1 *arg); +int __tag2 foo3(struct t1 *arg) { + return arg->a; +} + +// CHECK: distinct !DISubprogram(name: "foo3", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], scopeLine: [[#]], flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], retainedNodes: ![[#]], annotations: ![[ANNOT]]) + +int __tag1 foo4(struct t1 *arg); +int __tag2 foo4(struct t1 *arg); +int foo4(struct t1 *arg) { + return arg->a; +} + +// CHECK: distinct !DISubprogram(name: "foo4", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], scopeLine: [[#]], flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: ![[#]], retainedNodes: ![[#]], 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 @@ -716,6 +716,7 @@ /// \param SPFlags Additional flags specific to subprograms. /// \param TParams Function template parameters. /// \param ThrownTypes Exception types this function may throw. + /// \param Annotations Attribute Annotations. DISubprogram * createFunction(DIScope *Scope, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DISubroutineType *Ty, @@ -723,7 +724,8 @@ DISubprogram::DISPFlags SPFlags = DISubprogram::SPFlagZero, DITemplateParameterArray TParams = nullptr, DISubprogram *Decl = nullptr, - DITypeArray ThrownTypes = nullptr); + DITypeArray ThrownTypes = nullptr, + DINodeArray Annotations = nullptr); /// Identical to createFunction, /// except that the resulting DbgNode is 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 @@ -1892,13 +1892,14 @@ DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams, DISubprogram *Declaration, DINodeArray RetainedNodes, DITypeArray ThrownTypes, - StorageType Storage, bool ShouldCreate = true) { + DINodeArray Annotations, StorageType Storage, + bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams.get(), Declaration, - RetainedNodes.get(), ThrownTypes.get(), Storage, - ShouldCreate); + RetainedNodes.get(), ThrownTypes.get(), Annotations.get(), + Storage, ShouldCreate); } static DISubprogram *getImpl(LLVMContext &Context, Metadata *Scope, MDString *Name, MDString *LinkageName, @@ -1908,7 +1909,8 @@ DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, Metadata *ThrownTypes, - StorageType Storage, bool ShouldCreate = true); + Metadata *Annotations, StorageType Storage, + bool ShouldCreate = true); TempDISubprogram cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), @@ -1916,7 +1918,7 @@ getContainingType(), getVirtualIndex(), getThisAdjustment(), getFlags(), getSPFlags(), getUnit(), getTemplateParams(), getDeclaration(), - getRetainedNodes(), getThrownTypes()); + getRetainedNodes(), getThrownTypes(), getAnnotations()); } public: @@ -1928,10 +1930,10 @@ DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams = nullptr, DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, - DITypeArray ThrownTypes = nullptr), + DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes)) + Declaration, RetainedNodes, ThrownTypes, Annotations)) DEFINE_MDNODE_GET( DISubprogram, @@ -1940,10 +1942,11 @@ Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams = nullptr, Metadata *Declaration = nullptr, - Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr), + Metadata *RetainedNodes = nullptr, Metadata *ThrownTypes = nullptr, + Metadata *Annotations = nullptr), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, - Declaration, RetainedNodes, ThrownTypes)) + Declaration, RetainedNodes, ThrownTypes, Annotations)) TempDISubprogram clone() const { return cloneImpl(); } @@ -2046,6 +2049,9 @@ DITypeArray getThrownTypes() const { return cast_or_null(getRawThrownTypes()); } + DINodeArray getAnnotations() const { + return cast_or_null(getRawAnnotations()); + } Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs(2); } @@ -2063,6 +2069,9 @@ Metadata *getRawThrownTypes() const { return getNumOperands() > 10 ? getOperandAs(10) : nullptr; } + Metadata *getRawAnnotations() const { + return getNumOperands() > 11 ? getOperandAs(11) : nullptr; + } void replaceRawLinkageName(MDString *LinkageName) { replaceOperandWith(3, LinkageName); 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 @@ -4724,7 +4724,8 @@ /// virtuality: DW_VIRTUALTIY_pure_virtual, /// virtualIndex: 10, thisAdjustment: 4, flags: 11, /// spFlags: 10, isOptimized: false, templateParams: !4, -/// declaration: !5, retainedNodes: !6, thrownTypes: !7) +/// declaration: !5, retainedNodes: !6, thrownTypes: !7, +/// annotations: !8) bool LLParser::parseDISubprogram(MDNode *&Result, bool IsDistinct) { auto Loc = Lex.getLoc(); #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ @@ -4748,7 +4749,8 @@ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ OPTIONAL(retainedNodes, MDField, ); \ - OPTIONAL(thrownTypes, MDField, ); + OPTIONAL(thrownTypes, MDField, ); \ + OPTIONAL(annotations, MDField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4767,7 +4769,7 @@ (Context, scope.Val, name.Val, linkageName.Val, file.Val, line.Val, type.Val, scopeLine.Val, containingType.Val, virtualIndex.Val, thisAdjustment.Val, flags.Val, SPFlags, unit.Val, templateParams.Val, - declaration.Val, retainedNodes.Val, thrownTypes.Val)); + declaration.Val, retainedNodes.Val, thrownTypes.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 @@ -1693,6 +1693,7 @@ bool HasFn = false; bool HasThisAdj = true; bool HasThrownTypes = true; + bool HasAnnotations = false; unsigned OffsetA = 0; unsigned OffsetB = 0; if (!HasSPFlags) { @@ -1704,6 +1705,8 @@ } HasThisAdj = Record.size() >= 20; HasThrownTypes = Record.size() >= 21; + } else { + HasAnnotations = Record.size() >= 19; } Metadata *CUorFn = getMDOrNull(Record[12 + OffsetB]); DISubprogram *SP = GET_OR_DISTINCT( @@ -1726,7 +1729,9 @@ getMDOrNull(Record[14 + OffsetB]), // declaration getMDOrNull(Record[15 + OffsetB]), // retainedNodes HasThrownTypes ? getMDOrNull(Record[17 + OffsetB]) - : nullptr // thrownTypes + : nullptr, // thrownTypes + HasAnnotations ? getMDOrNull(Record[18 + OffsetB]) + : nullptr // annotations )); MetadataList.assignValue(SP, NextMetadataNo); NextMetadataNo++; 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 @@ -1814,6 +1814,7 @@ Record.push_back(VE.getMetadataOrNullID(N->getRetainedNodes().get())); Record.push_back(N->getThisAdjustment()); Record.push_back(VE.getMetadataOrNullID(N->getThrownTypes().get())); + Record.push_back(VE.getMetadataOrNullID(N->getAnnotations().get())); Stream.EmitRecord(bitc::METADATA_SUBPROGRAM, 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 @@ -2160,6 +2160,7 @@ Printer.printMetadata("declaration", N->getRawDeclaration()); Printer.printMetadata("retainedNodes", N->getRawRetainedNodes()); Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); + 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 @@ -819,13 +819,14 @@ unsigned LineNo, DISubroutineType *Ty, unsigned ScopeLine, DINode::DIFlags Flags, DISubprogram::DISPFlags SPFlags, DITemplateParameterArray TParams, DISubprogram *Decl, - DITypeArray ThrownTypes) { + DITypeArray ThrownTypes, DINodeArray Annotations) { bool IsDefinition = SPFlags & DISubprogram::SPFlagDefinition; auto *Node = getSubprogram( /*IsDistinct=*/IsDefinition, VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, ScopeLine, nullptr, 0, 0, Flags, SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, - MDTuple::getTemporary(VMContext, None).release(), ThrownTypes); + MDTuple::getTemporary(VMContext, None).release(), ThrownTypes, + Annotations); if (IsDefinition) AllSubprograms.push_back(Node); 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 @@ -864,23 +864,28 @@ unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) { + Metadata *ThrownTypes, Metadata *Annotations, StorageType Storage, + bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); assert(isCanonical(LinkageName) && "Expected canonical MDString"); DEFINE_GETIMPL_LOOKUP(DISubprogram, (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, VirtualIndex, ThisAdjustment, Flags, SPFlags, Unit, TemplateParams, Declaration, - RetainedNodes, ThrownTypes)); - SmallVector Ops = { + RetainedNodes, ThrownTypes, Annotations)); + SmallVector Ops = { File, Scope, Name, LinkageName, Type, Unit, - Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes}; - if (!ThrownTypes) { + Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes, + Annotations}; + if (!Annotations) { Ops.pop_back(); - if (!TemplateParams) { + if (!ThrownTypes) { Ops.pop_back(); - if (!ContainingType) + if (!TemplateParams) { Ops.pop_back(); + if (!ContainingType) + Ops.pop_back(); + } } } DEFINE_GETIMPL_STORE_N( 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 @@ -696,6 +696,7 @@ Metadata *Declaration; Metadata *RetainedNodes; Metadata *ThrownTypes; + Metadata *Annotations; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, @@ -703,13 +704,14 @@ unsigned VirtualIndex, int ThisAdjustment, unsigned Flags, unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes, - Metadata *ThrownTypes) + Metadata *ThrownTypes, Metadata *Annotations) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), ScopeLine(ScopeLine), ContainingType(ContainingType), VirtualIndex(VirtualIndex), ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags), Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration), - RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes) {} + RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes), + Annotations(Annotations) {} MDNodeKeyImpl(const DISubprogram *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), @@ -721,7 +723,8 @@ TemplateParams(N->getRawTemplateParams()), Declaration(N->getRawDeclaration()), RetainedNodes(N->getRawRetainedNodes()), - ThrownTypes(N->getRawThrownTypes()) {} + ThrownTypes(N->getRawThrownTypes()), Annotations(N->getRawAnnotations()) + {} bool isKeyOf(const DISubprogram *RHS) const { return Scope == RHS->getRawScope() && Name == RHS->getRawName() && @@ -736,7 +739,8 @@ TemplateParams == RHS->getRawTemplateParams() && Declaration == RHS->getRawDeclaration() && RetainedNodes == RHS->getRawRetainedNodes() && - ThrownTypes == RHS->getRawThrownTypes(); + ThrownTypes == RHS->getRawThrownTypes() && + Annotations == RHS->getRawAnnotations(); } bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; } diff --git a/llvm/test/Bitcode/attr-btf_tag-disubprogram.ll b/llvm/test/Bitcode/attr-btf_tag-disubprogram.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Bitcode/attr-btf_tag-disubprogram.ll @@ -0,0 +1,46 @@ +; REQUIRES: x86-registered-target +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn +define dso_local i32 @f(i32 %a) local_unnamed_addr #0 !dbg !8 { +entry: + call void @llvm.dbg.value(metadata i32 %a, metadata !13, metadata !DIExpression()), !dbg !17 + ret i32 0, !dbg !18 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone uwtable willreturn "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nofree nosync nounwind readnone speculatable willreturn } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git a6dd9d402a04d53403664bbb47771f2573c7ade0)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "func.c", directory: "/home/yhs/work/tests/llvm/btf_tag") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{i32 7, !"uwtable", i32 1} +!7 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git a6dd9d402a04d53403664bbb47771f2573c7ade0)"} +!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !9, scopeLine: 1, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12, annotations: !14) +!9 = !DISubroutineType(types: !10) +!10 = !{!11, !11} +!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!12 = !{!13} +!13 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 1, type: !11) +!14 = !{!15, !16} +!15 = !{!"btf_tag", !"a"} +!16 = !{!"btf_tag", !"b"} + +; CHECK: distinct !DISubprogram(name: "f" +; CHECK-SAME: annotations: ![[ANNOT:[0-9]+]] +; CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} +; CHECK: ![[TAG1]] = !{!"btf_tag", !"a"} +; CHECK: ![[TAG2]] = !{!"btf_tag", !"b"} + +!17 = !DILocation(line: 0, scope: !8) +!18 = !DILocation(line: 1, column: 77, scope: !8)