Index: include/llvm-c/DebugInfo.h =================================================================== --- include/llvm-c/DebugInfo.h +++ include/llvm-c/DebugInfo.h @@ -969,21 +969,15 @@ * \param Expr The location of the global relative to the attached * GlobalVariable. * \param Decl Reference to the corresponding declaration. + * variables. * \param AlignInBits Variable alignment(or 0 if no alignment attr was * specified) */ -LLVMMetadataRef -LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *Linkage, size_t LinkLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMBool LocalToUnit, - LLVMMetadataRef Expr, - LLVMMetadataRef Decl, - uint32_t AlignInBits); +LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits); /** * Create a new temporary \c MDNode. Suitable for use in constructing cyclic * \c MDNode structures. A temporary \c MDNode is not uniqued, may be RAUW'd, @@ -1029,17 +1023,11 @@ * \param AlignInBits Variable alignment(or 0 if no alignment attr was * specified) */ -LLVMMetadataRef -LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *Linkage, size_t LnkLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMBool LocalToUnit, - LLVMMetadataRef Decl, - uint32_t AlignInBits); +LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Decl, uint32_t AlignInBits); /** * Insert a new llvm.dbg.declare intrinsic call before the given instruction. Index: include/llvm/IR/DIBuilder.h =================================================================== --- include/llvm/IR/DIBuilder.h +++ include/llvm/IR/DIBuilder.h @@ -583,14 +583,14 @@ DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DIType *Ty, bool isLocalToUnit, DIExpression *Expr = nullptr, MDNode *Decl = nullptr, - uint32_t AlignInBits = 0); + MDTuple *templateParams = nullptr, uint32_t AlignInBits = 0); /// Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. DIGlobalVariable *createTempGlobalVariableFwdDecl( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *File, unsigned LineNo, DIType *Ty, bool isLocalToUnit, MDNode *Decl = nullptr, - uint32_t AlignInBits = 0); + MDTuple *templateParams = nullptr, uint32_t AlignInBits = 0); /// Create a new descriptor for an auto variable. This is a local variable /// that is not a subprogram parameter. Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -2523,30 +2523,30 @@ IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} ~DIGlobalVariable() = default; - static DIGlobalVariable *getImpl(LLVMContext &Context, DIScope *Scope, - StringRef Name, StringRef LinkageName, - DIFile *File, unsigned Line, DITypeRef Type, - bool IsLocalToUnit, bool IsDefinition, - DIDerivedType *StaticDataMemberDeclaration, - uint32_t AlignInBits, StorageType Storage, - bool ShouldCreate = true) { + static DIGlobalVariable * + getImpl(LLVMContext &Context, DIScope *Scope, StringRef Name, + StringRef LinkageName, DIFile *File, unsigned Line, DITypeRef Type, + bool IsLocalToUnit, bool IsDefinition, + DIDerivedType *StaticDataMemberDeclaration, MDTuple *TemplateParams, + uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - AlignInBits, Storage, ShouldCreate); + cast_or_null(TemplateParams), AlignInBits, 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, uint32_t AlignInBits, - StorageType Storage, bool ShouldCreate = true); + Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, + uint32_t AlignInBits, StorageType Storage, bool ShouldCreate = true); TempDIGlobalVariable cloneImpl() const { return getTemporary(getContext(), getScope(), getName(), getLinkageName(), getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getStaticDataMemberDeclaration(), - getAlignInBits()); + getTemplateParams(), getAlignInBits()); } public: @@ -2555,17 +2555,19 @@ DIFile *File, unsigned Line, DITypeRef Type, bool IsLocalToUnit, bool IsDefinition, DIDerivedType *StaticDataMemberDeclaration, - uint32_t AlignInBits), + MDTuple *TemplateParams, uint32_t AlignInBits), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, StaticDataMemberDeclaration, AlignInBits)) + IsDefinition, StaticDataMemberDeclaration, TemplateParams, + AlignInBits)) DEFINE_MDNODE_GET(DIGlobalVariable, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, - uint32_t AlignInBits), + Metadata *TemplateParams, uint32_t AlignInBits), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, - IsDefinition, StaticDataMemberDeclaration, AlignInBits)) + IsDefinition, StaticDataMemberDeclaration, TemplateParams, + AlignInBits)) TempDIGlobalVariable clone() const { return cloneImpl(); } @@ -2579,6 +2581,8 @@ MDString *getRawLinkageName() const { return getOperandAs(5); } Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(6); } + Metadata *getRawTemplateParams() const { return getOperand(7); } + MDTuple *getTemplateParams() const { return getOperandAs(7); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIGlobalVariableKind; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -4661,7 +4661,8 @@ /// ParseDIGlobalVariable: /// ::= !DIGlobalVariable(scope: !0, name: "foo", linkageName: "foo", /// file: !1, line: 7, type: !2, isLocal: false, -/// isDefinition: true, declaration: !3, align: 8) +/// isDefinition: true, templateParams: !3, +/// declaration: !4, align: 8) bool LLParser::ParseDIGlobalVariable(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(name, MDStringField, (/* AllowEmpty */ false)); \ @@ -4672,15 +4673,17 @@ OPTIONAL(type, MDField, ); \ OPTIONAL(isLocal, MDBoolField, ); \ OPTIONAL(isDefinition, MDBoolField, (true)); \ + OPTIONAL(templateParams, MDField, ); \ OPTIONAL(declaration, MDField, ); \ OPTIONAL(align, MDUnsignedField, (0, UINT32_MAX)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - Result = GET_OR_DISTINCT(DIGlobalVariable, - (Context, scope.Val, name.Val, linkageName.Val, - file.Val, line.Val, type.Val, isLocal.Val, - isDefinition.Val, declaration.Val, align.Val)); + Result = + 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)); return false; } Index: lib/Bitcode/Reader/MetadataLoader.cpp =================================================================== --- lib/Bitcode/Reader/MetadataLoader.cpp +++ lib/Bitcode/Reader/MetadataLoader.cpp @@ -1560,21 +1560,35 @@ break; } case bitc::METADATA_GLOBAL_VAR: { - if (Record.size() < 11 || Record.size() > 12) + if (Record.size() < 11 || Record.size() > 13) return error("Invalid record"); IsDistinct = Record[0] & 1; unsigned Version = Record[0] >> 1; - if (Version == 1) { + if (Version == 2) { + 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])), + NextMetadataNo); + + NextMetadataNo++; + } else if (Version == 1) { + // No upgrade necessary. A null field will be introduced to indicate + // that no parameter information is available. 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[10]), Record[11])), + getMDOrNull(Record[10]), nullptr, Record[11])), NextMetadataNo); + NextMetadataNo++; } else if (Version == 0) { // Upgrade old metadata, which stored a global variable reference or a @@ -1605,7 +1619,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]), AlignInBits)); + getMDOrNull(Record[10]), nullptr, AlignInBits)); DIGlobalVariableExpression *DGVE = nullptr; if (Attach || Expr) Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1743,7 +1743,7 @@ void ModuleBitcodeWriter::writeDIGlobalVariable( const DIGlobalVariable *N, SmallVectorImpl &Record, unsigned Abbrev) { - const uint64_t Version = 1 << 1; + const uint64_t Version = 2 << 1; Record.push_back((uint64_t)N->isDistinct() | Version); Record.push_back(VE.getMetadataOrNullID(N->getScope())); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); @@ -1753,8 +1753,8 @@ Record.push_back(VE.getMetadataOrNullID(N->getType())); Record.push_back(N->isLocalToUnit()); Record.push_back(N->isDefinition()); - Record.push_back(/* expr */ 0); Record.push_back(VE.getMetadataOrNullID(N->getStaticDataMemberDeclaration())); + Record.push_back(VE.getMetadataOrNullID(N->getTemplateParams())); Record.push_back(N->getAlignInBits()); Stream.EmitRecord(bitc::METADATA_GLOBAL_VAR, Record, Abbrev); Index: lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp =================================================================== --- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -160,6 +160,9 @@ addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata, AlignInBytes); + if (MDTuple *TP = GV->getTemplateParams()) + addTemplateParams(*VariableDIE, DINodeArray(TP)); + // Add location. bool addToAccelTable = false; DIELoc *Loc = nullptr; Index: lib/IR/AsmWriter.cpp =================================================================== --- lib/IR/AsmWriter.cpp +++ lib/IR/AsmWriter.cpp @@ -2051,6 +2051,7 @@ Printer.printBool("isLocal", N->isLocalToUnit()); Printer.printBool("isDefinition", N->isDefinition()); Printer.printMetadata("declaration", N->getRawStaticDataMemberDeclaration()); + Printer.printMetadata("templateParams", N->getRawTemplateParams()); Printer.printInt("align", N->getAlignInBits()); Out << ")"; } Index: lib/IR/DIBuilder.cpp =================================================================== --- lib/IR/DIBuilder.cpp +++ lib/IR/DIBuilder.cpp @@ -639,13 +639,13 @@ DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, unsigned LineNumber, DIType *Ty, bool isLocalToUnit, DIExpression *Expr, - MDNode *Decl, uint32_t AlignInBits) { + MDNode *Decl, MDTuple *templateParams, uint32_t AlignInBits) { checkGlobalVariableScope(Context); auto *GV = DIGlobalVariable::getDistinct( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, true, cast_or_null(Decl), - AlignInBits); + templateParams, AlignInBits); if (!Expr) Expr = createExpression(); auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr); @@ -656,13 +656,13 @@ DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( DIScope *Context, StringRef Name, StringRef LinkageName, DIFile *F, unsigned LineNumber, DIType *Ty, bool isLocalToUnit, MDNode *Decl, - uint32_t AlignInBits) { + MDTuple *templateParams, uint32_t AlignInBits) { checkGlobalVariableScope(Context); return DIGlobalVariable::getTemporary( VMContext, cast_or_null(Context), Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, false, - cast_or_null(Decl), AlignInBits) + cast_or_null(Decl), templateParams, AlignInBits) .release(); } Index: lib/IR/DebugInfo.cpp =================================================================== --- lib/IR/DebugInfo.cpp +++ lib/IR/DebugInfo.cpp @@ -1220,23 +1220,16 @@ return wrap(unwrap(Builder)->createConstantValueExpression(Value)); } -LLVMMetadataRef -LLVMDIBuilderCreateGlobalVariableExpression(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *Linkage, size_t LinkLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMBool LocalToUnit, - LLVMMetadataRef Expr, - LLVMMetadataRef Decl, - uint32_t AlignInBits) { +LLVMMetadataRef LLVMDIBuilderCreateGlobalVariableExpression( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LinkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Expr, LLVMMetadataRef Decl, uint32_t AlignInBits) { return wrap(unwrap(Builder)->createGlobalVariableExpression( - unwrapDI(Scope), {Name, NameLen}, {Linkage, LinkLen}, - unwrapDI(File), LineNo, unwrapDI(Ty), - LocalToUnit, unwrap(Expr), - unwrapDI(Decl), AlignInBits)); + unwrapDI(Scope), {Name, NameLen}, {Linkage, LinkLen}, + unwrapDI(File), LineNo, unwrapDI(Ty), LocalToUnit, + unwrap(Expr), unwrapDI(Decl), + nullptr, AlignInBits)); } LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef Ctx, LLVMMetadataRef *Data, @@ -1256,26 +1249,21 @@ MDNode::deleteTemporary(Node); } -LLVMMetadataRef -LLVMDIBuilderCreateTempGlobalVariableFwdDecl(LLVMDIBuilderRef Builder, - LLVMMetadataRef Scope, - const char *Name, size_t NameLen, - const char *Linkage, size_t LnkLen, - LLVMMetadataRef File, - unsigned LineNo, - LLVMMetadataRef Ty, - LLVMBool LocalToUnit, - LLVMMetadataRef Decl, - uint32_t AlignInBits) { +LLVMMetadataRef LLVMDIBuilderCreateTempGlobalVariableFwdDecl( + LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + size_t NameLen, const char *Linkage, size_t LnkLen, LLVMMetadataRef File, + unsigned LineNo, LLVMMetadataRef Ty, LLVMBool LocalToUnit, + LLVMMetadataRef Decl, uint32_t AlignInBits) { return wrap(unwrap(Builder)->createTempGlobalVariableFwdDecl( - unwrapDI(Scope), {Name, NameLen}, {Linkage, LnkLen}, - unwrapDI(File), LineNo, unwrapDI(Ty), - LocalToUnit, unwrapDI(Decl), AlignInBits)); + unwrapDI(Scope), {Name, NameLen}, {Linkage, LnkLen}, + unwrapDI(File), LineNo, unwrapDI(Ty), LocalToUnit, + unwrapDI(Decl), nullptr, AlignInBits)); } -LLVMValueRef LLVMDIBuilderInsertDeclareBefore( - LLVMDIBuilderRef Builder, LLVMValueRef Storage, LLVMMetadataRef VarInfo, - LLVMMetadataRef Expr, LLVMMetadataRef DL, LLVMValueRef Instr) { +LLVMValueRef +LLVMDIBuilderInsertDeclareBefore(LLVMDIBuilderRef Builder, LLVMValueRef Storage, + LLVMMetadataRef VarInfo, LLVMMetadataRef Expr, + LLVMMetadataRef DL, LLVMValueRef Instr) { return wrap(unwrap(Builder)->insertDeclare( unwrap(Storage), unwrap(VarInfo), unwrap(Expr), unwrap(DL), Index: lib/IR/DebugInfoMetadata.cpp =================================================================== --- lib/IR/DebugInfoMetadata.cpp +++ lib/IR/DebugInfoMetadata.cpp @@ -650,19 +650,24 @@ MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, Metadata *StaticDataMemberDeclaration, - uint32_t AlignInBits, StorageType Storage, - bool ShouldCreate) { + Metadata *TemplateParams, uint32_t AlignInBits, + 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, AlignInBits)); - Metadata *Ops[] = { - Scope, Name, File, Type, Name, LinkageName, StaticDataMemberDeclaration}; + DEFINE_GETIMPL_LOOKUP(DIGlobalVariable, (Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, + StaticDataMemberDeclaration, + TemplateParams, AlignInBits)); + Metadata *Ops[] = {Scope, + Name, + File, + Type, + Name, + LinkageName, + StaticDataMemberDeclaration, + TemplateParams}; DEFINE_GETIMPL_STORE(DIGlobalVariable, - (Line, IsLocalToUnit, IsDefinition, AlignInBits), - Ops); + (Line, IsLocalToUnit, IsDefinition, AlignInBits), Ops); } DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope, Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -867,23 +867,26 @@ bool IsLocalToUnit; bool IsDefinition; Metadata *StaticDataMemberDeclaration; + Metadata *TemplateParams; uint32_t AlignInBits; MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName, Metadata *File, unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, - Metadata *StaticDataMemberDeclaration, uint32_t AlignInBits) + Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams, + uint32_t AlignInBits) : Scope(Scope), Name(Name), LinkageName(LinkageName), File(File), Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), StaticDataMemberDeclaration(StaticDataMemberDeclaration), - AlignInBits(AlignInBits) {} + TemplateParams(TemplateParams), AlignInBits(AlignInBits) {} MDNodeKeyImpl(const DIGlobalVariable *N) : Scope(N->getRawScope()), Name(N->getRawName()), LinkageName(N->getRawLinkageName()), File(N->getRawFile()), Line(N->getLine()), Type(N->getRawType()), IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()), StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()), + TemplateParams(N->getRawTemplateParams()), AlignInBits(N->getAlignInBits()) {} bool isKeyOf(const DIGlobalVariable *RHS) const { @@ -894,6 +897,7 @@ IsDefinition == RHS->isDefinition() && StaticDataMemberDeclaration == RHS->getRawStaticDataMemberDeclaration() && + TemplateParams == RHS->getRawTemplateParams() && AlignInBits == RHS->getAlignInBits(); } Index: test/Assembler/diglobalvariable.ll =================================================================== --- test/Assembler/diglobalvariable.ll +++ test/Assembler/diglobalvariable.ll @@ -3,8 +3,8 @@ @foo = global i32 0 -; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8} -!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8} +; CHECK: !named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12} +!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12} !0 = !DIFile(filename: "scope.h", directory: "/path/to/dir") !1 = distinct !{} @@ -23,3 +23,8 @@ ; CHECK: !8 = !DIGlobalVariable(name: "mem", scope: !0, type: !9, isLocal: false, isDefinition: true, declaration: !7) !8 = !DIGlobalVariable(name: "mem", scope: !0, declaration: !7, type: !9) !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) + +; CHECK: !12 = !DIGlobalVariable(name: "bar", linkageName: "bar", scope: !0, file: !2, line: 8, type: !3, isLocal: true, isDefinition: false, templateParams: !11, align: 32) +!10 = !DITemplateTypeParameter(name: "Ty", type: !3) +!11 = distinct !{!10} +!12 = !DIGlobalVariable(name: "bar", linkageName: "bar", scope: !0, file: !2, line: 8, type: !3, isLocal: true, isDefinition: false, templateParams: !11, align: 32) Index: test/DebugInfo/X86/template.ll =================================================================== --- test/DebugInfo/X86/template.ll +++ test/DebugInfo/X86/template.ll @@ -3,7 +3,10 @@ ; RUN: llc -mtriple=x86_64-linux -O0 -filetype=obj < %s | llvm-dwarfdump -v -debug-info - | FileCheck %s ; IR generated with `clang++ -g -emit-llvm -S` from the following code: -; template class y, decltype(nullptr) n, int ...z> int func() { return 3; } +; template class y, decltype(nullptr) n, int ...z> int func() { +; var = 5; +; return var; +; } ; template struct y_impl { struct nested { }; }; ; int glbl = func<3, &glbl, y_impl, nullptr, 1, 2>(); ; y_impl::nested n; @@ -12,9 +15,17 @@ ; CHECK-NEXT: DW_AT_name{{.*}} = "int" ; CHECK: DW_TAG_structure_type -; CHECK-NEXT: DW_AT_name{{.*}}"y_impl" +; CHECK: DW_AT_name{{.*}}"y_impl" +; CHECK-NOT: {{TAG|NULL}} +; CHECK: DW_TAG_template_type_parameter + +; CHECK: DW_TAG_variable +; CHECK-NEXT: DW_AT_name{{.*}}"var" ; CHECK-NOT: NULL ; CHECK: DW_TAG_template_type_parameter +; CHECK-NEXT: DW_AT_type{{.*}}=> {[[INT]]} +; CHECK-NEXT: DW_AT_name{{.*}}= "T" + ; CHECK: DW_AT_name{{.*}}"func<3, &glbl, y_impl, nullptr, 1, 2>" ; CHECK-NOT: NULL @@ -59,75 +70,84 @@ ; CHECK-NEXT: DW_AT_name{{.*}}= "decltype(nullptr)" source_filename = "test/DebugInfo/X86/template.ll" - %"struct.y_impl::nested" = type { i8 } -@glbl = global i32 0, align 4, !dbg !0 -@n = global %"struct.y_impl::nested" zeroinitializer, align 1, !dbg !4 -@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_template.cpp, i8* null }] +@glbl = dso_local global i32 0, align 4, !dbg !0 +@_Z3varIiE = linkonce_odr dso_local global i32 0, align 4, !dbg !13 +@n = dso_local global %"struct.y_impl::nested" zeroinitializer, align 1, !dbg !6 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_upstream_test.cpp, i8* null }] -define internal void @__cxx_global_var_init() section ".text.startup" !dbg !17 { +; Function Attrs: noinline uwtable +define internal void @__cxx_global_var_init() #0 section ".text.startup" !dbg !21 { entry: - %call = call i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv(), !dbg !20 - store i32 %call, i32* @glbl, align 4, !dbg !20 - ret void, !dbg !20 + %call = call i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv(), !dbg !24 + store i32 %call, i32* @glbl, align 4, !dbg !24 + ret void, !dbg !24 } -; Function Attrs: nounwind uwtable -define linkonce_odr i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv() #0 !dbg !21 { +; Function Attrs: noinline nounwind optnone uwtable +define linkonce_odr dso_local i32 @_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv() #1 !dbg !25 { entry: - ret i32 3, !dbg !35 + store i32 5, i32* @_Z3varIiE, align 4, !dbg !39 + %0 = load i32, i32* @_Z3varIiE, align 4, !dbg !40 + ret i32 %0, !dbg !41 } -define internal void @_GLOBAL__sub_I_template.cpp() section ".text.startup" { +; Function Attrs: noinline uwtable +define internal void @_GLOBAL__sub_I_upstream_test.cpp() #0 section ".text.startup" !dbg !42 { entry: - call void @__cxx_global_var_init(), !dbg !36 + call void @__cxx_global_var_init(), !dbg !44 ret void } -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #0 = { nounwind uwtable } +attributes #1 = { nounwind uwtable noinline optnone } -!llvm.dbg.cu = !{!11} -!llvm.module.flags = !{!14, !15} -!llvm.ident = !{!16} +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!17, !18, !19} +!llvm.ident = !{!20} !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) -!1 = !DIGlobalVariable(name: "glbl", scope: null, file: !2, line: 3, type: !3, isLocal: false, isDefinition: true) -!2 = !DIFile(filename: "template.cpp", directory: "/tmp/dbginfo") -!3 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) -!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) -!5 = !DIGlobalVariable(name: "n", scope: null, file: !2, line: 4, type: !6, isLocal: false, isDefinition: true) -!6 = !DICompositeType(tag: DW_TAG_structure_type, name: "nested", scope: !7, file: !2, line: 2, size: 8, align: 8, elements: !8, identifier: "_ZTSN6y_implIiE6nestedE") -!7 = !DICompositeType(tag: DW_TAG_structure_type, name: "y_impl", file: !2, line: 2, size: 8, align: 8, elements: !8, templateParams: !9, identifier: "_ZTS6y_implIiE") -!8 = !{} -!9 = !{!10} -!10 = !DITemplateTypeParameter(type: !3) -!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "clang version 3.6.0 (trunk 224394) (llvm/trunk 224384)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, retainedTypes: !12, globals: !13, imports: !8) -!12 = !{!7, !6} -!13 = !{!0, !4} -!14 = !{i32 2, !"Dwarf Version", i32 4} -!15 = !{i32 2, !"Debug Info Version", i32 3} -!16 = !{!"clang version 3.6.0 (trunk 224394) (llvm/trunk 224384)"} -!17 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !2, file: !2, line: 3, type: !18, isLocal: true, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !11, retainedNodes: !8) -!18 = !DISubroutineType(types: !19) -!19 = !{null} -!20 = !DILocation(line: 3, column: 12, scope: !17) -!21 = distinct !DISubprogram(name: "func<3, &glbl, y_impl, nullptr, 1, 2>", linkageName: "_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv", scope: !2, file: !2, line: 1, type: !22, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: false, unit: !11, templateParams: !24, retainedNodes: !8) +!1 = distinct !DIGlobalVariable(name: "glbl", scope: !2, file: !3, line: 7, type: !12, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) +!3 = !DIFile(filename: "upstream_test.cpp", directory: "/home/mvoss/src/92562") +!4 = !{} +!5 = !{!0, !6, !13} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "n", scope: !2, file: !3, line: 8, type: !8, isLocal: false, isDefinition: true)!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "nested", scope: !9, file: !3, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !4, identifier: "_ZTSN6y_implIiE6nestedE") +!9 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y_impl", file: !3, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !4, templateParams: !10, identifier: "_ZTS6y_implIiE") +!10 = !{!11} +!11 = !DITemplateTypeParameter(type: !12) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression()) +!14 = distinct !DIGlobalVariable(name: "var", linkageName: "_Z3varIiE", scope: !2, file: !3, line: 1, type: !12, isLocal: false, isDefinition: true, templateParams: !15) +!15 = !{!16} +!16 = !DITemplateTypeParameter(name: "T", type: !12) +!17 = !{i32 2, !"Dwarf Version", i32 4} +!18 = !{i32 2, !"Debug Info Version", i32 3} +!19 = !{i32 1, !"wchar_size", i32 4} +!20 = !{!"clang version 7.0.0 "} +!21 = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !3, file: !3, line: 7, type: !22, isLocal: true, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !2, retainedNodes: !4) !22 = !DISubroutineType(types: !23) -!23 = !{!3} -!24 = !{!25, !26, !28, !29, !31} -!25 = !DITemplateValueParameter(name: "x", type: !3, value: i32 3) -!26 = !DITemplateValueParameter(type: !27, value: i32* @glbl) -!27 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, align: 64) -!28 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "y", value: !"y_impl") -!29 = !DITemplateValueParameter(name: "n", type: !30, value: i8 0) -!30 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") -!31 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "z", value: !32) -!32 = !{!33, !34} -!33 = !DITemplateValueParameter(type: !3, value: i32 1) -!34 = !DITemplateValueParameter(type: !3, value: i32 2) -!35 = !DILocation(line: 1, column: 96, scope: !21) -!36 = !DILocation(line: 0, scope: !37) -!37 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_template.cpp", scope: !2, file: !2, type: !38, isLocal: true, isDefinition: true, flags: DIFlagArtificial, isOptimized: false, unit: !11, retainedNodes: !8) -!38 = !DISubroutineType(types: !8) - +!23 = !{null} +!24 = !DILocation(line: 7, column: 12, scope: !21) +!25 = distinct !DISubprogram(name: "func<3, &glbl, y_impl, nullptr, 1, 2>", linkageName: "_Z4funcILi3EXadL_Z4glblEE6y_implLDn0EJLi1ELi2EEEiv", scope: !3, file: !3, line: 2, type: !26, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !2, templateParams: !28, retainedNodes: !4) +!26 = !DISubroutineType(types: !27) +!27 = !{!12} +!28 = !{!29, !30, !32, !33, !35} +!29 = !DITemplateValueParameter(name: "x", type: !12, value: i32 3) +!30 = !DITemplateValueParameter(type: !31, value: i32* @glbl) +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!32 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, name: "y", value: !"y_impl") +!33 = !DITemplateValueParameter(name: "n", type: !34, value: i8 0) +!34 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") +!35 = !DITemplateValueParameter(tag: DW_TAG_GNU_template_parameter_pack, name: "z", value: !36) +!36 = !{!37, !38} +!37 = !DITemplateValueParameter(type: !12, value: i32 1) +!38 = !DITemplateValueParameter(type: !12, value: i32 2) +!39 = !DILocation(line: 3, column: 12, scope: !25) +!40 = !DILocation(line: 4, column: 10, scope: !25) +!41 = !DILocation(line: 4, column: 3, scope: !25) +!42 = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I_upstream_test.cpp", scope: !3, file: !3, type: !43, isLocal: true, isDefinition: true, flags: DIFlagArtificial, isOptimized: false, unit: !2, retainedNodes: !4) +!43 = !DISubroutineType(types: !4) +!44 = !DILocation(line: 0, scope: !42) Index: tools/llvm-c-test/debuginfo.c =================================================================== --- tools/llvm-c-test/debuginfo.c +++ tools/llvm-c-test/debuginfo.c @@ -61,26 +61,24 @@ LLVMMetadataRef ClassTy = declare_objc_class(DIB, File); LLVMMetadataRef GlobalClassValueExpr = - LLVMDIBuilderCreateConstantValueExpression(DIB, 0); - LLVMDIBuilderCreateGlobalVariableExpression(DIB, Module, "globalClass", 11, - "", 0, File, 1, ClassTy, - true, GlobalClassValueExpr, - NULL, 0); + LLVMDIBuilderCreateConstantValueExpression(DIB, 0); + LLVMDIBuilderCreateGlobalVariableExpression( + DIB, Module, "globalClass", 11, "", 0, File, 1, ClassTy, true, + GlobalClassValueExpr, NULL, 0); LLVMMetadataRef Int64Ty = - LLVMDIBuilderCreateBasicType(DIB, "Int64", 5, 64, 0, LLVMDIFlagZero); + LLVMDIBuilderCreateBasicType(DIB, "Int64", 5, 64, 0, LLVMDIFlagZero); LLVMMetadataRef Int64TypeDef = LLVMDIBuilderCreateTypedef(DIB, Int64Ty, "int64_t", 7, File, 42, File); LLVMMetadataRef GlobalVarValueExpr = - LLVMDIBuilderCreateConstantValueExpression(DIB, 0); - LLVMDIBuilderCreateGlobalVariableExpression(DIB, Module, "global", 6, - "", 0, File, 1, Int64TypeDef, - true, GlobalVarValueExpr, - NULL, 0); + LLVMDIBuilderCreateConstantValueExpression(DIB, 0); + LLVMDIBuilderCreateGlobalVariableExpression( + DIB, Module, "global", 6, "", 0, File, 1, Int64TypeDef, true, + GlobalVarValueExpr, NULL, 0); LLVMMetadataRef NameSpace = - LLVMDIBuilderCreateNameSpace(DIB, Module, "NameSpace", 9, false); + LLVMDIBuilderCreateNameSpace(DIB, Module, "NameSpace", 9, false); LLVMMetadataRef StructDbgElts[] = {Int64Ty, Int64Ty, Int64Ty}; LLVMMetadataRef StructDbgTy = Index: unittests/IR/MetadataTest.cpp =================================================================== --- unittests/IR/MetadataTest.cpp +++ unittests/IR/MetadataTest.cpp @@ -2014,13 +2014,16 @@ DIType *Type = getDerivedType(); bool IsLocalToUnit = false; bool IsDefinition = true; + MDTuple *templateParams = getTuple(); DIDerivedType *StaticDataMemberDeclaration = cast(getDerivedType()); + uint32_t AlignInBits = 8; - auto *N = DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, - Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits); + auto *N = DIGlobalVariable::get( + Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits); + EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag()); EXPECT_EQ(Scope, N->getScope()); EXPECT_EQ(Name, N->getName()); @@ -2031,47 +2034,57 @@ EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit()); EXPECT_EQ(IsDefinition, N->isDefinition()); EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration()); + EXPECT_EQ(templateParams, N->getTemplateParams()); EXPECT_EQ(AlignInBits, N->getAlignInBits()); EXPECT_EQ(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); + StaticDataMemberDeclaration, + templateParams, AlignInBits)); - EXPECT_NE(N, - DIGlobalVariable::get(Context, getSubprogram(), Name, LinkageName, - File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); + EXPECT_NE(N, DIGlobalVariable::get( + Context, getSubprogram(), Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, + StaticDataMemberDeclaration, templateParams, AlignInBits)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); + StaticDataMemberDeclaration, + templateParams, AlignInBits)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, "other", File, Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); - EXPECT_NE(N, - DIGlobalVariable::get(Context, Scope, Name, LinkageName, getFile(), - Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); - EXPECT_NE(N, - DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, - Line + 1, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); - EXPECT_NE(N, - DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, - getDerivedType(), IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); + StaticDataMemberDeclaration, + templateParams, AlignInBits)); + EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, + getFile(), Line, Type, IsLocalToUnit, + IsDefinition, StaticDataMemberDeclaration, + templateParams, AlignInBits)); + EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line + 1, Type, IsLocalToUnit, + IsDefinition, StaticDataMemberDeclaration, + templateParams, AlignInBits)); + EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, getDerivedType(), IsLocalToUnit, + IsDefinition, StaticDataMemberDeclaration, + templateParams, AlignInBits)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, !IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); + StaticDataMemberDeclaration, + templateParams, AlignInBits)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, !IsDefinition, - StaticDataMemberDeclaration, AlignInBits)); + StaticDataMemberDeclaration, + templateParams, AlignInBits)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, cast(getDerivedType()), + templateParams, AlignInBits)); + EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + StaticDataMemberDeclaration, nullptr, AlignInBits)); EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, StaticDataMemberDeclaration, - (AlignInBits << 1))); + templateParams, (AlignInBits << 1))); TempDIGlobalVariable Temp = N->clone(); EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); @@ -2088,18 +2101,19 @@ DIType *Type = getDerivedType(); bool IsLocalToUnit = false; bool IsDefinition = true; + MDTuple *templateParams = getTuple(); auto *Expr = DIExpression::get(Context, {1, 2}); auto *Expr2 = DIExpression::get(Context, {1, 2, 3}); DIDerivedType *StaticDataMemberDeclaration = cast(getDerivedType()); uint32_t AlignInBits = 8; - auto *Var = DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, - Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits); - auto *Var2 = DIGlobalVariable::get(Context, Scope, "other", LinkageName, File, - Line, Type, IsLocalToUnit, IsDefinition, - StaticDataMemberDeclaration, AlignInBits); + auto *Var = DIGlobalVariable::get( + Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits); + auto *Var2 = DIGlobalVariable::get( + Context, Scope, "other", LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, StaticDataMemberDeclaration, templateParams, AlignInBits); auto *N = DIGlobalVariableExpression::get(Context, Var, Expr); EXPECT_EQ(Var, N->getVariable());