diff --git a/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c b/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c index 5bbb05e6b8098..e3bfd71a56aad 100644 --- a/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c +++ b/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c @@ -13,7 +13,7 @@ int foo2(struct t1 *arg) { return foo(arg); } -// CHECK: ![[#]] = !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, annotations: ![[ANNOT:[0-9]+]]) +// CHECK: ![[#]] = !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: ![[#]], annotations: ![[ANNOT:[0-9]+]]) // CHECK: ![[ANNOT]] = !{![[TAG1:[0-9]+]], ![[TAG2:[0-9]+]]} // CHECK: ![[TAG1]] = !{!"btf_decl_tag", !"tag1"} // CHECK: ![[TAG2]] = !{!"btf_decl_tag", !"tag2"} diff --git a/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp b/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp index 6453e4379ae9a..a35ca27e10d2a 100644 --- a/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp +++ b/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp @@ -52,15 +52,15 @@ X v; // CHECK: ret void // CHECK: } -// CHECK: ![[DBGVAR16]] = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}) +// CHECK: ![[DBGVAR16]] = distinct !DISubprogram(name: "__cxx_global_var_init", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}}) // CHECK: ![[DBGVAR19]] = !DILocation(line: 14, column: 3, scope: ![[DBGVAR16]]) // CHECK: ![[DBGVAR19b]] = !DILocation(line: 0, scope: ![[DBGVAR16]]) -// CHECK: ![[DBGVAR20]] = distinct !DISubprogram(name: "__dtor_v", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 14, type: !{{[0-9]+}}, scopeLine: 14, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}) +// CHECK: ![[DBGVAR20]] = distinct !DISubprogram(name: "__dtor_v", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 14, type: !{{[0-9]+}}, scopeLine: 14, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}}) // CHECK: ![[DBGVAR21b]] = !DILocation(line: 0, scope: ![[DBGVAR20]]) // CHECK: ![[DBGVAR21]] = !DILocation(line: 14, column: 3, scope: ![[DBGVAR20]]) -// CHECK: ![[DBGVAR22]] = distinct !DISubprogram(linkageName: "__finalize_v", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 14, type: !{{[0-9]+}}, scopeLine: 14, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}) +// CHECK: ![[DBGVAR22]] = distinct !DISubprogram(linkageName: "__finalize_v", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, line: 14, type: !{{[0-9]+}}, scopeLine: 14, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}}) // CHECK: ![[DBGVAR24]] = !DILocation(line: 14, column: 3, scope: ![[DBGVAR22]]) -// CHECK: ![[DBGVAR25]] = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I__", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}) +// CHECK: ![[DBGVAR25]] = distinct !DISubprogram(linkageName: "_GLOBAL__sub_I__", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}}) // CHECK: ![[DBGVAR26]] = !DILocation(line: 0, scope: ![[DBGVAR25]]) -// CHECK: ![[DBGVAR27]] = distinct !DISubprogram(linkageName: "_GLOBAL__D_a", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}) +// CHECK: ![[DBGVAR27]] = distinct !DISubprogram(linkageName: "_GLOBAL__D_a", scope: !{{[0-9]+}}, file: !{{[0-9]+}}, type: !{{[0-9]+}}, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !{{[0-9]+}}, retainedNodes: !{{[0-9]+}}) // CHECK: ![[DBGVAR28]] = !DILocation(line: 0, scope: ![[DBGVAR27]]) diff --git a/clang/test/CodeGenCXX/debug-info-cxx1y.cpp b/clang/test/CodeGenCXX/debug-info-cxx1y.cpp index 42c801ad6530c..6ec55626033d6 100644 --- a/clang/test/CodeGenCXX/debug-info-cxx1y.cpp +++ b/clang/test/CodeGenCXX/debug-info-cxx1y.cpp @@ -11,9 +11,9 @@ // CHECK: [[TYPE_LIST]] = !{[[INT:![0-9]*]]} // CHECK: [[INT]] = !DIBasicType(name: "int" +// CHECK: [[EMPTY:![0-9]*]] = !{} // CHECK: [[FOO:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", -// CHECK-SAME: elements: [[EMPTY:![0-9]*]] -// CHECK: [[EMPTY]] = !{} +// CHECK-SAME: elements: [[EMPTY]] // FIXME: The context of this definition should be the CU/file scope, not the class. // CHECK: !DISubprogram(name: "func", {{.*}} scope: [[FOO]] diff --git a/clang/test/CodeGenCXX/debug-info-template.cpp b/clang/test/CodeGenCXX/debug-info-template.cpp index a5a17c932604c..cf45524769785 100644 --- a/clang/test/CodeGenCXX/debug-info-template.cpp +++ b/clang/test/CodeGenCXX/debug-info-template.cpp @@ -222,7 +222,7 @@ template void f1() { } template void f1(); // CHECK: !DISubprogram(name: "f1", -// CHECK-SAME: templateParams: ![[RAW_FUNC_QUAL_ARGS:[0-9]*]] +// CHECK-SAME: templateParams: ![[RAW_FUNC_QUAL_ARGS:[0-9]*]], // CHECK: ![[RAW_FUNC_QUAL_ARGS]] = !{![[RAW_FUNC_QUAL_T1:[0-9]*]], ![[RAW_FUNC_QUAL_T2:[0-9]*]], ![[RAW_FUNC_QUAL_T3:[0-9]*]], ![[RAW_FUNC_QUAL_T4:[0-9]*]]} // CHECK: ![[RAW_FUNC_QUAL_T1]] = !DITemplateTypeParameter(name: "T1", type: ![[RAW_FUNC_QUAL_VOL:[0-9]*]]) @@ -254,7 +254,7 @@ inline namespace inl { template class> void f1() { } template void f1(); // CHECK: !DISubprogram(name: "f1", -// CHECK-SAME: templateParams: ![[TEMP_TEMP_INL_ARGS:[0-9]*]] +// CHECK-SAME: templateParams: ![[TEMP_TEMP_INL_ARGS:[0-9]*]], // CHECK: ![[TEMP_TEMP_INL_ARGS]] = !{![[TEMP_TEMP_INL_ARGS_T:[0-9]*]]} // CHECK: ![[TEMP_TEMP_INL_ARGS_T]] = !DITemplateValueParameter(tag: DW_TAG_GNU_template_template_param, value: !"TemplateTemplateParamInlineNamespace::inl::t1") } // namespace TemplateTemplateParamInlineNamespace diff --git a/clang/test/CodeGenObjC/debug-info-category.m b/clang/test/CodeGenObjC/debug-info-category.m index 4cd71f25938f9..5ff2365722f39 100644 --- a/clang/test/CodeGenObjC/debug-info-category.m +++ b/clang/test/CodeGenObjC/debug-info-category.m @@ -37,10 +37,10 @@ - (id)add:(Foo *)addend { // CHECK: ![[STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo" // Verify "not a definition" by showing spFlags doesn't have DISPFlagDefinition. -// DWARF5: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit) -// DWARF5: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit) -// DWARF5: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit) -// DWARF5: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit) +// DWARF5: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit, +// DWARF5: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit, +// DWARF5: !DISubprogram(name: "+[Foo(Bar) zero:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit, +// DWARF5: !DISubprogram(name: "-[Foo(Bar) add:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit, // DWARF4-NOT: !DISubprogram(name: "-[Foo integer]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit, // DWARF4-NOT: !DISubprogram(name: "-[Foo integer:]", scope: ![[STRUCT]], {{.*}} spFlags: DISPFlagLocalToUnit, diff --git a/llvm/include/llvm/IR/DIBuilder.h b/llvm/include/llvm/IR/DIBuilder.h index 90ba6a7d1110c..7bcbc78a7fe18 100644 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -64,18 +64,15 @@ namespace llvm { SmallVector UnresolvedNodes; bool AllowUnresolvedNodes; - /// Each subprogram's preserved local variables and labels. + /// Each subprogram's preserved local variables. /// /// Do not use a std::vector. Some versions of libc++ apparently copy /// instead of move on grow operations, and TrackingMDRef is expensive to /// copy. - DenseMap> - SubprogramTrackedNodes; + DenseMap> PreservedVariables; - SmallVectorImpl & - getSubprogramNodesTrackingVector(const DIScope *S) { - return SubprogramTrackedNodes[cast(S)->getSubprogram()]; - } + /// Each subprogram's preserved labels. + DenseMap> PreservedLabels; /// Create a temporary. /// diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index defd1d5c2a1ea..325592421ab9d 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -1856,9 +1856,6 @@ class DISubprogram : public DILocalScope { void replaceRawLinkageName(MDString *LinkageName) { replaceOperandWith(3, LinkageName); } - void replaceRetainedNodes(DINodeArray N) { - replaceOperandWith(7, N.get()); - } /// Check if this subprogram describes the given function. /// diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index 4fa61b87c379f..1428cebfd6dac 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -52,11 +52,23 @@ void DIBuilder::trackIfUnresolved(MDNode *N) { } void DIBuilder::finalizeSubprogram(DISubprogram *SP) { - auto PN = SubprogramTrackedNodes.find(SP); - if (PN != SubprogramTrackedNodes.end()) - SP->replaceRetainedNodes( - MDTuple::get(VMContext, SmallVector(PN->second.begin(), - PN->second.end()))); + MDTuple *Temp = SP->getRetainedNodes().get(); + if (!Temp || !Temp->isTemporary()) + return; + + SmallVector RetainedNodes; + + auto PV = PreservedVariables.find(SP); + if (PV != PreservedVariables.end()) + RetainedNodes.append(PV->second.begin(), PV->second.end()); + + auto PL = PreservedLabels.find(SP); + if (PL != PreservedLabels.end()) + RetainedNodes.append(PL->second.begin(), PL->second.end()); + + DINodeArray Node = getOrCreateArray(RetainedNodes); + + TempMDTuple(Temp)->replaceAllUsesWith(Node.get()); } void DIBuilder::finalize() { @@ -754,20 +766,26 @@ DIGlobalVariable *DIBuilder::createTempGlobalVariableFwdDecl( static DILocalVariable *createLocalVariable( LLVMContext &VMContext, - SmallVectorImpl &PreservedNodes, - DIScope *Context, StringRef Name, unsigned ArgNo, DIFile *File, + DenseMap> &PreservedVariables, + DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File, unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, uint32_t AlignInBits, DINodeArray Annotations = nullptr) { + // FIXME: Why getNonCompileUnitScope()? + // FIXME: Why is "!Context" okay here? // FIXME: Why doesn't this check for a subprogram or lexical block (AFAICT // the only valid scopes)? - auto *Scope = cast(Context); - auto *Node = DILocalVariable::get(VMContext, Scope, Name, File, LineNo, Ty, - ArgNo, Flags, AlignInBits, Annotations); + DIScope *Context = getNonCompileUnitScope(Scope); + + auto *Node = DILocalVariable::get( + VMContext, cast_or_null(Context), Name, File, LineNo, Ty, + ArgNo, Flags, AlignInBits, Annotations); if (AlwaysPreserve) { // The optimizer may remove local variables. If there is an interest // to preserve variable info in such situation then stash it in a // named mdnode. - PreservedNodes.emplace_back(Node); + DISubprogram *Fn = getDISubprogram(Scope); + assert(Fn && "Missing subprogram for local variable"); + PreservedVariables[Fn].emplace_back(Node); } return Node; } @@ -777,11 +795,9 @@ DILocalVariable *DIBuilder::createAutoVariable(DIScope *Scope, StringRef Name, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, uint32_t AlignInBits) { - assert(Scope && isa(Scope) && - "Unexpected scope for a local variable."); - return createLocalVariable( - VMContext, getSubprogramNodesTrackingVector(Scope), Scope, Name, - /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve, Flags, AlignInBits); + return createLocalVariable(VMContext, PreservedVariables, Scope, Name, + /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve, + Flags, AlignInBits); } DILocalVariable *DIBuilder::createParameterVariable( @@ -789,23 +805,25 @@ DILocalVariable *DIBuilder::createParameterVariable( unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, DINodeArray Annotations) { assert(ArgNo && "Expected non-zero argument number for parameter"); - assert(Scope && isa(Scope) && - "Unexpected scope for a local variable."); - return createLocalVariable( - VMContext, getSubprogramNodesTrackingVector(Scope), Scope, Name, ArgNo, - File, LineNo, Ty, AlwaysPreserve, Flags, /*AlignInBits=*/0, Annotations); + return createLocalVariable(VMContext, PreservedVariables, Scope, Name, ArgNo, + File, LineNo, Ty, AlwaysPreserve, Flags, + /*AlignInBits=*/0, Annotations); } -DILabel *DIBuilder::createLabel(DIScope *Context, StringRef Name, DIFile *File, - unsigned LineNo, bool AlwaysPreserve) { - auto *Scope = cast(Context); - auto *Node = DILabel::get(VMContext, Scope, Name, File, LineNo); +DILabel *DIBuilder::createLabel(DIScope *Scope, StringRef Name, DIFile *File, + unsigned LineNo, bool AlwaysPreserve) { + DIScope *Context = getNonCompileUnitScope(Scope); + + auto *Node = DILabel::get(VMContext, cast_or_null(Context), + Name, File, LineNo); if (AlwaysPreserve) { /// The optimizer may remove labels. If there is an interest /// to preserve label info in such situation then append it to /// the list of retained nodes of the DISubprogram. - getSubprogramNodesTrackingVector(Scope).emplace_back(Node); + DISubprogram *Fn = getDISubprogram(Scope); + assert(Fn && "Missing subprogram for label"); + PreservedLabels[Fn].emplace_back(Node); } return Node; } @@ -832,8 +850,9 @@ DISubprogram *DIBuilder::createFunction( auto *Node = getSubprogram( /*IsDistinct=*/IsDefinition, VMContext, getNonCompileUnitScope(Context), Name, LinkageName, File, LineNo, Ty, ScopeLine, nullptr, 0, 0, Flags, - SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, nullptr, - ThrownTypes, Annotations, TargetFuncName); + SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, + MDTuple::getTemporary(VMContext, std::nullopt).release(), ThrownTypes, + Annotations, TargetFuncName); if (IsDefinition) AllSubprograms.push_back(Node);