diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -432,6 +432,9 @@ /// propagate signaling NaN inputs per IEEE 754-2008 (AMDGPU Only) CODEGENOPT(EmitIEEENaNCompliantInsts, 1, 1) +/// Whether to emit Annotations in dwarf sections +CODEGENOPT(EmitAnnotations, 1, 0) + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2898,6 +2898,10 @@ def gno_embed_source : Flag<["-"], "gno-embed-source">, Group, Flags<[NoXarchOption]>, HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">; +def gannotations : Flag<["-"], "gannotations">, Group, + MarshallingInfoFlag>, + Flags<[CC1Option]>, + HelpText<"Emit annotations in DWARF debug sections">; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption, FC1Option, FlangOption]>, HelpText<"Display available options">, 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 @@ -1516,6 +1516,11 @@ FieldType = createFieldType(name, type, field->getLocation(), field->getAccess(), OffsetInBits, Align, tunit, RecordTy, RD); + if (CGM.getCodeGenOpts().EmitAnnotations && + field->hasAttr()) { + for (const auto *I : field->specific_attrs()) + FieldType->addAnnotation(I->getAnnotation()); + } } elements.push_back(FieldType); @@ -3487,6 +3492,11 @@ break; } + if (CGM.getCodeGenOpts().EmitAnnotations && D->hasAttr()) { + for (const auto *I : D->specific_attrs()) + RealDecl->addAnnotation(I->getAnnotation()); + } + RegionMap[Ty->getDecl()].reset(RealDecl); TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); @@ -3977,6 +3987,11 @@ if (HasDecl && isa(D)) DeclCache[D->getCanonicalDecl()].reset(SP); + if (CGM.getCodeGenOpts().EmitAnnotations && D->hasAttr()) { + for (const auto *I : D->specific_attrs()) + SP->addAnnotation(I->getAnnotation()); + } + // Push the function onto the lexical block stack. LexicalBlockStack.emplace_back(SP); @@ -4375,6 +4390,10 @@ if (ArgNo) { D = DBuilder.createParameterVariable(Scope, Name, *ArgNo, Unit, Line, Ty, CGM.getLangOpts().Optimize, Flags); + if (CGM.getCodeGenOpts().EmitAnnotations && VD->hasAttr()) { + for (const auto *I : VD->specific_attrs()) + D->addAnnotation(I->getAnnotation()); + } } else { // For normal local variable, we will try to find out whether 'VD' is the // copy parameter of coroutine. @@ -4833,6 +4852,12 @@ getOrCreateStaticDataMemberDeclarationOrNull(D), TemplateParameters, Align); Var->addDebugInfo(GVE); + + if (CGM.getCodeGenOpts().EmitAnnotations && D->hasAttr()) { + auto DIVar = GVE->getVariable(); + for (const auto *I : D->specific_attrs()) + DIVar->addAnnotation(I->getAnnotation()); + } } DeclCache[D->getCanonicalDecl()].reset(GVE); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3968,6 +3968,11 @@ } } + if (const Arg *A = Args.getLastArg(options::OPT_gannotations)) { + if (checkDebugInfoOption(A, Args, D, TC)) + CmdArgs.push_back("-gannotations"); + } + unsigned RequestedDWARFVersion = 0; // DWARF version requested by the user unsigned EffectiveDWARFVersion = 0; // DWARF version TC can generate. It may // be lower than what the user wanted. diff --git a/clang/test/CodeGen/annotation-1.c b/clang/test/CodeGen/annotation-1.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/annotation-1.c @@ -0,0 +1,30 @@ +// REQUIRES: x86-registered-target +// RUN: %clang %s -g -target x86_64 -gannotations -S -emit-llvm -o - | FileCheck %s + +static volatile int s1 __attribute__((annotate("static1"))); +int g1 __attribute__((annotate("global1"))) __attribute__((annotate("global2"))); +int test1() { + return s1 + g1; +} + +// CHECK: distinct !DIGlobalVariable(name: "s1" +// CHECK-SAME: annotations: "static1" +// CHECK: distinct !DIGlobalVariable(name: "g1" +// CHECK-SAME: annotations: "global1,global2" + +static int __attribute__((annotate("sfunc"))) __attribute__((noinline)) +func1(int a, int b) { + return a + b; +} + +int __attribute__((annotate("gfunc"))) +func2(int a __attribute__((annotate("param"))), int b) { + return func1(a, b); +} + +// CHECK: distinct !DISubprogram(name: "func2" +// CHECK-SAME: annotations: "gfunc" +// CHECK: !DILocalVariable(name: "a" +// CHECK-SAME: annotations: "param" +// CHECK: distinct !DISubprogram(name: "func1" +// CHECK-SAME: annotations: "sfunc" diff --git a/clang/test/CodeGen/annotation-2.c b/clang/test/CodeGen/annotation-2.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/annotation-2.c @@ -0,0 +1,14 @@ +// REQUIRES: x86-registered-target +// RUN: %clang %s -g -target x86_64 -gannotations -S -emit-llvm -o - | FileCheck %s + +struct t { + int a __attribute__((annotate("gfield"))); +} __attribute__((annotate("gstruct"))); +int test(struct t *arg) { + return arg->a; +} + +// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t" +// CHECK-SAME: annotations: "gstruct" +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "a" +// CHECK-SAME: annotations: "gfield" diff --git a/llvm/include/llvm/BinaryFormat/Dwarf.def b/llvm/include/llvm/BinaryFormat/Dwarf.def --- a/llvm/include/llvm/BinaryFormat/Dwarf.def +++ b/llvm/include/llvm/BinaryFormat/Dwarf.def @@ -595,6 +595,7 @@ HANDLE_DW_AT(0x3e03, LLVM_tag_offset, 0, LLVM) // The missing numbers here are reserved for ptrauth support. HANDLE_DW_AT(0x3e07, LLVM_apinotes, 0, APPLE) +HANDLE_DW_AT(0x3e08, LLVM_annotations, 0, LLVM) // Apple extensions. 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 @@ -128,12 +128,16 @@ friend class LLVMContextImpl; friend class MDNode; + std::string Annotations; + protected: DINode(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, - ArrayRef Ops1, ArrayRef Ops2 = None) + ArrayRef Ops1, ArrayRef Ops2 = None, + StringRef Annotations = StringRef()) : MDNode(C, ID, Storage, Ops1, Ops2) { assert(Tag < 1u << 16); SubclassData16 = Tag; + this->Annotations = Annotations.str(); } ~DINode() = default; @@ -183,6 +187,19 @@ static DIFlags splitFlags(DIFlags Flags, SmallVectorImpl &SplitFlags); + /// Add annotations. + /// + /// If there are multiple annotations for a particular DINode, + /// merge all these annotations into one string separated with ','. + void addAnnotation(StringRef Annotation) { + if (Annotations.empty()) + this->Annotations = Annotation.str(); + else + this->Annotations = this->Annotations + std::string(",") + + Annotation.str(); + } + const StringRef getAnnotations() const { return Annotations; } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -2489,9 +2506,10 @@ protected: DIVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Line, - ArrayRef Ops, uint32_t AlignInBits = 0) - : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops), Line(Line), - AlignInBits(AlignInBits) {} + ArrayRef Ops, uint32_t AlignInBits = 0, + StringRef Annotations = StringRef()) + : DINode(C, ID, Storage, dwarf::DW_TAG_variable, Ops, None, Annotations), + Line(Line), AlignInBits(AlignInBits) {} ~DIVariable() = default; public: @@ -2914,8 +2932,9 @@ DIGlobalVariable(LLVMContext &C, StorageType Storage, unsigned Line, bool IsLocalToUnit, bool IsDefinition, uint32_t AlignInBits, - ArrayRef Ops) - : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits), + MDString *Annotations, ArrayRef Ops) + : DIVariable(C, DIGlobalVariableKind, Storage, Line, Ops, AlignInBits, + Annotations ? Annotations->getString() : StringRef()), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} ~DIGlobalVariable() = default; @@ -2924,11 +2943,13 @@ 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, StringRef 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, + cast_or_null(TemplateParams), AlignInBits, + getCanonicalMDString(Context, Annotations), Storage, ShouldCreate); } static DIGlobalVariable * @@ -2936,13 +2957,15 @@ 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, MDString *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: @@ -2951,19 +2974,21 @@ DIFile *File, unsigned Line, DIType *Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, - MDTuple *TemplateParams, uint32_t AlignInBits), + MDTuple *TemplateParams, uint32_t AlignInBits, + StringRef 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, + MDString *Annotations), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, TemplateParams, - AlignInBits)) + AlignInBits, Annotations)) TempDIGlobalVariable clone() const { return cloneImpl(); } @@ -2979,6 +3004,7 @@ Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } Metadata *getRawTemplateParams() const { return getOperand(7); } MDTuple *getTemplateParams() const { return getOperandAs(7); } + MDString *getRawAnnotations() const { return getOperandAs(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 @@ -4880,7 +4880,7 @@ /// ::= !DIDerivedType(tag: DW_TAG_pointer_type, name: "int", file: !0, /// line: 7, scope: !1, baseType: !2, size: 32, /// align: 32, offset: 0, flags: 0, extraData: !3, -/// dwarfAddressSpace: 3) +/// dwarfAddressSpace: 3, annotations: "bar") bool LLParser::parseDIDerivedType(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(tag, DwarfTagField, ); \ @@ -4894,7 +4894,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, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -4931,7 +4932,8 @@ OPTIONAL(dataLocation, MDField, ); \ OPTIONAL(associated, MDField, ); \ OPTIONAL(allocated, MDField, ); \ - OPTIONAL(rank, MDSignedOrMDField, ); + OPTIONAL(rank, MDSignedOrMDField, ); \ + OPTIONAL(annotations, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5062,7 +5064,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: "bar") bool LLParser::parseDISubprogram(MDNode *&Result, bool IsDistinct) { auto Loc = Lex.getLoc(); #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ @@ -5086,7 +5089,8 @@ OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ OPTIONAL(retainedNodes, MDField, ); \ - OPTIONAL(thrownTypes, MDField, ); + OPTIONAL(thrownTypes, MDField, ); \ + OPTIONAL(annotations, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5269,7 +5273,7 @@ /// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo", /// file: !1, line: 7, type: !2, isLocal: false, /// isDefinition: true, templateParams: !3, -/// declaration: !4, align: 8) +/// declaration: !4, align: 8, annotations: "bar") bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \ @@ -5282,7 +5286,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, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS @@ -5290,17 +5295,18 @@ 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; } /// parseDILocalVariable: /// ::= !DILocalVariable(arg: 7, scope: !0, name: "foo", /// file: !1, line: 7, type: !2, arg: 2, flags: 7, -/// align: 8) +/// align: 8, annotations: "bar") /// ::= !DILocalVariable(scope: !0, name: "foo", /// file: !1, line: 7, type: !2, arg: 2, flags: 7, -/// align: 8) +/// align: 8, annotations: "bar") bool LLParser::parseDILocalVariable(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(scope, MDField, (/* AllowNull */ false)); \ @@ -5310,7 +5316,8 @@ OPTIONAL(line, LineField, ); \ OPTIONAL(type, MDField, ); \ OPTIONAL(flags, DIFlagField, ); \ - OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); + OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); \ + OPTIONAL(annoations, MDStringField, ); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS 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 @@ -1866,7 +1866,8 @@ (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], + Record.size() == 13 ? getMDString(Record[12]) : nullptr)), NextMetadataNo); NextMetadataNo++; @@ -1879,7 +1880,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++; @@ -1912,7 +1914,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 @@ -1956,6 +1956,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->getRawAnnotations())); Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev); Record.clear(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -183,6 +183,9 @@ else addGlobalName(GV->getName(), *VariableDIE, DeclContext); + if (!GV->getAnnotations().empty()) + addAnnotations(*VariableDIE, GV); + if (uint32_t AlignInBytes = GV->getAlignInBytes()) addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, AlignInBytes); @@ -1479,11 +1482,15 @@ if (!Name.empty()) addString(VariableDie, dwarf::DW_AT_name, Name); const auto *DIVar = Var.getVariable(); - if (DIVar) + if (DIVar) { if (uint32_t AlignInBytes = DIVar->getAlignInBytes()) addUInt(VariableDie, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, AlignInBytes); + if (!DIVar->getAnnotations().empty()) + addAnnotations(VariableDie, DIVar); + } + addSourceLine(VariableDie, DIVar); addType(VariableDie, Var.getType()); if (Var.isArtificial()) diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -297,6 +297,9 @@ /// Get context owner's DIE. DIE *createTypeDIE(const DICompositeType *Ty); + /// Add annotations. + void addAnnotations(DIE &Die, const DINode *DN); + protected: ~DwarfUnit(); diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -957,6 +957,9 @@ if (!Name.empty()) addString(Buffer, dwarf::DW_AT_name, Name); + if (!CTy->getAnnotations().empty()) + addAnnotations(Buffer, CTy); + if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) { @@ -1191,6 +1194,9 @@ if (!SP->getName().empty()) addString(SPDie, dwarf::DW_AT_name, SP->getName()); + if (!SP->getAnnotations().empty()) + addAnnotations(SPDie, SP); + if (!SkipSPSourceLocation) addSourceLine(SPDie, SP); @@ -1541,6 +1547,9 @@ if (!Name.empty()) addString(MemberDie, dwarf::DW_AT_name, Name); + if (!DT->getAnnotations().empty()) + addAnnotations(MemberDie, DT); + if (DIType *Resolved = DT->getBaseType()) addType(MemberDie, Resolved); @@ -1794,6 +1803,10 @@ TLOF.getDwarfRnglistsSection()->getBeginSymbol()); } +void DwarfUnit::addAnnotations(DIE& D, const DINode *Ty) { + addString(D, dwarf::DW_AT_LLVM_annotations, Ty->getAnnotations()); +} + void DwarfTypeUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) { addFlag(D, dwarf::DW_AT_declaration); StringRef Name = CTy->getName(); 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 @@ -2051,6 +2051,7 @@ if (const auto &DWARFAddressSpace = N->getDWARFAddressSpace()) Printer.printInt("dwarfAddressSpace", *DWARFAddressSpace, /* ShouldSkipZero */ false); + Printer.printString("annotations", N->getAnnotations()); Out << ")"; } @@ -2084,6 +2085,7 @@ /* ShouldSkipZero */ false); else Printer.printMetadata("rank", N->getRawRank(), /*ShouldSkipNull */ true); + Printer.printString("annotations", N->getAnnotations()); Out << ")"; } @@ -2170,6 +2172,7 @@ Printer.printMetadata("declaration", N->getRawDeclaration()); Printer.printMetadata("retainedNodes", N->getRawRetainedNodes()); Printer.printMetadata("thrownTypes", N->getRawThrownTypes()); + Printer.printString("annotations", N->getAnnotations()); Out << ")"; } @@ -2308,6 +2311,7 @@ Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printInt("align", N->getAlignInBits()); + Printer.printString("annotations", N->getAnnotations()); Out << ")"; } @@ -2324,6 +2328,7 @@ Printer.printMetadata("type", N->getRawType()); Printer.printDIFlags("flags", N->getFlags()); Printer.printInt("align", N->getAlignInBits()); + Printer.printString("annotations", N->getAnnotations()); 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 @@ -704,7 +704,7 @@ auto *GV = DIGlobalVariable::getDistinct( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, IsLocalToUnit, isDefined, cast_or_null(Decl), - TemplateParams, AlignInBits); + TemplateParams, AlignInBits, StringRef()); if (!Expr) Expr = createExpression(); auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr); @@ -721,7 +721,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, + StringRef()) .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 @@ -977,13 +977,15 @@ Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, uint32_t AlignInBits, - StorageType Storage, bool ShouldCreate) { + MDString *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, @@ -991,9 +993,12 @@ Name, LinkageName, StaticDataMemberDeclaration, - TemplateParams}; + TemplateParams, + Annotations}; DEFINE_GETIMPL_STORE(DIGlobalVariable, - (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops); + (Line, IsLocalToUnit, IsDefinition, AlignInBits, + Annotations), + Ops); } DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, 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 @@ -981,7 +981,7 @@ Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, - uint32_t AlignInBits) + uint32_t AlignInBits, MDString *Annotations) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), diff --git a/llvm/test/DebugInfo/annotation-1.ll b/llvm/test/DebugInfo/annotation-1.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/annotation-1.ll @@ -0,0 +1,57 @@ +; REQUIRES: x86_64-linux +; RUN: llc -march=x86 -filetype=asm %s -o - | FileCheck %s + +@s1 = internal global i32 0, align 4, !dbg !0 +@g1 = dso_local global i32 0, align 4, !dbg !6 +@.str = private unnamed_addr constant [8 x i8] c"static1\00", section "llvm.metadata" +@.str.1 = private unnamed_addr constant [8 x i8] c"test3.c\00", section "llvm.metadata" +@.str.2 = private unnamed_addr constant [8 x i8] c"global1\00", section "llvm.metadata" +@.str.3 = private unnamed_addr constant [8 x i8] c"global2\00", section "llvm.metadata" +@llvm.global.annotations = appending global [3 x { i8*, i8*, i8*, i32, i8* }] [{ i8*, i8*, i8*, i32, i8* } { i8* bitcast (i32* @s1 to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 1, i8* null }, { i8*, i8*, i8*, i32, i8* } { i8* bitcast (i32* @g1 to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 2, i8* null }, { i8*, i8*, i8*, i32, i8* } { i8* bitcast (i32* @g1 to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.3, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @.str.1, i32 0, i32 0), i32 2, i8* null }], section "llvm.metadata" + +; Function Attrs: noinline nounwind optnone uwtable +define dso_local i32 @test1() #0 !dbg !16 { +entry: + %0 = load volatile i32, i32* @s1, align 4, !dbg !19 + %1 = load i32, i32* @g1, align 4, !dbg !20 + %add = add nsw i32 %0, %1, !dbg !21 + ret i32 %add, !dbg !22 +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "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" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!10, !11, !12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "s1", scope: !2, file: !3, line: 1, type: !9, isLocal: true, isDefinition: true, annotations: "static1") +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 13.0.0 (https://github.com/llvm/llvm-project.git 829c6b7c4cdcd57972e23d7aca4be65b1bd11eaf)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, splitDebugInlining: false, nameTableKind: None) +!3 = !DIFile(filename: "test3.c", directory: "/tmp/home/yhs/work/tests/llvm/annot") +!4 = !{} +!5 = !{!0, !6} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "g1", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true, annotations: "global1,global2") + +; CHECK: .long .Linfo_string5 # DW_AT_LLVM_annotations +; CHECK: .long .Linfo_string7 # DW_AT_LLVM_annotations +; CHECK: .Linfo_string5: +; CHECK-NEXT: .asciz "static1" +; CHECK: .Linfo_string7: +; CHECK-NEXT: .asciz "global1,global2" + +!8 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!9 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !8) +!10 = !{i32 7, !"Dwarf Version", i32 4} +!11 = !{i32 2, !"Debug Info Version", i32 3} +!12 = !{i32 1, !"wchar_size", i32 4} +!13 = !{i32 7, !"uwtable", i32 1} +!14 = !{i32 7, !"frame-pointer", i32 2} +!15 = !{!"clang version 13.0.0 (https://github.com/llvm/llvm-project.git 829c6b7c4cdcd57972e23d7aca4be65b1bd11eaf)"} +!16 = distinct !DISubprogram(name: "test1", scope: !3, file: !3, line: 3, type: !17, scopeLine: 3, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !4) +!17 = !DISubroutineType(types: !18) +!18 = !{!8} +!19 = !DILocation(line: 4, column: 10, scope: !16) +!20 = !DILocation(line: 4, column: 15, scope: !16) +!21 = !DILocation(line: 4, column: 13, scope: !16) +!22 = !DILocation(line: 4, column: 3, scope: !16)