diff --git a/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c b/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c --- a/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c +++ b/clang/test/CodeGen/attr-btf_tag-disubprogram-callsite.c @@ -13,7 +13,7 @@ return foo(arg); } -// CHECK: ![[#]] = !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: ![[#]], annotations: ![[ANNOT:[0-9]+]]) +// CHECK: ![[#]] = !DISubprogram(name: "foo", scope: ![[#]], file: ![[#]], line: [[#]], type: ![[#]], flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, 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/CodeGen/debug-info-codeview-unnamed.c b/clang/test/CodeGen/debug-info-codeview-unnamed.c --- a/clang/test/CodeGen/debug-info-codeview-unnamed.c +++ b/clang/test/CodeGen/debug-info-codeview-unnamed.c @@ -8,23 +8,23 @@ // struct { int bar; } one = {42}; // - // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" - // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( + // LINUX: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType( // LINUX-SAME: tag: DW_TAG_structure_type // LINUX-NOT: name: // LINUX-NOT: identifier: // LINUX-SAME: ) + // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" + // LINUX-SAME: type: [[TYPE_OF_ONE]] + // LINUX-SAME: ) // - // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" - // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType + // MSVC: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType // MSVC-SAME: tag: DW_TAG_structure_type // MSVC-NOT: name: // MSVC-NOT: identifier: // MSVC-SAME: ) + // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" + // MSVC-SAME: type: [[TYPE_OF_ONE]] + // MSVC-SAME: ) return 0; } diff --git a/clang/test/CodeGen/debug-info-unused-types.c b/clang/test/CodeGen/debug-info-unused-types.c --- a/clang/test/CodeGen/debug-info-unused-types.c +++ b/clang/test/CodeGen/debug-info-unused-types.c @@ -18,13 +18,13 @@ // CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]] // CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar" // CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAR" -// CHECK: [[TYPE2:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" -// CHECK: [[TYPE3:![0-9]+]] = !DIEnumerator(name: "Z" -// CHECK: [[RETTYPES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]], [[TYPE0]], [[TYPE6:![0-9]+]], {{![0-9]+}}, [[TYPE7:![0-9]+]], [[TYPE2]], [[TYPE8:![0-9]+]]} -// CHECK: [[TYPE4]] = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int" -// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" -// CHECK: [[TYPE6]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz" -// CHECK: [[TYPE7]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y" +// CHECK: [[RETTYPES]] = !{[[TYPE2:![0-9]+]], [[TYPE3:![0-9]+]], [[TYPE0]], [[TYPE4:![0-9]+]], {{![0-9]+}}, [[TYPE5:![0-9]+]], [[TYPE6:![0-9]+]], [[TYPE8:![0-9]+]]} +// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int" +// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo" +// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz" +// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y" +// CHECK: [[TYPE6]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" +// CHECK: [[TYPE7:![0-9]+]] = !DIEnumerator(name: "Z" // CHECK: [[TYPE8]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "w" // Check that debug info is not emitted for the typedef, struct, enum, and diff --git a/clang/test/CodeGen/debug-info-unused-types.cpp b/clang/test/CodeGen/debug-info-unused-types.cpp --- a/clang/test/CodeGen/debug-info-unused-types.cpp +++ b/clang/test/CodeGen/debug-info-unused-types.cpp @@ -13,12 +13,12 @@ // CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]] // CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz" // CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAZ" -// CHECK: [[TYPE2:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" -// CHECK: [[TYPE3:![0-9]+]] = !DIEnumerator(name: "Z" -// CHECK: [[RETTYPES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]], [[TYPE0]], {{![0-9]+}}, [[TYPE6:![0-9]+]], [[TYPE2]]} -// CHECK: [[TYPE4]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo" -// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar" -// CHECK: [[TYPE6]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y" +// CHECK: [[RETTYPES]] = !{[[TYPE2:![0-9]+]], [[TYPE3:![0-9]+]], [[TYPE0]], {{![0-9]+}}, [[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]]} +// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo" +// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar" +// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y" +// CHECK: [[TYPE5]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z" +// CHECK: [[TYPE6:![0-9]+]] = !DIEnumerator(name: "Z" // NODBG-NOT: !DI{{CompositeType|Enumerator|DerivedType}} diff --git a/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp b/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp --- a/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp +++ b/clang/test/CodeGenCXX/aix-static-init-debug-info.cpp @@ -52,15 +52,15 @@ // 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]+}}, retainedNodes: !{{[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]+}}) // 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]+}}, retainedNodes: !{{[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]+}}) // 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]+}}, retainedNodes: !{{[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]+}}) // 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]+}}, retainedNodes: !{{[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]+}}) // 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]+}}, retainedNodes: !{{[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]+}}) // CHECK: ![[DBGVAR28]] = !DILocation(line: 0, scope: ![[DBGVAR27]]) diff --git a/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp --- a/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp +++ b/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -51,13 +51,13 @@ // CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true // CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true // CHECK: !DIGlobalVariable(name: "value", {{.*}} isLocal: false, isDefinition: true -// CHECK: !DILocalVariable(name: "i", {{.*}}, flags: DIFlagArtificial -// CHECK: !DILocalVariable(name: "c", {{.*}}, flags: DIFlagArtificial -// CHECK: !DILocalVariable( -// CHECK-NOT: name: -// CHECK: type: ![[UNION:[0-9]+]] -// CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[UNION:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-NOT: name: // CHECK: elements // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i", scope: ![[UNION]], // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "c", scope: ![[UNION]], +// CHECK: !DILocalVariable(name: "i", {{.*}}, flags: DIFlagArtificial +// CHECK: !DILocalVariable(name: "c", {{.*}}, flags: DIFlagArtificial +// CHECK: !DILocalVariable( +// CHECK-NOT: name: +// CHECK: type: ![[UNION]] diff --git a/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp b/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp --- a/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp +++ b/clang/test/CodeGenCXX/debug-info-codeview-unnamed.cpp @@ -3,6 +3,60 @@ int main(int argc, char* argv[], char* arge[]) { // + // LINUX: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?1??main@@9@" + // MSVC-SAME: ) + + + // + // LINUX: [[TYPE_OF_TWO:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_TWO:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AU@?2??main@@9@" + // MSVC-SAME: ) + + + // + // LINUX: [[TYPE_OF_THREE:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_structure_type + // LINUX-SAME: name: "named" + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_THREE:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_structure_type + // MSVC-SAME: name: "named" + // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@" + // MSVC-SAME: ) + + // + // LINUX: [[TYPE_OF_FOUR:![0-9]+]] = distinct !DICompositeType( + // LINUX-SAME: tag: DW_TAG_class_type + // LINUX-NOT: name: + // LINUX-NOT: identifier: + // LINUX-SAME: ) + // + // MSVC: [[TYPE_OF_FOUR:![0-9]+]] = distinct !DICompositeType + // MSVC-SAME: tag: DW_TAG_class_type + // MSVC-SAME: name: "" + // MSVC-SAME: identifier: ".?AV@?0??main@@9@" + // MSVC-SAME: ) + + // In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward // reference of the unnamed struct. Visual Studio requires a unique // identifier to match the LF_STRUCTURE forward reference to the definition. @@ -10,21 +64,11 @@ struct { void bar() {} } one; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one" - // LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_structure_type - // LINUX-NOT: name: - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_ONE]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one" - // MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_ONE]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_structure_type - // MSVC-SAME: name: "" - // MSVC-SAME: identifier: ".?AU@?1??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_ONE]] // MSVC-SAME: ) @@ -36,21 +80,11 @@ int decltype(two)::*ptr2unnamed = &decltype(two)::bar; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two" - // LINUX-SAME: type: [[TYPE_OF_TWO:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_TWO]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_structure_type - // LINUX-NOT: name: - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_TWO]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two" - // MSVC-SAME: type: [[TYPE_OF_TWO:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_TWO]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_structure_type - // MSVC-SAME: name: "" - // MSVC-SAME: identifier: ".?AU@?2??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_TWO]] // MSVC-SAME: ) @@ -61,21 +95,11 @@ struct named { int bar; int named::* p2mem; } three = { 42, &named::bar }; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three" - // LINUX-SAME: type: [[TYPE_OF_THREE:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_THREE]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_structure_type - // LINUX-SAME: name: "named" - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_THREE]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three" - // MSVC-SAME: type: [[TYPE_OF_THREE:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_THREE]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_structure_type - // MSVC-SAME: name: "named" - // MSVC-SAME: identifier: ".?AUnamed@?1??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_THREE]] // MSVC-SAME: ) @@ -87,21 +111,11 @@ auto four = [argc](int i) -> int { return argc == i ? 1 : 0; }; // // LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four" - // LINUX-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] - // LINUX-SAME: ) - // LINUX: [[TYPE_OF_FOUR]] = distinct !DICompositeType( - // LINUX-SAME: tag: DW_TAG_class_type - // LINUX-NOT: name: - // LINUX-NOT: identifier: + // LINUX-SAME: type: [[TYPE_OF_FOUR]] // LINUX-SAME: ) // // MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four" - // MSVC-SAME: type: [[TYPE_OF_FOUR:![0-9]+]] - // MSVC-SAME: ) - // MSVC: [[TYPE_OF_FOUR]] = distinct !DICompositeType - // MSVC-SAME: tag: DW_TAG_class_type - // MSVC-SAME: name: "" - // MSVC-SAME: identifier: ".?AV@?0??main@@9@" + // MSVC-SAME: type: [[TYPE_OF_FOUR]] // MSVC-SAME: ) return 0; diff --git a/clang/test/CodeGenCXX/debug-info-cxx1y.cpp b/clang/test/CodeGenCXX/debug-info-cxx1y.cpp --- 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]] +// CHECK-SAME: elements: [[EMPTY:![0-9]*]] +// CHECK: [[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-gline-tables-only-codeview.cpp b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp --- a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp +++ b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp @@ -51,9 +51,9 @@ // CHECK-SAME: name: "", c.lambda_params(); - // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1:[0-9]+]], - // CHECK: ![[LAMBDA1]] = !DICompositeType(tag: DW_TAG_class_type, + // CHECK: ![[LAMBDA1:[0-9]+]] = !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "", // CHECK-SAME: flags: DIFlagFwdDecl + // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1]], c.lambda2(); } diff --git a/clang/test/CodeGenCXX/debug-info-namespace.cpp b/clang/test/CodeGenCXX/debug-info-namespace.cpp --- a/clang/test/CodeGenCXX/debug-info-namespace.cpp +++ b/clang/test/CodeGenCXX/debug-info-namespace.cpp @@ -81,44 +81,43 @@ // CHECK: !DINamespace(scope: null) // CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit( // CHECK-SAME: imports: [[MODULES:![0-9]*]] -// CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]], [[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]] +// CHECK: [[MODULES]] = !{[[M1:![0-9]+]], [[M2:![0-9]+]], [[M3:![0-9]+]], [[M4:![0-9]+]]} // CHECK: [[M1]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CTXT]], entity: [[NS]], file: [[FOOCPP]], line: 15) - // CHECK: [[M2]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[CU]], entity: [[CTXT]], // CHECK: [[M3]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "E", scope: [[CU]], entity: [[CTXT]], file: [[FOOCPP]], line: 19) -// CHECK: [[M4]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[LEX2:![0-9]+]], entity: [[NS]], file: [[FOOCPP]], line: 23) +// CHECK: [[M4]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]] +// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4 +// CHECK-SAME: DISPFlagDefinition +// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} DISPFlagDefinition +// CHECK-SAME: retainedNodes: [[FUNC_NODES:![0-9]*]] +// CHECK: [[FUNC_NODES]] = !{[[M5:![0-9]+]], [[M6:![0-9]+]], [[M7:![0-9]+]], [[M8:![0-9]+]], [[M9:![0-9]+]], [[M10:![0-9]+]], [[M11:![0-9]+]], [[M12:![0-9]+]], [[M13:![0-9]+]], [[M14:![0-9]+]], [[M15:![0-9]+]], [[M16:![0-9]+]], [[M17:![0-9]+]]} +// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[LEX2:![0-9]+]], entity: [[NS]], file: [[FOOCPP]], line: 23) // CHECK: [[LEX2]] = distinct !DILexicalBlock(scope: [[LEX1:![0-9]+]], file: [[FOOCPP]], // CHECK: [[LEX1]] = distinct !DILexicalBlock(scope: [[FUNC:![0-9]+]], file: [[FOOCPP]], - -// CHECK: [[FUNC:![0-9]+]] = distinct !DISubprogram(name: "func",{{.*}} DISPFlagDefinition -// CHECK: [[M5]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT:![0-9]+]], -// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], file: [[FOOCPP]], line: 27) +// CHECK: [[M6]] = !DIImportedEntity(tag: DW_TAG_imported_module, scope: [[FUNC]], entity: [[CTXT]], +// CHECK: [[M7]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FOO:![0-9]+]], file: [[FOOCPP]], line: 27) // CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", // CHECK-SAME: line: 5 // CHECK-SAME: DIFlagFwdDecl -// CHECK: [[M7]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAR:![0-9]+]] +// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAR:![0-9]+]] // CHECK: [[BAR]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar", // CHECK-SAME: line: 6 // CHECK-SAME: DIFlagFwdDecl - -// CHECK: [[M8]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1:![0-9]+]] -// CHECK: [[F1:![0-9]+]] = distinct !DISubprogram(name: "f1",{{.*}} line: 4 -// CHECK-SAME: DISPFlagDefinition -// CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]] -// CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]] +// CHECK: [[M9]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[F1]] +// CHECK: [[M10]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[I]] +// CHECK: [[M11]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[BAZ:![0-9]+]] // CHECK: [[BAZ]] = !DIDerivedType(tag: DW_TAG_typedef, name: "baz", scope: [[NS]], file: [[FOOCPP]], // CHECK-SAME: baseType: [[BAR]] -// CHECK: [[M11]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "X", scope: [[FUNC]], entity: [[CTXT]] -// CHECK: [[M12]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "Y", scope: [[FUNC]], entity: [[M11]] -// CHECK: [[M13]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_DECL:![0-9]+]] +// CHECK: [[M12]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "X", scope: [[FUNC]], entity: [[CTXT]] +// CHECK: [[M13]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "Y", scope: [[FUNC]], entity: [[M12]] +// CHECK: [[M14]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_DECL:![0-9]+]] // CHECK: [[VAR_DECL]] = !DIGlobalVariable(name: "var_decl", linkageName: "{{[^"]*var_decl[^"]*}}", scope: [[NS]],{{.*}} line: 8, -// CHECK: [[M14]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_DECL:![0-9]+]] +// CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_DECL:![0-9]+]] // CHECK: [[FUNC_DECL]] = !DISubprogram(name: "func_decl", // CHECK-SAME: scope: [[NS]], file: [[FOOCPP]], line: 9 -// CHECK: [[M15]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]] -// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]] +// CHECK: [[M16]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[VAR_FWD:![0-9]+]] +// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[FUNC]], entity: [[FUNC_FWD:![0-9]+]] // CHECK: [[FUNC_FWD]] = distinct !DISubprogram(name: "func_fwd",{{.*}} line: 53,{{.*}} DISPFlagDefinition -// CHECK: [[M17]] = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: [[CTXT]], entity: [[I]] // CHECK: distinct !DISubprogram(name: "c",{{.*}}, scope: ![[C:[0-9]+]],{{.*}}, line: 60,{{.*}} DISPFlagDefinition // CHECK: ![[C]] = !DINamespace(name: "C", diff --git a/clang/test/CodeGenCXX/debug-info-template.cpp b/clang/test/CodeGenCXX/debug-info-template.cpp --- a/clang/test/CodeGenCXX/debug-info-template.cpp +++ b/clang/test/CodeGenCXX/debug-info-template.cpp @@ -222,7 +222,7 @@ 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 @@ 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/CodeGenCXX/debug-lambda-this.cpp b/clang/test/CodeGenCXX/debug-lambda-this.cpp --- a/clang/test/CodeGenCXX/debug-lambda-this.cpp +++ b/clang/test/CodeGenCXX/debug-lambda-this.cpp @@ -13,10 +13,10 @@ } // CHECK: ![[D:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D", -// CHECK: ![[POINTER:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64) // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "this", // CHECK-SAME: line: 11 -// CHECK-SAME: baseType: ![[POINTER]] +// CHECK-SAME: baseType: ![[POINTER:[0-9]+]] // CHECK-SAME: size: 64 // CHECK-NOT: offset: 0 // CHECK-SAME: ){{$}} +// CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64) diff --git a/clang/test/CodeGenObjC/debug-info-category.m b/clang/test/CodeGenObjC/debug-info-category.m --- a/clang/test/CodeGenObjC/debug-info-category.m +++ b/clang/test/CodeGenObjC/debug-info-category.m @@ -37,10 +37,10 @@ // 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 --- a/llvm/include/llvm/IR/DIBuilder.h +++ b/llvm/include/llvm/IR/DIBuilder.h @@ -48,30 +48,43 @@ Function *LabelFn; ///< llvm.dbg.label Function *AddrFn; ///< llvm.dbg.addr - SmallVector AllEnumTypes; /// Track the RetainTypes, since they can be updated later on. SmallVector AllRetainTypes; SmallVector AllSubprograms; - SmallVector AllGVs; - SmallVector AllImportedModules; /// Map Macro parent (which can be DIMacroFile or nullptr) to a list of /// Metadata all of type DIMacroNode. /// DIMacroNode's with nullptr parent are DICompileUnit direct children. MapVector> AllMacrosPerParent; + /// Module level global variables, enum types and imported entities. + SmallVector ModuleGVs; + SmallVector ModuleEnumTypes; + SmallVector ModuleImports; + /// Track nodes that may be unresolved. SmallVector UnresolvedNodes; bool AllowUnresolvedNodes; - /// Each subprogram's preserved local variables. + /// Each subprogram's local variables (including static), labels, types, + /// and imported entities. /// /// 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> PreservedVariables; + DenseMap> + SubprogramTrackedNodes; + + SmallVectorImpl & + getImportTrackingVector(const DIScope *S) { + return isa_and_nonnull(S) + ? getSubprogramNodesTrackingVector(S) + : ModuleImports; + } - /// Each subprogram's preserved labels. - DenseMap> PreservedLabels; + SmallVectorImpl & + getSubprogramNodesTrackingVector(const DIScope *S) { + return SubprogramTrackedNodes[cast(S)->getSubprogram()]; + } /// Create a temporary. /// 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 @@ -1856,7 +1856,7 @@ unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams, DISubprogram *Declaration, - DINodeArray RetainedNodes, DITypeArray ThrownTypes, + MDNodeArray RetainedNodes, DITypeArray ThrownTypes, DINodeArray Annotations, StringRef TargetFuncName, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), @@ -1873,7 +1873,7 @@ unsigned ScopeLine, Metadata *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, Metadata *Unit, Metadata *TemplateParams, Metadata *Declaration, - Metadata *RetainedNodes, Metadata *ThrownTypes, Metadata *Annotations, + Metadata *RetainedNodes,Metadata *ThrownTypes, Metadata *Annotations, MDString *TargetFuncName, StorageType Storage, bool ShouldCreate = true); @@ -1895,7 +1895,7 @@ DIType *ContainingType, unsigned VirtualIndex, int ThisAdjustment, DIFlags Flags, DISPFlags SPFlags, DICompileUnit *Unit, DITemplateParameterArray TemplateParams = nullptr, - DISubprogram *Declaration = nullptr, DINodeArray RetainedNodes = nullptr, + DISubprogram *Declaration = nullptr, MDNodeArray RetainedNodes = nullptr, DITypeArray ThrownTypes = nullptr, DINodeArray Annotations = nullptr, StringRef TargetFuncName = ""), (Scope, Name, LinkageName, File, Line, Type, ScopeLine, ContainingType, @@ -2017,7 +2017,7 @@ DISubprogram *getDeclaration() const { return cast_or_null(getRawDeclaration()); } - DINodeArray getRetainedNodes() const { + MDNodeArray getRetainedNodes() const { return cast_or_null(getRawRetainedNodes()); } DITypeArray getThrownTypes() const { @@ -2056,6 +2056,9 @@ void replaceRawLinkageName(MDString *LinkageName) { replaceOperandWith(3, LinkageName); } + void replaceRetainedNodes(MDNodeArray N) { + replaceOperandWith(7, N.get()); + } /// Check if this subprogram describes the given function. /// diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -61,11 +61,6 @@ /// The start of the unit macro info within macro section. MCSymbol *MacroLabelBegin; - using ImportedEntityList = SmallVector; - using ImportedEntityMap = DenseMap; - - ImportedEntityMap ImportedEntities; - /// GlobalNames - A map of globally visible named entities for this unit. StringMap GlobalNames; @@ -79,7 +74,19 @@ // ranges/locs. const MCSymbol *BaseAddress = nullptr; - DenseMap AbstractSPDies; + using MDNodeSetVector = + SetVector, + SmallPtrSet>; + + // List of entities (either static locals, types or imports) that + // belong to subprograms within this CU. + MDNodeSetVector DeferredLocalDecls; + + // List of concrete lexical block scopes belong to subprograms within this CU. + DenseMap LocalScopeDIEs; + + // List of abstract local scopes (either DISubprogram or DILexicalBlock). + DenseMap AbstractLocalScopeDIEs; DenseMap> AbstractEntities; /// DWO ID for correlating skeleton and split units. @@ -94,10 +101,10 @@ bool isDwoUnit() const override; - DenseMap &getAbstractSPDies() { + DenseMap &getAbstractScopeDIEs() { if (isDwoUnit() && !DD->shareAcrossDWOCUs()) - return AbstractSPDies; - return DU->getAbstractSPDies(); + return AbstractLocalScopeDIEs; + return DU->getAbstractScopeDIEs(); } DenseMap> &getAbstractEntities() { @@ -147,9 +154,8 @@ std::vector ExprRefedBaseTypes; /// Get or create global variable DIE. - DIE * - getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, - ArrayRef GlobalExprs); + DIE *getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV, + ArrayRef GlobalExprs); DIE *getOrCreateCommonBlock(const DICommonBlock *CB, ArrayRef GlobalExprs); @@ -171,17 +177,6 @@ unsigned getOrCreateSourceID(const DIFile *File) override; - void addImportedEntity(const DIImportedEntity* IE) { - DIScope *Scope = IE->getScope(); - assert(Scope && "Invalid Scope encoding!"); - if (!isa(Scope)) - // No need to add imported enities that are not local declaration. - return; - - auto *LocalScope = cast(Scope)->getNonLexicalBlockFileScope(); - ImportedEntities[LocalScope].push_back(IE); - } - /// addRange - Add an address range to the list of ranges for this unit. void addRange(RangeSpan Range); @@ -210,7 +205,11 @@ /// Construct new DW_TAG_lexical_block for this scope and /// attach DW_AT_low_pc/DW_AT_high_pc labels. - DIE *constructLexicalScopeDIE(LexicalScope *Scope); + DIE *getOrCreateLexicalScopeDIE(LexicalScope *Scope, DIE &ScopeDIE); + + /// Construct a DW_TAG_lexical_block for the given DILexicalBlock + /// w/o setting location information. + DIE *getOrCreateLexicalBlockDIE(const DILexicalBlock *LB); /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false); @@ -223,6 +222,8 @@ void createBaseTypeDIEs(); + DIE *getOrCreateContextDIE(const DIScope *Ty) override; + /// Construct a DIE for this subprogram scope. DIE &constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope); @@ -261,8 +262,9 @@ void constructCallSiteParmEntryDIEs(DIE &CallSiteDIE, SmallVector &Params); - /// Construct import_module DIE. - DIE *constructImportedEntityDIE(const DIImportedEntity *Module); + /// Construct DIE for an imported entity. + DIE *createImportedEntityDIE(const DIImportedEntity *IE); + void createAndAddImportedEntityDIE(const DIImportedEntity *IE); void finishSubprogramDefinition(const DISubprogram *SP); void finishEntityDefinition(const DbgEntity *Entity); @@ -359,6 +361,8 @@ bool hasDwarfPubSections() const; void addBaseTypeRef(DIEValueList &Die, int64_t Idx); + + MDNodeSetVector &getDeferredLocalDecls() { return DeferredLocalDecls; } }; } // end namespace llvm 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 @@ -561,10 +561,9 @@ return; // Emit lexical blocks. - DIE *ScopeDIE = constructLexicalScopeDIE(Scope); + DIE *ScopeDIE = getOrCreateLexicalScopeDIE(Scope, ParentScopeDIE); assert(ScopeDIE && "Scope DIE should not be null."); - ParentScopeDIE.addChild(ScopeDIE); createAndAddScopeChildren(Scope, *ScopeDIE); } @@ -658,7 +657,7 @@ auto *InlinedSP = getDISubprogram(DS); // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram // was inlined from another compile unit. - DIE *OriginDIE = getAbstractSPDies()[InlinedSP]; + DIE *OriginDIE = getAbstractScopeDIEs()[InlinedSP]; assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_inlined_subroutine); @@ -684,21 +683,75 @@ return ScopeDIE; } -// Construct new DW_TAG_lexical_block for this scope and attach -// DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) { +// Construct new DW_TAG_lexical_block for this scope if it hasn't been +// created yet and attach DW_AT_low_pc/DW_AT_high_pc labels. +DIE *DwarfCompileUnit::getOrCreateLexicalScopeDIE(LexicalScope *Scope, + DIE &ParentScopeDIE) { if (DD->isLexicalScopeDIENull(Scope)) return nullptr; - auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); - if (Scope->isAbstractScope()) - return ScopeDIE; + DIE *ScopeDIE = nullptr; + const auto *DS = Scope->getScopeNode(); + + // FIXME: We may already create a concrete DIE for this scope while + // emitting local variables for abstract tree of an inlined function. + // This may happen if the local variable has a templated type with + // a function-local type as a template parameter. See PR55680 for details. + if (!Scope->isAbstractScope() && !Scope->getInlinedAt()) { + if (LocalScopeDIEs.count(DS)) { + ScopeDIE = LocalScopeDIEs[DS]; + assert(!ScopeDIE->findAttribute(dwarf::DW_AT_low_pc) && + !ScopeDIE->findAttribute(dwarf::DW_AT_ranges)); + assert(ScopeDIE->getParent() == &ParentScopeDIE); + } + } - attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); + if (!ScopeDIE) { + ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + ParentScopeDIE.addChild(ScopeDIE); + + if (Scope->isAbstractScope()) { + assert(!getAbstractScopeDIEs().count(DS) && + "Abstract DIE for this scope exists!"); + getAbstractScopeDIEs()[DS] = ScopeDIE; + return ScopeDIE; + } + + if (!Scope->getInlinedAt()) + LocalScopeDIEs[DS] = ScopeDIE; + } + attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); return ScopeDIE; } +// Construct DW_TAG_lexical_block, but without ranges information. +// It's used to create proper context DIE for function-local types. +DIE *DwarfCompileUnit::getOrCreateLexicalBlockDIE(const DILexicalBlock *LB) { + // Assume if there is an abstract tree all the DIEs are already emitted. + bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram()); + if (isAbstract && getAbstractScopeDIEs().count(LB)) + return getAbstractScopeDIEs()[LB]; + assert(!isAbstract && "Missed lexical block DIE in abstract tree!"); + + // Check if we have a concrete DIE. + if (LocalScopeDIEs.count(LB)) + return LocalScopeDIEs[LB]; + + // If nothing available found, create new DW_TAG_lexical_block. + const auto *Context = LB->getScope()->getNonLexicalBlockFileScope(); + DIE *ContextDIE = + isa(Context) + ? getOrCreateContextDIE(Context) + : getOrCreateLexicalBlockDIE(cast(Context)); + assert(ContextDIE && "Empty context DIE."); + + auto *BlockDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block); + ContextDIE->addChild(BlockDIE); + LocalScopeDIEs[LB] = BlockDIE; + return BlockDIE; +} + /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) { auto D = constructVariableDIEImpl(DV, Abstract); @@ -1057,35 +1110,33 @@ for (DbgVariable *DV : Locals) ScopeDIE.addChild(constructVariableDIE(*DV, *Scope, ObjectPointer)); - // Emit imported entities (skipped in gmlt-like data). - if (!includeMinimalInlineScopes()) { - for (const auto *IE : ImportedEntities[Scope->getScopeNode()]) - ScopeDIE.addChild(constructImportedEntityDIE(cast(IE))); - } - // Emit labels. for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope)) ScopeDIE.addChild(constructLabelDIE(*DL, *Scope)); + // Track other local entities. This creates mapping between CU and a set + // of local declarations that should be emitted for subprograms in this CU. + if (!includeMinimalInlineScopes() && !Scope->getInlinedAt()) + for (const auto *Decl : DD->getLocalDeclsForScope(Scope->getScopeNode())) + DeferredLocalDecls.insert(Decl); + // Emit inner lexical scopes. - auto needToEmitLexicalScope = [this](LexicalScope *LS) { - if (isa(LS->getScopeNode())) - return true; - auto Vars = DU->getScopeVariables().lookup(LS); + auto skipLexicalScope = [this](LexicalScope *S) -> bool { + if (isa(S->getScopeNode())) + return false; + auto Vars = DU->getScopeVariables().lookup(S); if (!Vars.Args.empty() || !Vars.Locals.empty()) - return true; - if (!includeMinimalInlineScopes() && - !ImportedEntities[LS->getScopeNode()].empty()) - return true; - return false; + return false; + return includeMinimalInlineScopes() || + DD->getLocalDeclsForScope(S->getScopeNode()).empty(); }; for (LexicalScope *LS : Scope->getChildren()) { // If the lexical block doesn't have non-scope children, skip // its emission and put its children directly to the parent scope. - if (needToEmitLexicalScope(LS)) - constructScopeDIE(LS, ScopeDIE); - else + if (skipLexicalScope(LS)) createAndAddScopeChildren(LS, ScopeDIE); + else + constructScopeDIE(LS, ScopeDIE); } return ObjectPointer; @@ -1093,11 +1144,9 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE( LexicalScope *Scope) { - DIE *&AbsDef = getAbstractSPDies()[Scope->getScopeNode()]; - if (AbsDef) - return; - auto *SP = cast(Scope->getScopeNode()); + if (getAbstractScopeDIEs().count(SP)) + return; DIE *ContextDIE; DwarfCompileUnit *ContextCU = this; @@ -1121,14 +1170,19 @@ // Passing null as the associated node because the abstract definition // shouldn't be found by lookup. - AbsDef = &ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, nullptr); - ContextCU->applySubprogramAttributesToDefinition(SP, *AbsDef); - ContextCU->addSInt(*AbsDef, dwarf::DW_AT_inline, + DIE &AbsDef = ContextCU->createAndAddDIE(dwarf::DW_TAG_subprogram, + *ContextDIE, nullptr); + + // Store the DIE before creating children. + ContextCU->getAbstractScopeDIEs()[SP] = &AbsDef; + + ContextCU->applySubprogramAttributesToDefinition(SP, AbsDef); + ContextCU->addSInt(AbsDef, dwarf::DW_AT_inline, DD->getDwarfVersion() <= 4 ? Optional() : dwarf::DW_FORM_implicit_const, dwarf::DW_INL_inlined); - if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, *AbsDef)) - ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); + if (DIE *ObjectPointer = ContextCU->createAndAddScopeChildren(Scope, AbsDef)) + ContextCU->addDIEEntry(AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); } bool DwarfCompileUnit::useGNUAnalogForDwarf5Feature() const { @@ -1262,47 +1316,59 @@ } } -DIE *DwarfCompileUnit::constructImportedEntityDIE( - const DIImportedEntity *Module) { - DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag()); - insertDIE(Module, IMDie); +DIE *DwarfCompileUnit::createImportedEntityDIE(const DIImportedEntity *IE) { + DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)IE->getTag()); + insertDIE(IE, IMDie); + DIE *EntityDie; - auto *Entity = Module->getEntity(); + auto *Entity = IE->getEntity(); if (auto *NS = dyn_cast(Entity)) EntityDie = getOrCreateNameSpace(NS); else if (auto *M = dyn_cast(Entity)) EntityDie = getOrCreateModule(M); - else if (auto *SP = dyn_cast(Entity)) - EntityDie = getOrCreateSubprogramDIE(SP); - else if (auto *T = dyn_cast(Entity)) + else if (auto *SP = dyn_cast(Entity)) { + // If there is an abstract subprogram, refer it. Note that this assumes + // that all the abstract SPs have been already created. + if (auto *AbsSPDie = getAbstractScopeDIEs().lookup(SP)) + EntityDie = AbsSPDie; + else + EntityDie = getOrCreateSubprogramDIE(SP); + } else if (auto *T = dyn_cast(Entity)) EntityDie = getOrCreateTypeDIE(T); else if (auto *GV = dyn_cast(Entity)) EntityDie = getOrCreateGlobalVariableDIE(GV, {}); else EntityDie = getDIE(Entity); assert(EntityDie); - addSourceLine(*IMDie, Module->getLine(), Module->getFile()); + + addSourceLine(*IMDie, IE->getLine(), IE->getFile()); addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); - StringRef Name = Module->getName(); + StringRef Name = IE->getName(); if (!Name.empty()) addString(*IMDie, dwarf::DW_AT_name, Name); // This is for imported module with renamed entities (such as variables and // subprograms). - DINodeArray Elements = Module->getElements(); + DINodeArray Elements = IE->getElements(); for (const auto *Element : Elements) { if (!Element) continue; - IMDie->addChild( - constructImportedEntityDIE(cast(Element))); + IMDie->addChild(createImportedEntityDIE(cast(Element))); } - return IMDie; } +void DwarfCompileUnit::createAndAddImportedEntityDIE( + const DIImportedEntity *IE) { + DIE *ContextDIE = getOrCreateContextDIE(IE->getScope()); + assert(ContextDIE && "Empty scope for the imported entity!"); + + ContextDIE->addChild(createImportedEntityDIE(IE)); +} + void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) { DIE *D = getDIE(SP); - if (DIE *AbsSPDIE = getAbstractSPDies().lookup(SP)) { + if (DIE *AbsSPDIE = getAbstractScopeDIEs().lookup(SP)) { if (D) // If this subprogram has an abstract definition, reference that addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); @@ -1593,3 +1659,18 @@ Btr.Die = &Die; } } + +DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) { + if (isa_and_nonnull(Context)) { + if (auto *LFScope = dyn_cast(Context)) + Context = LFScope->getNonLexicalBlockFileScope(); + if (auto *LScope = dyn_cast(Context)) + return getOrCreateLexicalBlockDIE(LScope); + + // Otherwise the context must be a DISubprogram. + auto *SPScope = cast(Context); + if (getAbstractScopeDIEs().count(SPScope)) + return getAbstractScopeDIEs()[SPScope]; + } + return DwarfUnit::getOrCreateContextDIE(Context); +} diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -314,11 +314,19 @@ /// can refer to them in spite of insertions into this list. DebugLocStream DebugLocs; + using SubprogramSetVector = + SetVector, + SmallPtrSet>; + /// This is a collection of subprogram MDNodes that are processed to /// create DIEs. - SetVector, - SmallPtrSet> - ProcessedSPNodes; + SubprogramSetVector ProcessedSPNodes; + + /// Map function-local types, static vars and imports to their parent local + /// scope (either DILexicalBlock or DISubprogram) for a processed function + /// (including inlined subprograms). + DenseMap> + LocalDeclsPerLS; /// If nonnull, stores the current machine function we're processing. const MachineFunction *CurFn = nullptr; @@ -454,9 +462,6 @@ using InlinedEntity = DbgValueHistoryMap::InlinedEntity; - void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, - const DINode *Node, - const MDNode *Scope); void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, const DINode *Node, const MDNode *Scope); @@ -596,10 +601,6 @@ void finishUnitAttributes(const DICompileUnit *DIUnit, DwarfCompileUnit &NewCU); - /// Construct imported_module or imported_declaration DIE. - void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity *N); - /// Register a source line with debug info. Returns the unique /// label that was emitted and which provides correspondence to the /// source line list. @@ -840,6 +841,11 @@ /// If the \p File has an MD5 checksum, return it as an MD5Result /// allocated in the MCContext. Optional getMD5AsBytes(const DIFile *File) const; + + SmallVectorImpl & + getLocalDeclsForScope(const DILocalScope *S) { + return LocalDeclsPerLS[S]; + } }; } // end namespace llvm diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -513,7 +513,7 @@ // well into the name table. Only do that if we are going to actually emit // that name. if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() && - (useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP))) + (useAllLinkageNames() || InfoHolder.getAbstractScopeDIEs().lookup(SP))) addAccelName(CU, SP->getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator @@ -1064,6 +1064,7 @@ } } } + // Create new DwarfCompileUnit for the given metadata node with tag // DW_TAG_compile_unit. DwarfCompileUnit & @@ -1078,9 +1079,6 @@ DwarfCompileUnit &NewCU = *OwnedUnit; InfoHolder.addUnit(std::move(OwnedUnit)); - for (auto *IE : DIUnit->getImportedEntities()) - NewCU.addImportedEntity(IE); - // LTO with assembly output shares a single line table amongst multiple CUs. // To avoid the compilation directory being ambiguous, let the line table // explicitly describe the directory of all files, never relying on the @@ -1100,15 +1098,8 @@ CUMap.insert({DIUnit, &NewCU}); CUDieMap.insert({&NewCU.getUnitDie(), &NewCU}); - return NewCU; -} -void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity *N) { - if (isa(N->getScope())) - return; - if (DIE *D = TheCU.getOrCreateContextDIE(N->getScope())) - D->addChild(TheCU.constructImportedEntityDIE(N)); + return NewCU; } // Emit all Dwarf sections that should come prior to the content. Create @@ -1351,6 +1342,7 @@ assert(CurFn == nullptr); assert(CurMI == nullptr); + // Collect global variables info. DenseMap> GVMap; for (const GlobalVariable &Global : MMI->getModule()->globals()) { @@ -1365,19 +1357,11 @@ // If this CU hasn't been emitted yet, create it here unless it is empty. if (!CU) { - // FIXME: Move local imported entities into a list attached to the - // subprogram, then this search won't be needed and a - // getImportedEntities().empty() test should go below with the rest. - bool HasNonLocalImportedEntities = llvm::any_of( - CUNode->getImportedEntities(), [](const DIImportedEntity *IE) { - return !isa(IE->getScope()); - }); - - if (!HasNonLocalImportedEntities && CUNode->getEnumTypes().empty() && + if (CUNode->getImportedEntities().empty() && + CUNode->getEnumTypes().empty() && CUNode->getRetainedTypes().empty() && CUNode->getGlobalVariables().empty() && CUNode->getMacros().empty()) continue; - CU = &getOrCreateDwarfCompileUnit(CUNode); } @@ -1395,22 +1379,46 @@ DenseSet Processed; for (auto *GVE : CUNode->getGlobalVariables()) { DIGlobalVariable *GV = GVE->getVariable(); + assert(!isa_and_nonnull(GV->getScope()) && + "Unexpected function-local entity in 'globals' CU field."); if (Processed.insert(GV).second) CU->getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV])); } - for (auto *Ty : CUNode->getEnumTypes()) + for (auto *Ty : CUNode->getEnumTypes()) { + assert(!isa_and_nonnull(Ty->getScope()) && + "Unexpected function-local entity in 'enums' CU field."); CU->getOrCreateTypeDIE(cast(Ty)); + } - for (auto *Ty : CUNode->getRetainedTypes()) + for (auto *Ty : CUNode->getRetainedTypes()) { + // There is no point in force-emitting a forward declaration. if (DIType *RT = dyn_cast(Ty)) - // There is no point in force-emitting a forward declaration. CU->getOrCreateTypeDIE(RT); + } // Emit imported entities last so that the relevant context // is already available. - for (auto *IE : CUNode->getImportedEntities()) - constructAndAddImportedEntityDIE(*CU, IE); + for (auto *IE : CUNode->getImportedEntities()) { + assert(!isa_and_nonnull(IE->getScope()) && + "Unexpected function-local entity in 'imports' CU field."); + CU->createAndAddImportedEntityDIE(IE); + } + + // Emit function-local entities. + for (const auto *D : CU->getDeferredLocalDecls()) { + if (auto *GVE = dyn_cast(D)) { + DIGlobalVariable *GV = GVE->getVariable(); + if (Processed.insert(GV).second) + CU->getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV])); + } else if (auto *Ty = dyn_cast(D)) { + CU->getOrCreateTypeDIE(Ty); + } else if (auto *IE = dyn_cast(D)) { + CU->createAndAddImportedEntityDIE(IE); + } else { + llvm_unreachable("Unexpected function-local entity!"); + } + } CU->createBaseTypeDIEs(); } @@ -1486,16 +1494,6 @@ // FIXME: AbstractVariables.clear(); } -void DwarfDebug::ensureAbstractEntityIsCreated(DwarfCompileUnit &CU, - const DINode *Node, - const MDNode *ScopeNode) { - if (CU.getExistingAbstractEntity(Node)) - return; - - CU.createAbstractEntity(Node, LScopes.getOrCreateAbstractScope( - cast(ScopeNode))); -} - void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU, const DINode *Node, const MDNode *ScopeNode) { if (CU.getExistingAbstractEntity(Node)) @@ -1939,19 +1937,24 @@ createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym); } - // Collect info for variables/labels that were optimized out. - for (const DINode *DN : SP->getRetainedNodes()) { - if (!Processed.insert(InlinedEntity(DN, nullptr)).second) - continue; - LexicalScope *Scope = nullptr; - if (auto *DV = dyn_cast(DN)) { - Scope = LScopes.findLexicalScope(DV->getScope()); - } else if (auto *DL = dyn_cast(DN)) { - Scope = LScopes.findLexicalScope(DL->getScope()); + // Collect info for retained nodes. + for (const MDNode *N : SP->getRetainedNodes()) { + if (isa(N) || isa(N)) { + if (!Processed.insert(InlinedEntity(cast(N), nullptr)).second) + continue; + LexicalScope *LexS = LScopes.findLexicalScope( + isa(N) ? cast(N)->getScope() + : cast(N)->getScope()); + if (LexS) + createConcreteEntity(TheCU, *LexS, cast(N), nullptr); + } else { + const DIScope *LocalS = + isa(N) ? cast(N)->getScope() + : isa(N) + ? cast(N)->getVariable()->getScope() + : cast(N)->getScope(); + LocalDeclsPerLS[cast(LocalS)].push_back(N); } - - if (Scope) - createConcreteEntity(TheCU, *Scope, DN, nullptr); } } @@ -2231,28 +2234,42 @@ return; } + // Construct abstract scopes. #ifndef NDEBUG - size_t NumAbstractScopes = LScopes.getAbstractScopesList().size(); + size_t NumSPAbstractScopes = LScopes.getAbstractScopesList().size(); #endif - // Construct abstract scopes. + SmallPtrSet ProcessedASPs; for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { const auto *SP = cast(AScope->getScopeNode()); - for (const DINode *DN : SP->getRetainedNodes()) { - if (!Processed.insert(InlinedEntity(DN, nullptr)).second) - continue; - - const MDNode *Scope = nullptr; - if (auto *DV = dyn_cast(DN)) - Scope = DV->getScope(); - else if (auto *DL = dyn_cast(DN)) - Scope = DL->getScope(); - else - llvm_unreachable("Unexpected DI type!"); - - // Collect info for variables/labels that were optimized out. - ensureAbstractEntityIsCreated(TheCU, DN, Scope); - assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes - && "ensureAbstractEntityIsCreated inserted abstract scopes"); + for (const MDNode *N : SP->getRetainedNodes()) { + if (isa(N) || isa(N)) { + const auto *DN = cast(N); + if (!Processed.insert(InlinedEntity(DN, nullptr)).second) + continue; + if (TheCU.getExistingAbstractEntity(DN)) + continue; + const auto *LS = isa(N) + ? cast(DN)->getScope() + : cast(DN)->getScope(); + TheCU.createAbstractEntity(DN, LScopes.getOrCreateAbstractScope(LS)); + } else { + if (!ProcessedASPs.insert(SP).second) + continue; + const DIScope *S = + isa(N) ? cast(N)->getScope() + : isa(N) + ? cast(N)->getVariable()->getScope() + : cast(N)->getScope(); + // Ensure the scope is not a DILexicalBlockFile. + const auto *LS = cast(S)->getNonLexicalBlockFileScope(); + // Ensure LexicalScope is created for the scope of this node. + const auto *LexS = LScopes.getOrCreateAbstractScope(LS); (void)LexS; + assert(LexS && "Expected the LexicalScope to be created."); + LocalDeclsPerLS[LS].push_back(N); + } + assert( + LScopes.getAbstractScopesList().size() == NumSPAbstractScopes && + "getOrCreateAbstractScope() inserted abstract scope of a subprogram"); } constructAbstractSubprogramScopeDIE(TheCU, AScope); } @@ -2273,6 +2290,7 @@ // can be used cross-function) InfoHolder.getScopeVariables().clear(); InfoHolder.getScopeLabels().clear(); + LocalDeclsPerLS.clear(); PrevLabel = nullptr; CurFn = nullptr; } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h --- a/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h @@ -26,6 +26,7 @@ class DbgVariable; class DbgLabel; class DINode; +class DILocalScope; class DwarfCompileUnit; class DwarfUnit; class LexicalScope; @@ -87,7 +88,7 @@ DenseMap ScopeLabels; // Collection of abstract subprogram DIEs. - DenseMap AbstractSPDies; + DenseMap AbstractLocalScopeDIEs; DenseMap> AbstractEntities; /// Maps MDNodes for type system with the corresponding DIEs. These DIEs can @@ -162,8 +163,8 @@ return ScopeLabels; } - DenseMap &getAbstractSPDies() { - return AbstractSPDies; + DenseMap &getAbstractScopeDIEs() { + return AbstractLocalScopeDIEs; } DenseMap> &getAbstractEntities() { 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 @@ -248,7 +248,7 @@ DIE *getOrCreateTypeDIE(const MDNode *TyNode); /// Get context owner's DIE. - DIE *getOrCreateContextDIE(const DIScope *Context); + virtual DIE *getOrCreateContextDIE(const DIScope *Context); /// Construct DIEs for types that contain vtables. void constructContainingTypeDIEs(); 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 @@ -1222,7 +1222,7 @@ "decl has a linkage name and it is different"); if (DeclLinkageName.empty() && // Always emit it for abstract subprograms. - (DD->useAllLinkageNames() || DU->getAbstractSPDies().lookup(SP))) + (DD->useAllLinkageNames() || DU->getAbstractScopeDIEs().lookup(SP))) addLinkageName(SPDie, LinkageName); if (!DeclDie) 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 @@ -34,13 +34,13 @@ AllowUnresolvedNodes(AllowUnresolvedNodes) { if (CUNode) { if (const auto &ETs = CUNode->getEnumTypes()) - AllEnumTypes.assign(ETs.begin(), ETs.end()); + ModuleEnumTypes.assign(ETs.begin(), ETs.end()); if (const auto &RTs = CUNode->getRetainedTypes()) AllRetainTypes.assign(RTs.begin(), RTs.end()); if (const auto &GVs = CUNode->getGlobalVariables()) - AllGVs.assign(GVs.begin(), GVs.end()); + ModuleGVs.assign(GVs.begin(), GVs.end()); if (const auto &IMs = CUNode->getImportedEntities()) - AllImportedModules.assign(IMs.begin(), IMs.end()); + ModuleImports.assign(IMs.begin(), IMs.end()); if (const auto &MNs = CUNode->getMacros()) AllMacrosPerParent.insert({nullptr, {MNs.begin(), MNs.end()}}); } @@ -57,23 +57,11 @@ } void DIBuilder::finalizeSubprogram(DISubprogram *SP) { - 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()); + auto PN = SubprogramTrackedNodes.find(SP); + if (PN != SubprogramTrackedNodes.end()) + SP->replaceRetainedNodes( + MDTuple::get(VMContext, SmallVector(PN->second.begin(), + PN->second.end()))); } void DIBuilder::finalize() { @@ -83,8 +71,8 @@ return; } - if (!AllEnumTypes.empty()) - CUNode->replaceEnumTypes(MDTuple::get(VMContext, AllEnumTypes)); + if (!ModuleEnumTypes.empty()) + CUNode->replaceEnumTypes(MDTuple::get(VMContext, ModuleEnumTypes)); SmallVector RetainValues; // Declarations and definitions of the same type may be retained. Some @@ -106,13 +94,13 @@ if (auto *SP = dyn_cast(N)) finalizeSubprogram(SP); - if (!AllGVs.empty()) - CUNode->replaceGlobalVariables(MDTuple::get(VMContext, AllGVs)); + if (!ModuleGVs.empty()) + CUNode->replaceGlobalVariables(MDTuple::get(VMContext, ModuleGVs)); - if (!AllImportedModules.empty()) + if (!ModuleImports.empty()) CUNode->replaceImportedEntities(MDTuple::get( - VMContext, SmallVector(AllImportedModules.begin(), - AllImportedModules.end()))); + VMContext, SmallVector(ModuleImports.begin(), + ModuleImports.end()))); for (const auto &I : AllMacrosPerParent) { // DIMacroNode's with nullptr parent are DICompileUnit direct children. @@ -176,7 +164,7 @@ createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope *Context, Metadata *NS, DIFile *File, unsigned Line, StringRef Name, DINodeArray Elements, - SmallVectorImpl &AllImportedModules) { + SmallVectorImpl &ImportedEntities) { if (Line) assert(File && "Source location has line number but no file"); unsigned EntitiesCount = C.pImpl->DIImportedEntitys.size(); @@ -185,7 +173,7 @@ if (EntitiesCount < C.pImpl->DIImportedEntitys.size()) // A new Imported Entity was just added to the context. // Add it to the Imported Modules list. - AllImportedModules.emplace_back(M); + ImportedEntities.emplace_back(M); return M; } @@ -195,7 +183,7 @@ DINodeArray Elements) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, Context, NS, File, Line, StringRef(), Elements, - AllImportedModules); + getImportTrackingVector(Context)); } DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, @@ -204,7 +192,7 @@ DINodeArray Elements) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, Context, NS, File, Line, StringRef(), Elements, - AllImportedModules); + getImportTrackingVector(Context)); } DIImportedEntity *DIBuilder::createImportedModule(DIScope *Context, DIModule *M, @@ -212,7 +200,7 @@ DINodeArray Elements) { return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_module, Context, M, File, Line, StringRef(), Elements, - AllImportedModules); + getImportTrackingVector(Context)); } DIImportedEntity * @@ -223,7 +211,7 @@ // types that have one. return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration, Context, Decl, File, Line, Name, Elements, - AllImportedModules); + getImportTrackingVector(Context)); } DIFile *DIBuilder::createFile(StringRef Filename, StringRef Directory, @@ -349,10 +337,13 @@ DIFile *File, unsigned LineNo, DIScope *Context, uint32_t AlignInBits, DINodeArray Annotations) { - return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, - LineNo, getNonCompileUnitScope(Context), Ty, 0, - AlignInBits, 0, None, DINode::FlagZero, nullptr, - Annotations); + auto *T = + DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, LineNo, + getNonCompileUnitScope(Context), Ty, 0, AlignInBits, 0, + None, DINode::FlagZero, nullptr, Annotations); + if (isa_and_nonnull(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(T); + return T; } DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) { @@ -499,6 +490,8 @@ OffsetInBits, Flags, Elements, 0, VTableHolder, cast_or_null(TemplateParams), UniqueIdentifier); trackIfUnresolved(R); + if (isa_and_nonnull(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(R); return R; } @@ -512,6 +505,8 @@ getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits, 0, Flags, Elements, RunTimeLang, VTableHolder, nullptr, UniqueIdentifier); trackIfUnresolved(R); + if (isa_and_nonnull(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(R); return R; } @@ -524,6 +519,8 @@ getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags, Elements, RunTimeLang, nullptr, nullptr, UniqueIdentifier); trackIfUnresolved(R); + if (isa_and_nonnull(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(R); return R; } @@ -556,7 +553,10 @@ getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0, IsScoped ? DINode::FlagEnumClass : DINode::FlagZero, Elements, 0, nullptr, nullptr, UniqueIdentifier); - AllEnumTypes.push_back(CTy); + if (isa_and_nonnull(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(CTy); + else + ModuleEnumTypes.push_back(CTy); trackIfUnresolved(CTy); return CTy; } @@ -654,6 +654,8 @@ SizeInBits, AlignInBits, 0, DINode::FlagFwdDecl, nullptr, RuntimeLang, nullptr, nullptr, UniqueIdentifier); trackIfUnresolved(RetTy); + if (isa_and_nonnull(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(RetTy); return RetTy; } @@ -670,6 +672,8 @@ nullptr, Annotations) .release(); trackIfUnresolved(RetTy); + if (isa_and_nonnull(Scope)) + getSubprogramNodesTrackingVector(Scope).emplace_back(RetTy); return RetTy; } @@ -748,7 +752,10 @@ if (!Expr) Expr = createExpression(); auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr); - AllGVs.push_back(N); + if (isa_and_nonnull(Context)) + getSubprogramNodesTrackingVector(Context).emplace_back(N); + else + ModuleGVs.push_back(N); return N; } @@ -768,26 +775,20 @@ static DILocalVariable *createLocalVariable( LLVMContext &VMContext, - DenseMap> &PreservedVariables, - DIScope *Scope, StringRef Name, unsigned ArgNo, DIFile *File, + SmallVectorImpl &PreservedNodes, + DIScope *Context, 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)? - DIScope *Context = getNonCompileUnitScope(Scope); - - auto *Node = DILocalVariable::get( - VMContext, cast_or_null(Context), Name, File, LineNo, Ty, - ArgNo, Flags, AlignInBits, Annotations); + auto *Scope = cast(Context); + auto *Node = DILocalVariable::get(VMContext, Scope, 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. - DISubprogram *Fn = getDISubprogram(Scope); - assert(Fn && "Missing subprogram for local variable"); - PreservedVariables[Fn].emplace_back(Node); + PreservedNodes.emplace_back(Node); } return Node; } @@ -797,9 +798,11 @@ DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, uint32_t AlignInBits) { - return createLocalVariable(VMContext, PreservedVariables, Scope, Name, - /* ArgNo */ 0, File, LineNo, Ty, AlwaysPreserve, - Flags, 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); } DILocalVariable *DIBuilder::createParameterVariable( @@ -807,25 +810,23 @@ unsigned LineNo, DIType *Ty, bool AlwaysPreserve, DINode::DIFlags Flags, DINodeArray Annotations) { assert(ArgNo && "Expected non-zero argument number for parameter"); - return createLocalVariable(VMContext, PreservedVariables, Scope, Name, ArgNo, - File, LineNo, Ty, AlwaysPreserve, Flags, - /*AlignInBits=*/0, Annotations); + 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); } -DILabel *DIBuilder::createLabel(DIScope *Scope, StringRef Name, DIFile *File, +DILabel *DIBuilder::createLabel(DIScope *Context, StringRef Name, DIFile *File, unsigned LineNo, bool AlwaysPreserve) { - DIScope *Context = getNonCompileUnitScope(Scope); - - auto *Node = DILabel::get(VMContext, cast_or_null(Context), - Name, File, LineNo); + auto *Scope = cast(Context); + auto *Node = DILabel::get(VMContext, Scope, 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. - DISubprogram *Fn = getDISubprogram(Scope); - assert(Fn && "Missing subprogram for label"); - PreservedLabels[Fn].emplace_back(Node); + getSubprogramNodesTrackingVector(Scope).emplace_back(Node); } return Node; } @@ -852,9 +853,8 @@ 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, - Annotations, TargetFuncName); + SPFlags, IsDefinition ? CUNode : nullptr, TParams, Decl, nullptr, + ThrownTypes, Annotations, TargetFuncName); if (IsDefinition) AllSubprograms.push_back(Node); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1319,9 +1319,12 @@ auto *Node = dyn_cast(RawNode); CheckDI(Node, "invalid retained nodes list", &N, RawNode); for (Metadata *Op : Node->operands()) { - CheckDI(Op && (isa(Op) || isa(Op)), - "invalid retained nodes, expected DILocalVariable or DILabel", &N, - Node, Op); + CheckDI(Op && (isa(Op) || isa(Op) || + isa(Op) || isa(Op) || + isa(Op)), + "invalid retained nodes, expected DIGlobalVariableExpression, " + "DIType, DIImportedEntity, DILocalVariable or DILabel", + &N, Node, Op); } } CheckDI(!hasConflictingReferenceFlags(N.getFlags()), diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1188,40 +1188,7 @@ // only a few imported entities into every destination module may be very // size inefficient. CU->replaceGlobalVariables(nullptr); - - // Imported entities only need to be mapped in if they have local - // scope, as those might correspond to an imported entity inside a - // function being imported (any locally scoped imported entities that - // don't end up referenced by an imported function will not be emitted - // into the object). Imported entities not in a local scope - // (e.g. on the namespace) only need to be emitted by the originating - // module. Create a list of the locally scoped imported entities, and - // replace the source CUs imported entity list with the new list, so - // only those are mapped in. - // FIXME: Locally-scoped imported entities could be moved to the - // functions they are local to instead of listing them on the CU, and - // we would naturally only link in those needed by function importing. - SmallVector AllImportedModules; - bool ReplaceImportedEntities = false; - for (auto *IE : CU->getImportedEntities()) { - DIScope *Scope = IE->getScope(); - assert(Scope && "Invalid Scope encoding!"); - if (isa(Scope)) - AllImportedModules.emplace_back(IE); - else - ReplaceImportedEntities = true; - } - if (ReplaceImportedEntities) { - if (!AllImportedModules.empty()) - CU->replaceImportedEntities(MDTuple::get( - CU->getContext(), - SmallVector(AllImportedModules.begin(), - AllImportedModules.end()))); - else - // If there were no local scope imported entities, we can map - // the whole list to nullptr. - CU->replaceImportedEntities(nullptr); - } + CU->replaceImportedEntities(nullptr); } } diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp --- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp +++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp @@ -237,7 +237,7 @@ if (SP && SP->isDefinition()) { for (DIType *Ty: SP->getType()->getTypeArray()) CheckAnonRecordType(nullptr, Ty); - for (const DINode *DN : SP->getRetainedNodes()) { + for (const MDNode *DN : SP->getRetainedNodes()) { if (const auto *DV = dyn_cast(DN)) CheckAnonRecordType(nullptr, DV->getType()); } diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -1160,7 +1160,7 @@ // Use RetainedNodes so we can collect all argument names // even if the argument is not used. std::unordered_map FuncArgNames; - for (const DINode *DN : SP->getRetainedNodes()) { + for (const auto *DN : SP->getRetainedNodes()) { if (const auto *DV = dyn_cast(DN)) { // Collect function arguments for subprogram func type. uint32_t Arg = DV->getArg(); @@ -1182,7 +1182,7 @@ uint32_t FuncTypeId = addType(std::move(FuncTypeEntry)); // Process argument annotations. - for (const DINode *DN : SP->getRetainedNodes()) { + for (const auto *DN : SP->getRetainedNodes()) { if (const auto *DV = dyn_cast(DN)) { uint32_t Arg = DV->getArg(); if (Arg) diff --git a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp --- a/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -954,6 +954,7 @@ /*Decl=*/nullptr, /*TemplateParams=*/nullptr, /*AlignInBits=*/0, Annotations); CounterPtr->addDebugInfo(DICounter); + DB.finalizeSubprogram(SP); DB.finalize(); } else { std::string Msg = ("Missing debug info for function " + Fn->getName() + diff --git a/llvm/lib/Transforms/Utils/Debugify.cpp b/llvm/lib/Transforms/Utils/Debugify.cpp --- a/llvm/lib/Transforms/Utils/Debugify.cpp +++ b/llvm/lib/Transforms/Utils/Debugify.cpp @@ -315,7 +315,7 @@ DebugInfoBeforePass.DIFunctions.insert({&F, SP}); if (SP) { LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n'); - for (const DINode *DN : SP->getRetainedNodes()) { + for (const auto *DN : SP->getRetainedNodes()) { if (const auto *DV = dyn_cast(DN)) { DebugInfoBeforePass.DIVariables[DV] = 0; } @@ -554,7 +554,7 @@ if (SP) { LLVM_DEBUG(dbgs() << " Collecting subprogram: " << *SP << '\n'); - for (const DINode *DN : SP->getRetainedNodes()) { + for (const auto *DN : SP->getRetainedNodes()) { if (const auto *DV = dyn_cast(DN)) { DebugInfoAfterPass.DIVariables[DV] = 0; } diff --git a/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll b/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll --- a/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll +++ b/llvm/test/CodeGen/AArch64/arm64-2011-03-17-AsmPrinterCrash.ll @@ -28,12 +28,12 @@ !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!9, !10} -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2) +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug) !1 = !DIFile(filename: "print.i", directory: "/Volumes/Ebi/echeng/radars/r9146594") !2 = !{!3} !3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) !4 = !DIGlobalVariable(name: "vsplive", scope: !5, file: !1, line: 617, type: !8, isLocal: true, isDefinition: true) -!5 = distinct !DISubprogram(name: "drt_vsprintf", scope: !1, file: !1, line: 616, type: !6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0) +!5 = distinct !DISubprogram(name: "drt_vsprintf", scope: !1, file: !1, line: 616, type: !6, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) !6 = !DISubroutineType(types: !7) !7 = !{!8} !8 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll --- a/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll +++ b/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll @@ -101,14 +101,14 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8) +!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29) !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug") !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !8 = !{} -!9 = !{!0, !10} +!9 = !{!10} !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true) !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13) @@ -128,3 +128,4 @@ !26 = !{!"short", !22, i64 0} !27 = !DILocation(line: 4, column: 12, scope: !2) !28 = !DILocation(line: 4, column: 3, scope: !2) +!29 = !{!0} diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll b/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll --- a/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll +++ b/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll @@ -101,14 +101,14 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8) +!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29) !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug") !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !8 = !{} -!9 = !{!0, !10} +!9 = !{!10} !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true) !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13) @@ -128,3 +128,4 @@ !26 = !{!"short", !22, i64 0} !27 = !DILocation(line: 4, column: 12, scope: !2) !28 = !DILocation(line: 4, column: 3, scope: !2) +!29 = !{!0} diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll --- a/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll +++ b/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll @@ -107,14 +107,14 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !15, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8) +!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !31) !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug") !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !8 = !{} -!9 = !{!0, !10} +!9 = !{!10} !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true) !12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13) @@ -136,3 +136,4 @@ !28 = !{!"short", !24, i64 0} !29 = !DILocation(line: 4, column: 12, scope: !2) !30 = !DILocation(line: 4, column: 3, scope: !2) +!31 = !{!0} diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll b/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll --- a/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll +++ b/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll @@ -107,14 +107,14 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !15, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8) +!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !31) !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug") !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !8 = !{} -!9 = !{!0, !10} +!9 = !{!10} !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true) !12 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !13) @@ -136,3 +136,4 @@ !28 = !{!"short", !24, i64 0} !29 = !DILocation(line: 4, column: 12, scope: !2) !30 = !DILocation(line: 4, column: 3, scope: !2) +!31 = !{!0} diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll --- a/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll +++ b/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll @@ -101,14 +101,14 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8) +!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29) !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug") !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !8 = !{} -!9 = !{!0, !10} +!9 = !{!10} !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true) !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13) @@ -128,3 +128,4 @@ !26 = !{!"short", !22, i64 0} !27 = !DILocation(line: 4, column: 12, scope: !2) !28 = !DILocation(line: 4, column: 3, scope: !2) +!29 = !{!0} diff --git a/llvm/test/CodeGen/BPF/BTF/static-var.ll b/llvm/test/CodeGen/BPF/BTF/static-var.ll --- a/llvm/test/CodeGen/BPF/BTF/static-var.ll +++ b/llvm/test/CodeGen/BPF/BTF/static-var.ll @@ -101,14 +101,14 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "b", scope: !2, file: !3, line: 3, type: !14, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !8) +!2 = distinct !DISubprogram(name: "foo", scope: !3, file: !3, line: 2, type: !4, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !7, retainedNodes: !29) !3 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/llvm/bug") !4 = !DISubroutineType(types: !5) !5 = !{!6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) !7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9, nameTableKind: None) !8 = !{} -!9 = !{!0, !10} +!9 = !{!10} !10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) !11 = distinct !DIGlobalVariable(name: "a", scope: !7, file: !3, line: 1, type: !12, isLocal: true, isDefinition: true) !12 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !13) @@ -128,3 +128,4 @@ !26 = !{!"short", !22, i64 0} !27 = !DILocation(line: 4, column: 12, scope: !2) !28 = !DILocation(line: 4, column: 3, scope: !2) +!29 = !{!0} diff --git a/llvm/test/CodeGen/BPF/dwarfdump.ll b/llvm/test/CodeGen/BPF/dwarfdump.ll --- a/llvm/test/CodeGen/BPF/dwarfdump.ll +++ b/llvm/test/CodeGen/BPF/dwarfdump.ll @@ -37,10 +37,9 @@ !4 = !DISubroutineType(types: !5) !5 = !{!6, !6, !6} !6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 4.0.0 (trunk 287518) (llvm/trunk 287520)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, globals: !9) +!7 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 4.0.0 (trunk 287518) (llvm/trunk 287520)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !8) !8 = !{} -!9 = !{!0} -!10 = !{!11, !12} +!10 = !{!0, !11, !12} !11 = !DILocalVariable(name: "myvar_a", arg: 1, scope: !2, file: !3, line: 1, type: !6) !12 = !DILocalVariable(name: "myvar_b", arg: 2, scope: !2, file: !3, line: 1, type: !6) !13 = !{i32 2, !"Dwarf Version", i32 4} diff --git a/llvm/test/CodeGen/PowerPC/pr24546.ll b/llvm/test/CodeGen/PowerPC/pr24546.ll --- a/llvm/test/CodeGen/PowerPC/pr24546.ll +++ b/llvm/test/CodeGen/PowerPC/pr24546.ll @@ -56,7 +56,7 @@ !llvm.module.flags = !{!29, !30} !llvm.ident = !{!31} -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3, globals: !23) +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !3) !1 = !DIFile(filename: "testcase.i", directory: "/tmp/glibc.build") !2 = !{} !3 = !{!4} @@ -76,9 +76,8 @@ !18 = distinct !DISubprogram(name: "php_intpow10", scope: !1, file: !1, line: 1, type: !19, isLocal: true, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, retainedNodes: !21) !19 = !DISubroutineType(types: !20) !20 = !{!4, !9} -!21 = !{!22} +!21 = !{!22, !24} !22 = !DILocalVariable(name: "power", arg: 1, scope: !18, file: !1, line: 1, type: !9) -!23 = !{!24} !24 = !DIGlobalVariableExpression(var: !DIGlobalVariable(name: "powers", scope: !18, file: !1, line: 3, type: !25, isLocal: true, isDefinition: true), expr: !DIExpression()) !25 = !DICompositeType(tag: DW_TAG_array_type, baseType: !26, size: 1472, align: 64, elements: !27) !26 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !4) diff --git a/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll b/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll --- a/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll +++ b/llvm/test/CodeGen/X86/dbg-distringtype-uint.ll @@ -74,10 +74,9 @@ !5 = !DISubroutineType(types: !6) !6 = !{!7} !7 = !DIStringType(name: "CHARACTER_0", size: 64) -!8 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2745", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, globals: !10, splitDebugInlining: false, nameTableKind: None) +!8 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2745", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, splitDebugInlining: false, nameTableKind: None) !9 = !{} -!10 = !{!0} -!11 = !{!12, !14} +!11 = !{!0, !12, !14} !12 = !DILocalVariable(name: "esym", arg: 1, scope: !2, file: !3, line: 15, type: !13, flags: DIFlagArtificial) !13 = !DIStringType(name: "CHARACTER_1", size: 64) !14 = !DILocalVariable(name: "i", arg: 2, scope: !2, file: !3, line: 15, type: !15) diff --git a/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll b/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll --- a/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll +++ b/llvm/test/DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll @@ -14,13 +14,13 @@ !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!10} -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !3) +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.0 (trunk 139632)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, retainedTypes: !2) !1 = !DIFile(filename: "fb.c", directory: "/private/tmp") !2 = !{} !3 = !{!4} !4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression()) !5 = !DIGlobalVariable(name: "bar", scope: !6, file: !1, line: 2, type: !9, isLocal: true, isDefinition: true) -!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0) +!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, virtualIndex: 6, isOptimized: true, unit: !0, retainedNodes: !3) !7 = !DISubroutineType(types: !8) !8 = !{!9} !9 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) diff --git a/llvm/test/DebugInfo/Generic/import-inlined-declaration.ll b/llvm/test/DebugInfo/Generic/import-inlined-declaration.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/import-inlined-declaration.ll @@ -0,0 +1,73 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s +; REQUIRES: object-emission + +; namespace ns { +; inline __attribute__((always_inline)) +; void foo() { int a = 4; } +; } +; +; void goo() { +; using ns::foo; +; foo(); +; } + +; Ensure that imported declarations reference the correct subprograms even if +; those subprograms are inlined. + +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_namespace +; CHECK: DW_AT_name ("ns") +; CHECK: [[FOO:0x.*]]: DW_TAG_subprogram +; CHECK: DW_AT_name ("foo") +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: NULL +; CHECK: DW_TAG_base_type +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("goo") +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin ([[FOO]] +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: DW_TAG_imported_declaration +; CHECK: DW_AT_import ([[FOO]]) +; CHECK: NULL +; CHECK: NULL + +; Function Attrs: mustprogress noinline optnone uwtable +define dso_local void @_Z3goov() !dbg !4 { +entry: + %a.i = alloca i32, align 4 + call void @llvm.dbg.declare(metadata i32* %a.i, metadata !16, metadata !DIExpression()), !dbg !18 + store i32 4, i32* %a.i, align 4, !dbg !18 + ret void, !dbg !20 +} + +; Function Attrs: nofree nosync nounwind readnone speculatable willreturn +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!10, !11, !12, !13, !14} +!llvm.ident = !{!15} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "imported-inlined-declaration.cpp", directory: "") +!2 = !{!3} +!3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !8, file: !1, line: 7) +!4 = distinct !DISubprogram(name: "goo", linkageName: "_Z3goov", scope: !1, file: !1, line: 6, type: !5, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = !{} +!8 = distinct !DISubprogram(name: "foo", linkageName: "_ZN2ns3fooEv", scope: !9, file: !1, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !7) +!9 = !DINamespace(name: "ns", scope: null) +!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 14.0.0"} +!16 = !DILocalVariable(name: "a", scope: !8, file: !1, line: 3, type: !17) +!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!18 = !DILocation(line: 3, column: 18, scope: !8, inlinedAt: !19) +!19 = distinct !DILocation(line: 8, column: 2, scope: !4) +!20 = !DILocation(line: 9, column: 1, scope: !4) diff --git a/llvm/test/DebugInfo/Generic/imported-name-inlined.ll b/llvm/test/DebugInfo/Generic/imported-name-inlined.ll --- a/llvm/test/DebugInfo/Generic/imported-name-inlined.ll +++ b/llvm/test/DebugInfo/Generic/imported-name-inlined.ll @@ -13,21 +13,17 @@ ; Ensure that top level imported declarations don't produce an extra degenerate ; concrete subprogram definition. -; FIXME: imported entities should only be emitted to the abstract origin if one is present - ; CHECK: DW_TAG_compile_unit ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name ("f1") ; CHECK: DW_TAG_imported_declaration ; CHECK: NULL -; CHECK: DW_TAG_namespace -; CHECK: DW_TAG_subprogram -; CHECK: NULL ; CHECK: DW_TAG_subprogram ; CHECK: DW_AT_name ("f2") ; CHECK: DW_TAG_inlined_subroutine -; CHECK: DW_TAG_imported_declaration -; CHECK: NULL +; CHECK: NULL +; CHECK: DW_TAG_namespace +; CHECK: DW_TAG_subprogram ; CHECK: NULL ; CHECK: NULL @@ -44,12 +40,12 @@ !llvm.module.flags = !{!10, !11, !12} !llvm.ident = !{!13} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 (trunk 309061) (llvm/trunk 309076)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !3) +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 (trunk 309061) (llvm/trunk 309076)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) !1 = !DIFile(filename: "imported-name-inlined.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !2 = !{} !3 = !{!4} !4 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !5, entity: !8, file: !1, line: 5) -!5 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 4, type: !6, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) +!5 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 4, type: !6, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !3) !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = !DISubprogram(name: "f", linkageName: "_ZN2ns1fEv", scope: !9, file: !1, line: 2, type: !6, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false) diff --git a/llvm/test/DebugInfo/Generic/inlined-local-type.ll b/llvm/test/DebugInfo/Generic/inlined-local-type.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/inlined-local-type.ll @@ -0,0 +1,128 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-info - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s +; REQUIRES: object-emission + +; inline __attribute__((always_inline)) +; int removed() { struct A {int i;}; struct A a; return a.i++; } +; +; __attribute__((always_inline)) +; int not_removed() { struct B {int i;}; struct B b; return b.i++; } +; +; int foo() { return removed() + not_removed(); }} + +; Ensure that function-local types have the correct subprogram parent even if +; those subprograms are inlined. + +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_abstract_origin ({{0x.*}} "not_removed") +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("removed") +; CHECK: [[A:0x.*]]: DW_TAG_structure_type +; CHECK: DW_AT_name ("A") +; CHECK: DW_TAG_member +; CHECK: NULL +; CHECK: DW_TAG_variable +; CHECK: DW_AT_type ([[A]] "A") +; CHECK: NULL +; CHECK: DW_TAG_base_type +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("not_removed") +; CHECK: [[B:0x.*]]: DW_TAG_structure_type +; CHECK: DW_AT_name ("B") +; CHECK: DW_TAG_member +; CHECK: NULL +; CHECK: DW_TAG_variable +; CHECK: DW_AT_type ([[B]] "B") +; CHECK: NULL +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL + +%struct.B = type { i32 } +%struct.A = type { i32 } + +define dso_local i32 @not_removed() !dbg !12 { + %1 = alloca %struct.B, align 4 + call void @llvm.dbg.declare(metadata %struct.B* %1, metadata !18, metadata !DIExpression()), !dbg !22 + %2 = getelementptr inbounds %struct.B, %struct.B* %1, i32 0, i32 0, !dbg !23 + %3 = load i32, i32* %2, align 4, !dbg !24 + %4 = add nsw i32 %3, 1, !dbg !24 + store i32 %4, i32* %2, align 4, !dbg !24 + ret i32 %3, !dbg !25 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +define dso_local i32 @foo() !dbg !26 { + %1 = alloca %struct.A, align 4 + %2 = alloca %struct.B, align 4 + call void @llvm.dbg.declare(metadata %struct.A* %1, metadata !27, metadata !DIExpression()), !dbg !32 + %3 = getelementptr inbounds %struct.A, %struct.A* %1, i32 0, i32 0, !dbg !34 + %4 = load i32, i32* %3, align 4, !dbg !35 + %5 = add nsw i32 %4, 1, !dbg !35 + store i32 %5, i32* %3, align 4, !dbg !35 + call void @llvm.dbg.declare(metadata %struct.B* %2, metadata !18, metadata !DIExpression()), !dbg !36 + %6 = getelementptr inbounds %struct.B, %struct.B* %2, i32 0, i32 0, !dbg !38 + %7 = load i32, i32* %6, align 4, !dbg !39 + %8 = add nsw i32 %7, 1, !dbg !39 + store i32 %8, i32* %6, align 4, !dbg !39 + %9 = add nsw i32 %4, %7, !dbg !40 + ret i32 %9, !dbg !41 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8, !9, !10} +!llvm.ident = !{!11} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "inlined-local-type.cpp", directory: "") +!2 = !{i32 7, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 1, !"branch-target-enforcement", i32 0} +!6 = !{i32 1, !"sign-return-address", i32 0} +!7 = !{i32 1, !"sign-return-address-all", i32 0} +!8 = !{i32 1, !"sign-return-address-with-bkey", i32 0} +!9 = !{i32 7, !"uwtable", i32 1} +!10 = !{i32 7, !"frame-pointer", i32 1} +!11 = !{!"clang version 14.0.0"} +!12 = distinct !DISubprogram(name: "not_removed", scope: !13, file: !13, line: 5, type: !14, scopeLine: 5, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !43) +!13 = !DIFile(filename: "inlined-local-type.cpp", directory: "") +!14 = !DISubroutineType(types: !15) +!15 = !{!16} +!16 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!17 = !{} +!18 = !DILocalVariable(name: "b", scope: !12, file: !13, line: 5, type: !19) +!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", scope: !12, file: !13, line: 5, size: 32, elements: !20) +!20 = !{!21} +!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !13, line: 5, baseType: !16, size: 32) +!22 = !DILocation(line: 5, column: 49, scope: !12) +!23 = !DILocation(line: 5, column: 61, scope: !12) +!24 = !DILocation(line: 5, column: 62, scope: !12) +!25 = !DILocation(line: 5, column: 52, scope: !12) +!26 = distinct !DISubprogram(name: "foo", scope: !13, file: !13, line: 7, type: !14, scopeLine: 7, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !17) +!27 = !DILocalVariable(name: "a", scope: !28, file: !13, line: 2, type: !29) +!28 = distinct !DISubprogram(name: "removed", scope: !13, file: !13, line: 2, type: !14, scopeLine: 2, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !42) +!29 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", scope: !28, file: !13, line: 2, size: 32, elements: !30) +!30 = !{!31} +!31 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !29, file: !13, line: 2, baseType: !16, size: 32) +!32 = !DILocation(line: 2, column: 45, scope: !28, inlinedAt: !33) +!33 = distinct !DILocation(line: 7, column: 20, scope: !26) +!34 = !DILocation(line: 2, column: 57, scope: !28, inlinedAt: !33) +!35 = !DILocation(line: 2, column: 58, scope: !28, inlinedAt: !33) +!36 = !DILocation(line: 5, column: 49, scope: !12, inlinedAt: !37) +!37 = distinct !DILocation(line: 7, column: 32, scope: !26) +!38 = !DILocation(line: 5, column: 61, scope: !12, inlinedAt: !37) +!39 = !DILocation(line: 5, column: 62, scope: !12, inlinedAt: !37) +!40 = !DILocation(line: 7, column: 30, scope: !26) +!41 = !DILocation(line: 7, column: 13, scope: !26) +!42 = !{!29} +!43 = !{!19} diff --git a/llvm/test/DebugInfo/Generic/inlined-static-var.ll b/llvm/test/DebugInfo/Generic/inlined-static-var.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/inlined-static-var.ll @@ -0,0 +1,94 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-info - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s +; REQUIRES: object-emission + +; inline __attribute__((always_inline)) +; int removed() { static int A; return A++; } +; +; __attribute__((always_inline)) +; int not_removed() { static int B; return B++; } +; +; int foo() { return removed() + not_removed(); } + +; Ensure that global variables belong to the correct subprograms even if those +; subprograms are inlined. + +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_abstract_origin {{.*}} "_Z11not_removedv" +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("removed") +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("A") +; CHECK: NULL +; CHECK: DW_TAG_base_type +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("not_removed") +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("B") +; CHECK: NULL +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("foo") +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_inlined_subroutine +; CHECK: NULL +; CHECK: NULL + +@_ZZ11not_removedvE1A = internal global i32 0, align 4, !dbg !0 +@_ZZ7removedvE1A = linkonce_odr dso_local global i32 0, align 4, !dbg !10 + +define dso_local i32 @_Z11not_removedv() !dbg !2 { + %1 = load i32, i32* @_ZZ11not_removedvE1A, align 4, !dbg !24 + %2 = add nsw i32 %1, 1, !dbg !24 + store i32 %2, i32* @_ZZ11not_removedvE1A, align 4, !dbg !24 + ret i32 %1, !dbg !25 +} + +define dso_local i32 @_Z3foov() !dbg !26 { + %1 = load i32, i32* @_ZZ7removedvE1A, align 4, !dbg !27 + %2 = add nsw i32 %1, 1, !dbg !27 + store i32 %2, i32* @_ZZ7removedvE1A, align 4, !dbg !27 + %3 = load i32, i32* @_ZZ11not_removedvE1A, align 4, !dbg !29 + %4 = add nsw i32 %3, 1, !dbg !29 + store i32 %4, i32* @_ZZ11not_removedvE1A, align 4, !dbg !29 + %5 = add nsw i32 %1, %3, !dbg !31 + ret i32 %5, !dbg !32 +} + +!llvm.dbg.cu = !{!7} +!llvm.module.flags = !{!14, !15, !16, !17, !18, !19, !20, !21, !22} +!llvm.ident = !{!23} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "B", scope: !2, file: !3, line: 5, type: !6, isLocal: true, isDefinition: true) +!2 = distinct !DISubprogram(name: "not_removed", linkageName: "_Z11not_removedv", scope: !3, file: !3, line: 5, type: !4, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !9) +!3 = !DIFile(filename: "example.cpp", directory: "") +!4 = !DISubroutineType(types: !5) +!5 = !{!6} +!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!7 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !8, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!8 = !DIFile(filename: "example.cpp", directory: "") +!9 = !{!0} +!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) +!11 = distinct !DIGlobalVariable(name: "A", scope: !12, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true) +!12 = distinct !DISubprogram(name: "removed", linkageName: "_Z7removedv", scope: !3, file: !3, line: 2, type: !4, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !33) +!13 = !{} +!14 = !{i32 7, !"Dwarf Version", i32 4} +!15 = !{i32 2, !"Debug Info Version", i32 3} +!16 = !{i32 1, !"wchar_size", i32 4} +!17 = !{i32 1, !"branch-target-enforcement", i32 0} +!18 = !{i32 1, !"sign-return-address", i32 0} +!19 = !{i32 1, !"sign-return-address-all", i32 0} +!20 = !{i32 1, !"sign-return-address-with-bkey", i32 0} +!21 = !{i32 7, !"uwtable", i32 1} +!22 = !{i32 7, !"frame-pointer", i32 1} +!23 = !{!"clang version 14.0.0"} +!24 = !DILocation(line: 5, column: 43, scope: !2) +!25 = !DILocation(line: 5, column: 35, scope: !2) +!26 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 7, type: !4, scopeLine: 7, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !7, retainedNodes: !13) +!27 = !DILocation(line: 2, column: 39, scope: !12, inlinedAt: !28) +!28 = distinct !DILocation(line: 7, column: 20, scope: !26) +!29 = !DILocation(line: 5, column: 43, scope: !2, inlinedAt: !30) +!30 = distinct !DILocation(line: 7, column: 32, scope: !26) +!31 = !DILocation(line: 7, column: 30, scope: !26) +!32 = !DILocation(line: 7, column: 13, scope: !26) +!33 = !{!10} diff --git a/llvm/test/DebugInfo/Generic/lexical-block-retained-types.ll b/llvm/test/DebugInfo/Generic/lexical-block-retained-types.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/lexical-block-retained-types.ll @@ -0,0 +1,51 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s + +; Test that retained unused (unreferenced) types emitted correctly. + +; Compiled from +; $ clang -cc1 -debug-info-kind=unused-types test.cpp -emit-llvm + +; void test_unused() { +; struct Y {}; +; { +; struct X {}; +; } +; } + +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("test_unused") +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("Y") +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("X") +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL + +define dso_local void @_Z11test_unusedv() !dbg !5 { +entry: + ret void, !dbg !16 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!13, !14} +!llvm.ident = !{!15} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "", directory: "/") +!2 = !{!3, !10} +!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Y", scope: !5, file: !4, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !8) +!4 = !DIFile(filename: "test.cpp", directory: "/") +!5 = distinct !DISubprogram(name: "test_unused", linkageName: "_Z11test_unusedv", scope: !4, file: !4, line: 1, type: !6, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !9) +!6 = !DISubroutineType(types: !7) +!7 = !{null} +!8 = !{} +!9 = !{!3, !10} +!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "X", scope: !11, file: !4, line: 4, size: 8, flags: DIFlagTypePassByValue, elements: !8) +!11 = distinct !DILexicalBlock(scope: !5, file: !4, line: 3, column: 3) +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 15.0.0"} +!16 = !DILocation(line: 6, column: 1, scope: !5) diff --git a/llvm/test/DebugInfo/Generic/lexical-block-static-var.ll b/llvm/test/DebugInfo/Generic/lexical-block-static-var.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/lexical-block-static-var.ll @@ -0,0 +1,144 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-info - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s +; REQUIRES: object-emission + +; inline __attribute__((always_inline)) +; int removed() { +; { +; static int A; +; return A++; +; } +; } +; +; __attribute__((always_inline)) +; int not_removed() { +; { +; static int B; +; return B++; +; } +; } +; +; int foo() { +; { +; static int C; +; return ++C + removed() + not_removed(); +; } +; } + +; CHECK: DW_TAG_compile_unit + +; Out-of-line definition of `not_removed()`. +; The empty lexical block is created to match abstract origin. +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_abstract_origin {{.*}} "_Z11not_removedv" +; CHECK: DW_TAG_lexical_block +; CHECK: NULL + +; Abstract definition of `removed()` +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("removed") +; CHECK: DW_AT_inline (DW_INL_inlined) +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("A") +; CHECK: DW_AT_location (DW_OP_addr 0x0) +; CHECK: NULL +; CHECK: NULL +; CHECK: DW_TAG_base_type + +; Abstract definition of `not_removed()` +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("not_removed") +; CHECK: DW_AT_inline (DW_INL_inlined) +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("B") +; CHECK: DW_AT_location (DW_OP_addr 0x0) +; CHECK: NULL +; CHECK: NULL + +; Definition of foo(). +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("foo") +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_lexical_block +; CHECK: NULL +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_TAG_lexical_block +; CHECK: NULL +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("C") +; CHECK: DW_AT_location (DW_OP_addr 0x0) +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL + +@_ZZ11not_removedvE1B = internal global i32 0, align 4, !dbg !0 +@_ZZ3foovE1C = internal global i32 0, align 4, !dbg !10 +@_ZZ7removedvE1A = linkonce_odr dso_local global i32 0, align 4, !dbg !15 + +define dso_local i32 @_Z11not_removedv() !dbg !4 { +entry: + %0 = load i32, i32* @_ZZ11not_removedvE1B, align 4, !dbg !25 + %inc = add nsw i32 %0, 1, !dbg !25 + store i32 %inc, i32* @_ZZ11not_removedvE1B, align 4, !dbg !25 + ret i32 %0, !dbg !26 +} + +define dso_local i32 @_Z3foov() !dbg !13 { +entry: + %0 = load i32, i32* @_ZZ3foovE1C, align 4, !dbg !27 + %inc = add nsw i32 %0, 1, !dbg !27 + store i32 %inc, i32* @_ZZ3foovE1C, align 4, !dbg !27 + %1 = load i32, i32* @_ZZ7removedvE1A, align 4, !dbg !28 + %inc.i3 = add nsw i32 %1, 1, !dbg !28 + store i32 %inc.i3, i32* @_ZZ7removedvE1A, align 4, !dbg !28 + %add = add nsw i32 %inc, %1, !dbg !30 + %2 = load i32, i32* @_ZZ11not_removedvE1B, align 4, !dbg !31 + %inc.i = add nsw i32 %2, 1, !dbg !31 + store i32 %inc.i, i32* @_ZZ11not_removedvE1B, align 4, !dbg !31 + %add2 = add nsw i32 %add, %2, !dbg !33 + ret i32 %add2, !dbg !34 +} + +!llvm.dbg.cu = !{!8} +!llvm.module.flags = !{!19, !20, !21, !22, !23} +!llvm.ident = !{!24} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "B", scope: !2, file: !3, line: 13, type: !7, isLocal: true, isDefinition: true) +!2 = distinct !DILexicalBlock(scope: !4, file: !3, line: 12, column: 3) +!3 = !DIFile(filename: "test_static.cpp", directory: "/") +!4 = distinct !DISubprogram(name: "not_removed", linkageName: "_Z11not_removedv", scope: !3, file: !3, line: 11, type: !5, scopeLine: 11, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !35) +!5 = !DISubroutineType(types: !6) +!6 = !{!7} +!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!9 = !{!15} +!10 = !DIGlobalVariableExpression(var: !11, expr: !DIExpression()) +!11 = distinct !DIGlobalVariable(name: "C", scope: !12, file: !3, line: 20, type: !7, isLocal: true, isDefinition: true) +!12 = distinct !DILexicalBlock(scope: !13, file: !3, line: 19, column: 3) +!13 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 18, type: !5, scopeLine: 18, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !36) +!14 = !{} +!15 = !DIGlobalVariableExpression(var: !16, expr: !DIExpression()) +!16 = distinct !DIGlobalVariable(name: "A", scope: !17, file: !3, line: 5, type: !7, isLocal: false, isDefinition: true) +!17 = distinct !DILexicalBlock(scope: !18, file: !3, line: 4, column: 3) +!18 = distinct !DISubprogram(name: "removed", linkageName: "_Z7removedv", scope: !3, file: !3, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !8, retainedNodes: !9) +!19 = !{i32 7, !"Dwarf Version", i32 4} +!20 = !{i32 2, !"Debug Info Version", i32 3} +!21 = !{i32 1, !"wchar_size", i32 4} +!22 = !{i32 7, !"uwtable", i32 1} +!23 = !{i32 7, !"frame-pointer", i32 2} +!24 = !{!"clang version 14.0.0"} +!25 = !DILocation(line: 14, column: 13, scope: !2) +!26 = !DILocation(line: 14, column: 5, scope: !2) +!27 = !DILocation(line: 21, column: 12, scope: !12) +!28 = !DILocation(line: 6, column: 13, scope: !17, inlinedAt: !29) +!29 = distinct !DILocation(line: 21, column: 18, scope: !12) +!30 = !DILocation(line: 21, column: 16, scope: !12) +!31 = !DILocation(line: 14, column: 13, scope: !2, inlinedAt: !32) +!32 = distinct !DILocation(line: 21, column: 30, scope: !12) +!33 = !DILocation(line: 21, column: 28, scope: !12) +!34 = !DILocation(line: 21, column: 5, scope: !12) +!35 = !{!0} +!36 = !{!10} diff --git a/llvm/test/DebugInfo/Generic/lexical-block-types.ll b/llvm/test/DebugInfo/Generic/lexical-block-types.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/lexical-block-types.ll @@ -0,0 +1,425 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump -debug-info - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s +; REQUIRES: object-emission + +; inline __attribute__((always_inline)) +; void removed() { +; struct A1 { int i; }; +; typedef int Int1; +; { +; struct I1 { Int1 j; }; +; struct C1 { typedef char Char1; Char1 c; }; +; A1 a1; a1.i++; +; { +; I1 i1; i1.j++; +; C1 c1; c1.c++; +; } +; } +; } +; +; __attribute__((always_inline)) +; void not_removed() { +; struct A2 { int i; }; +; typedef int Int2; +; { +; struct I2 { Int2 j; }; +; struct C2 { typedef char Char2; Char2 c; }; +; A2 a2; a2.i++; +; { +; I2 i2; i2.j++; +; C2 c2; c2.c++; +; } +; } +; } +; +; void foo() { +; struct A3 { int i; }; +; typedef int Int3; +; { +; struct I3 { Int3 j; }; +; { +; struct C3 { typedef char Char3; Char3 c; }; +; A3 a3; a3.i++; +; { +; I3 i3; i3.j++; +; C3 c3; c3.c++; +; } +; } +; } +; removed(); +; not_removed(); +; } +; +; CHECK: DW_TAG_compile_unit + +; Out-of-line definition of `not_removed()` shouldn't contain any debug info for types. +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_abstract_origin {{.*}} "_Z11not_removedv" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "a2" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "i2" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "c2" +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL + +; Abstract definition of `removed()`. +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("removed") +; CHECK: DW_AT_inline (DW_INL_inlined) + +; I1 and C1 defined in the first lexical block, typedef Char1 is a child of C1. +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("a1") +; CHECK: DW_AT_type {{.*}} "A1" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_type {{.*}} "I1" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_type {{.*}} "C1" +; CHECK: NULL +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("I1") +; CHECK: DW_TAG_member +; CHECK: DW_AT_type {{.*}} "Int1" +; CHECK: NULL +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("C1") +; CHECK: DW_TAG_member +; CHECK: DW_AT_type {{.*}} "C1::Char1" +; CHECK: DW_TAG_typedef +; CHECK: DW_AT_name ("Char1") +; CHECK: NULL +; CHECK: NULL + +; A1 and typedef Int1 defined in the subprogram scope. +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("A1") +; CHECK: DW_TAG_member +; CHECK: NULL +; CHECK: DW_TAG_typedef +; CHECK: DW_AT_name ("Int1") +; CHECK: NULL + +; CHECK: DW_TAG_base_type +; CHECK: DW_TAG_base_type + +; Abstract definition of `not_removed()`. +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("not_removed") +; CHECK: DW_AT_inline (DW_INL_inlined) + +; I2 and C2 defined in the first lexical block, typedef Char2 is a child of C2. +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("a2") +; CHECK: DW_AT_type {{.*}} "A2" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("i2") +; CHECK: DW_AT_type {{.*}} "I2" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("c2") +; CHECK: DW_AT_type {{.*}} "C2" +; CHECK: NULL +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("I2") +; CHECK: DW_TAG_member +; CHECK: DW_AT_type {{.*}} "Int2" +; CHECK: NULL +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("C2") +; CHECK: DW_TAG_member +; CHECK: DW_AT_type {{.*}} "C2::Char2" +; CHECK: DW_TAG_typedef +; CHECK: DW_AT_name ("Char2") +; CHECK: NULL +; CHECK: NULL + +; A2 and typedef Int2 defined in subprogram scope. +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("A2") +; CHECK: DW_TAG_member +; CHECK: NULL +; CHECK: DW_TAG_typedef +; CHECK: DW_AT_name ("Int2") +; CHECK: NULL + +; Definition of `foo()`. +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("foo") + +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("a3") +; CHECK: DW_AT_type {{.*}} "A3" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("i3") +; CHECK: DW_AT_type {{.*}} "I3" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("c3") +; CHECK: DW_AT_type {{.*}} "C3" +; CHECK: NULL + +; C3 has the inner lexical block scope, typedef Char3 is a child of C3. +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("C3") +; CHECK: DW_TAG_member +; CHECK: DW_AT_type {{.*}} "C3::Char3" +; CHECK: DW_TAG_typedef +; CHECK: DW_AT_name ("Char3") +; CHECK: NULL +; CHECK: NULL + +; I3 has the outer lexical block scope. +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("I3") +; CHECK: DW_TAG_member +; CHECK: DW_AT_type {{.*}} "Int3" +; CHECK: NULL +; CHECK: NULL + +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin {{.*}} "_Z7removedv" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL + +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin {{.*}} "_Z11not_removedv" +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_variable +; CHECK: DW_TAG_variable +; CHECK: NULL +; CHECK: NULL +; CHECK: NULL + +; A3 and Int3 defined within the subprogam scope. +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("A3") +; CHECK: DW_TAG_member +; CHECK: NULL +; CHECK: DW_TAG_typedef +; CHECK: DW_AT_name ("Int3") +; CHECK: NULL +; CHECK: NULL + +%struct.A2 = type { i32 } +%struct.I2 = type { i32 } +%struct.C2 = type { i8 } +%struct.A1 = type { i32 } +%struct.I1 = type { i32 } +%struct.C1 = type { i8 } +%struct.A3 = type { i32 } +%struct.I3 = type { i32 } +%struct.C3 = type { i8 } + +define dso_local void @_Z11not_removedv() !dbg !8 { +entry: + %a2 = alloca %struct.A2, align 4 + %i2 = alloca %struct.I2, align 4 + %c2 = alloca %struct.C2, align 1 + call void @llvm.dbg.declare(metadata %struct.A2* %a2, metadata !12, metadata !DIExpression()), !dbg !18 + %i = getelementptr inbounds %struct.A2, %struct.A2* %a2, i32 0, i32 0, !dbg !19 + %0 = load i32, i32* %i, align 4, !dbg !20 + %inc = add nsw i32 %0, 1, !dbg !20 + store i32 %inc, i32* %i, align 4, !dbg !20 + call void @llvm.dbg.declare(metadata %struct.I2* %i2, metadata !21, metadata !DIExpression()), !dbg !27 + %j = getelementptr inbounds %struct.I2, %struct.I2* %i2, i32 0, i32 0, !dbg !28 + %1 = load i32, i32* %j, align 4, !dbg !29 + %inc1 = add nsw i32 %1, 1, !dbg !29 + store i32 %inc1, i32* %j, align 4, !dbg !29 + call void @llvm.dbg.declare(metadata %struct.C2* %c2, metadata !30, metadata !DIExpression()), !dbg !36 + %c = getelementptr inbounds %struct.C2, %struct.C2* %c2, i32 0, i32 0, !dbg !37 + %2 = load i8, i8* %c, align 1, !dbg !38 + %inc2 = add i8 %2, 1, !dbg !38 + store i8 %inc2, i8* %c, align 1, !dbg !38 + ret void, !dbg !39 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +define dso_local void @_Z3foov() !dbg !40 { +entry: + %a1.i = alloca %struct.A1, align 4 + %i1.i = alloca %struct.I1, align 4 + %c1.i = alloca %struct.C1, align 1 + %a2.i = alloca %struct.A2, align 4 + %i2.i = alloca %struct.I2, align 4 + %c2.i = alloca %struct.C2, align 1 + %a3 = alloca %struct.A3, align 4 + %i3 = alloca %struct.I3, align 4 + %c3 = alloca %struct.C3, align 1 + call void @llvm.dbg.declare(metadata %struct.A3* %a3, metadata !41, metadata !DIExpression()), !dbg !47 + %i = getelementptr inbounds %struct.A3, %struct.A3* %a3, i32 0, i32 0, !dbg !48 + %0 = load i32, i32* %i, align 4, !dbg !49 + %inc = add nsw i32 %0, 1, !dbg !49 + store i32 %inc, i32* %i, align 4, !dbg !49 + call void @llvm.dbg.declare(metadata %struct.I3* %i3, metadata !50, metadata !DIExpression()), !dbg !56 + %j = getelementptr inbounds %struct.I3, %struct.I3* %i3, i32 0, i32 0, !dbg !57 + %1 = load i32, i32* %j, align 4, !dbg !58 + %inc1 = add nsw i32 %1, 1, !dbg !58 + store i32 %inc1, i32* %j, align 4, !dbg !58 + call void @llvm.dbg.declare(metadata %struct.C3* %c3, metadata !59, metadata !DIExpression()), !dbg !64 + %c = getelementptr inbounds %struct.C3, %struct.C3* %c3, i32 0, i32 0, !dbg !65 + %2 = load i8, i8* %c, align 1, !dbg !66 + %inc2 = add i8 %2, 1, !dbg !66 + store i8 %inc2, i8* %c, align 1, !dbg !66 + call void @llvm.dbg.declare(metadata %struct.A1* %a1.i, metadata !67, metadata !DIExpression()), !dbg !73 + %i.i3 = getelementptr inbounds %struct.A1, %struct.A1* %a1.i, i32 0, i32 0, !dbg !75 + %3 = load i32, i32* %i.i3, align 4, !dbg !76 + %inc.i4 = add nsw i32 %3, 1, !dbg !76 + store i32 %inc.i4, i32* %i.i3, align 4, !dbg !76 + call void @llvm.dbg.declare(metadata %struct.I1* %i1.i, metadata !77, metadata !DIExpression()), !dbg !83 + %j.i5 = getelementptr inbounds %struct.I1, %struct.I1* %i1.i, i32 0, i32 0, !dbg !84 + %4 = load i32, i32* %j.i5, align 4, !dbg !85 + %inc1.i6 = add nsw i32 %4, 1, !dbg !85 + store i32 %inc1.i6, i32* %j.i5, align 4, !dbg !85 + call void @llvm.dbg.declare(metadata %struct.C1* %c1.i, metadata !86, metadata !DIExpression()), !dbg !91 + %c.i7 = getelementptr inbounds %struct.C1, %struct.C1* %c1.i, i32 0, i32 0, !dbg !92 + %5 = load i8, i8* %c.i7, align 1, !dbg !93 + %inc2.i8 = add i8 %5, 1, !dbg !93 + store i8 %inc2.i8, i8* %c.i7, align 1, !dbg !93 + call void @llvm.dbg.declare(metadata %struct.A2* %a2.i, metadata !12, metadata !DIExpression()), !dbg !94 + %i.i = getelementptr inbounds %struct.A2, %struct.A2* %a2.i, i32 0, i32 0, !dbg !96 + %6 = load i32, i32* %i.i, align 4, !dbg !97 + %inc.i = add nsw i32 %6, 1, !dbg !97 + store i32 %inc.i, i32* %i.i, align 4, !dbg !97 + call void @llvm.dbg.declare(metadata %struct.I2* %i2.i, metadata !21, metadata !DIExpression()), !dbg !98 + %j.i = getelementptr inbounds %struct.I2, %struct.I2* %i2.i, i32 0, i32 0, !dbg !99 + %7 = load i32, i32* %j.i, align 4, !dbg !100 + %inc1.i = add nsw i32 %7, 1, !dbg !100 + store i32 %inc1.i, i32* %j.i, align 4, !dbg !100 + call void @llvm.dbg.declare(metadata %struct.C2* %c2.i, metadata !30, metadata !DIExpression()), !dbg !101 + %c.i = getelementptr inbounds %struct.C2, %struct.C2* %c2.i, i32 0, i32 0, !dbg !102 + %8 = load i8, i8* %c.i, align 1, !dbg !103 + %inc2.i = add i8 %8, 1, !dbg !103 + store i8 %inc2.i, i8* %c.i, align 1, !dbg !103 + ret void, !dbg !104 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5, !6} +!llvm.ident = !{!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.cpp", directory: "/") +!2 = !{i32 7, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 4} +!5 = !{i32 7, !"uwtable", i32 1} +!6 = !{i32 7, !"frame-pointer", i32 2} +!7 = !{!"clang version 14.0.0"} +!8 = distinct !DISubprogram(name: "not_removed", linkageName: "_Z11not_removedv", scope: !1, file: !1, line: 17, type: !9, scopeLine: 17, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !105) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !{} +!12 = !DILocalVariable(name: "a2", scope: !13, file: !1, line: 23, type: !14) +!13 = distinct !DILexicalBlock(scope: !8, file: !1, line: 20, column: 3) +!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A2", scope: !8, file: !1, line: 18, size: 32, flags: DIFlagTypePassByValue, elements: !15) +!15 = !{!16} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !14, file: !1, line: 18, baseType: !17, size: 32) +!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!18 = !DILocation(line: 23, column: 8, scope: !13) +!19 = !DILocation(line: 23, column: 15, scope: !13) +!20 = !DILocation(line: 23, column: 16, scope: !13) +!21 = !DILocalVariable(name: "i2", scope: !22, file: !1, line: 25, type: !23) +!22 = distinct !DILexicalBlock(scope: !13, file: !1, line: 24, column: 5) +!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "I2", scope: !13, file: !1, line: 21, size: 32, flags: DIFlagTypePassByValue, elements: !24) +!24 = !{!25} +!25 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !23, file: !1, line: 21, baseType: !26, size: 32) +!26 = !DIDerivedType(tag: DW_TAG_typedef, name: "Int2", scope: !8, file: !1, line: 19, baseType: !17) +!27 = !DILocation(line: 25, column: 10, scope: !22) +!28 = !DILocation(line: 25, column: 17, scope: !22) +!29 = !DILocation(line: 25, column: 18, scope: !22) +!30 = !DILocalVariable(name: "c2", scope: !22, file: !1, line: 26, type: !31) +!31 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C2", scope: !13, file: !1, line: 22, size: 8, flags: DIFlagTypePassByValue, elements: !32) +!32 = !{!33} +!33 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !31, file: !1, line: 22, baseType: !34, size: 8) +!34 = !DIDerivedType(tag: DW_TAG_typedef, name: "Char2", scope: !31, file: !1, line: 22, baseType: !35) +!35 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char) +!36 = !DILocation(line: 26, column: 10, scope: !22) +!37 = !DILocation(line: 26, column: 17, scope: !22) +!38 = !DILocation(line: 26, column: 18, scope: !22) +!39 = !DILocation(line: 29, column: 1, scope: !8) +!40 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 31, type: !9, scopeLine: 31, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !107) +!41 = !DILocalVariable(name: "a3", scope: !42, file: !1, line: 38, type: !44) +!42 = distinct !DILexicalBlock(scope: !43, file: !1, line: 36, column: 5) +!43 = distinct !DILexicalBlock(scope: !40, file: !1, line: 34, column: 3) +!44 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A3", scope: !40, file: !1, line: 32, size: 32, flags: DIFlagTypePassByValue, elements: !45) +!45 = !{!46} +!46 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !44, file: !1, line: 32, baseType: !17, size: 32) +!47 = !DILocation(line: 38, column: 10, scope: !42) +!48 = !DILocation(line: 38, column: 17, scope: !42) +!49 = !DILocation(line: 38, column: 18, scope: !42) +!50 = !DILocalVariable(name: "i3", scope: !51, file: !1, line: 40, type: !52) +!51 = distinct !DILexicalBlock(scope: !42, file: !1, line: 39, column: 7) +!52 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "I3", scope: !43, file: !1, line: 35, size: 32, flags: DIFlagTypePassByValue, elements: !53) +!53 = !{!54} +!54 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !52, file: !1, line: 35, baseType: !55, size: 32) +!55 = !DIDerivedType(tag: DW_TAG_typedef, name: "Int3", scope: !40, file: !1, line: 33, baseType: !17) +!56 = !DILocation(line: 40, column: 12, scope: !51) +!57 = !DILocation(line: 40, column: 19, scope: !51) +!58 = !DILocation(line: 40, column: 20, scope: !51) +!59 = !DILocalVariable(name: "c3", scope: !51, file: !1, line: 41, type: !60) +!60 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C3", scope: !42, file: !1, line: 37, size: 8, flags: DIFlagTypePassByValue, elements: !61) +!61 = !{!62} +!62 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !60, file: !1, line: 37, baseType: !63, size: 8) +!63 = !DIDerivedType(tag: DW_TAG_typedef, name: "Char3", scope: !60, file: !1, line: 37, baseType: !35) +!64 = !DILocation(line: 41, column: 12, scope: !51) +!65 = !DILocation(line: 41, column: 19, scope: !51) +!66 = !DILocation(line: 41, column: 20, scope: !51) +!67 = !DILocalVariable(name: "a1", scope: !68, file: !1, line: 8, type: !70) +!68 = distinct !DILexicalBlock(scope: !69, file: !1, line: 5, column: 3) +!69 = distinct !DISubprogram(name: "removed", linkageName: "_Z7removedv", scope: !1, file: !1, line: 2, type: !9, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !110) +!70 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A1", scope: !69, file: !1, line: 3, size: 32, flags: DIFlagTypePassByValue, elements: !71, identifier: "_ZTSZ7removedvE2A1") +!71 = !{!72} +!72 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !70, file: !1, line: 3, baseType: !17, size: 32) +!73 = !DILocation(line: 8, column: 8, scope: !68, inlinedAt: !74) +!74 = distinct !DILocation(line: 45, column: 3, scope: !40) +!75 = !DILocation(line: 8, column: 15, scope: !68, inlinedAt: !74) +!76 = !DILocation(line: 8, column: 16, scope: !68, inlinedAt: !74) +!77 = !DILocalVariable(name: "i1", scope: !78, file: !1, line: 10, type: !79) +!78 = distinct !DILexicalBlock(scope: !68, file: !1, line: 9, column: 5) +!79 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "I1", scope: !68, file: !1, line: 6, size: 32, flags: DIFlagTypePassByValue, elements: !80, identifier: "_ZTSZ7removedvE2I1") +!80 = !{!81} +!81 = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: !79, file: !1, line: 6, baseType: !82, size: 32) +!82 = !DIDerivedType(tag: DW_TAG_typedef, name: "Int1", scope: !69, file: !1, line: 4, baseType: !17) +!83 = !DILocation(line: 10, column: 10, scope: !78, inlinedAt: !74) +!84 = !DILocation(line: 10, column: 17, scope: !78, inlinedAt: !74) +!85 = !DILocation(line: 10, column: 18, scope: !78, inlinedAt: !74) +!86 = !DILocalVariable(name: "c1", scope: !78, file: !1, line: 11, type: !87) +!87 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C1", scope: !68, file: !1, line: 7, size: 8, flags: DIFlagTypePassByValue, elements: !88, identifier: "_ZTSZ7removedvE2C1") +!88 = !{!89} +!89 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !87, file: !1, line: 7, baseType: !90, size: 8) +!90 = !DIDerivedType(tag: DW_TAG_typedef, name: "Char1", scope: !87, file: !1, line: 7, baseType: !35) +!91 = !DILocation(line: 11, column: 10, scope: !78, inlinedAt: !74) +!92 = !DILocation(line: 11, column: 17, scope: !78, inlinedAt: !74) +!93 = !DILocation(line: 11, column: 18, scope: !78, inlinedAt: !74) +!94 = !DILocation(line: 23, column: 8, scope: !13, inlinedAt: !95) +!95 = distinct !DILocation(line: 46, column: 3, scope: !40) +!96 = !DILocation(line: 23, column: 15, scope: !13, inlinedAt: !95) +!97 = !DILocation(line: 23, column: 16, scope: !13, inlinedAt: !95) +!98 = !DILocation(line: 25, column: 10, scope: !22, inlinedAt: !95) +!99 = !DILocation(line: 25, column: 17, scope: !22, inlinedAt: !95) +!100 = !DILocation(line: 25, column: 18, scope: !22, inlinedAt: !95) +!101 = !DILocation(line: 26, column: 10, scope: !22, inlinedAt: !95) +!102 = !DILocation(line: 26, column: 17, scope: !22, inlinedAt: !95) +!103 = !DILocation(line: 26, column: 18, scope: !22, inlinedAt: !95) +!104 = !DILocation(line: 47, column: 1, scope: !40) +!105 = !{!14, !23, !26, !31} +!107 = !{!44, !52, !55, !60} +!110 = !{!70, !79, !82, !87} diff --git a/llvm/test/DebugInfo/Generic/local-type-as-template-parameter.ll b/llvm/test/DebugInfo/Generic/local-type-as-template-parameter.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/local-type-as-template-parameter.ll @@ -0,0 +1,160 @@ +; RUN: %llc_dwarf -O0 -filetype=obj < %s \ +; RUN: | llvm-dwarfdump --show-children --name=foo - \ +; RUN: | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s + +; The test ensures that AsmPrinter doesn't crashed compiling this. +; It also demostrates misplacement for a local type (see PR55680 for details). + +; The test compiled from: + +; template +; struct A { +; A(T &in) : a(in) {} +; T a; +; }; +; +; __attribute__((always_inline)) +; void foo() { +; struct B { int i; }; +; B objB; +; A objA(objB); +; } +; +; int main() { +; foo(); +; } + +; Concrete out-of-line tree of foo(). +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_abstract_origin {{.*}} "_Z3foov" +; +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "objB" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "objA" + +; FIXME: 'struct B' should be in the abstract tree below, not here. +; CHECK: DW_TAG_structure_type +; CHECK: DW_AT_name ("B") +; CHECK: DW_TAG_member +; CHECK: NULL + +; CHECK: NULL + +; Abstract tree of foo(). +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("foo") +; CHECK: DW_AT_inline (DW_INL_inlined) + +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("objB") +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("objA") + +; CHECK: NULL + +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin {{.*}} "_Z3foov" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "objB" +; CHECK: DW_TAG_variable +; CHECK: DW_AT_abstract_origin {{.*}} "objA" +; CHECK: NULL + +%struct.B = type { i32 } +%struct.A = type { %struct.B } + +define dso_local void @_Z3foov() !dbg !7 { +entry: + %objB = alloca %struct.B, align 4 + %objA = alloca %struct.A, align 4 + call void @llvm.dbg.declare(metadata ptr %objB, metadata !30, metadata !DIExpression()), !dbg !31 + call void @llvm.dbg.declare(metadata ptr %objA, metadata !32, metadata !DIExpression()), !dbg !33 + call void @_ZN1AIZ3foovE1BEC2ERS0_(ptr noundef nonnull align 4 dereferenceable(4) %objA, ptr noundef nonnull align 4 dereferenceable(4) %objB), !dbg !33 + ret void, !dbg !34 +} + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +define internal void @_ZN1AIZ3foovE1BEC2ERS0_(ptr noundef nonnull align 4 dereferenceable(4) %this, ptr noundef nonnull align 4 dereferenceable(4) %in) unnamed_addr align 2 !dbg !35 { +entry: + %this.addr = alloca ptr, align 8 + %in.addr = alloca ptr, align 8 + store ptr %this, ptr %this.addr, align 8 + call void @llvm.dbg.declare(metadata ptr %this.addr, metadata !36, metadata !DIExpression()), !dbg !38 + store ptr %in, ptr %in.addr, align 8 + call void @llvm.dbg.declare(metadata ptr %in.addr, metadata !39, metadata !DIExpression()), !dbg !40 + %this1 = load ptr, ptr %this.addr, align 8 + %a = getelementptr inbounds %struct.A, ptr %this1, i32 0, i32 0, !dbg !41 + %0 = load ptr, ptr %in.addr, align 8, !dbg !42 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %0, i64 4, i1 false), !dbg !41 + ret void, !dbg !43 +} + +define dso_local noundef i32 @main() !dbg !44 { +entry: + %objB.i = alloca %struct.B, align 4 + %objA.i = alloca %struct.A, align 4 + call void @llvm.dbg.declare(metadata ptr %objB.i, metadata !30, metadata !DIExpression()), !dbg !47 + call void @llvm.dbg.declare(metadata ptr %objA.i, metadata !32, metadata !DIExpression()), !dbg !49 + call void @_ZN1AIZ3foovE1BEC2ERS0_(ptr noundef nonnull align 4 dereferenceable(4) %objA.i, ptr noundef nonnull align 4 dereferenceable(4) %objB.i), !dbg !49 + ret i32 0, !dbg !50 +} + +declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!22, !23, !24, !25, !26, !27, !28} +!llvm.ident = !{!29} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 15.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "test.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "aec7fd397e86f8655ef7f4bb4233b849") +!2 = !{!3} +!3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "A", file: !1, line: 2, size: 32, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !4, templateParams: !20) +!4 = !{!5, !15} +!5 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !3, file: !1, line: 4, baseType: !6, size: 32) +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", scope: !7, file: !1, line: 9, size: 32, flags: DIFlagTypePassByValue, elements: !12) +!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{null} +!10 = !{} +!11 = !{!6} +!12 = !{!13} +!13 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !6, file: !1, line: 9, baseType: !14, size: 32) +!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = !DISubprogram(name: "A", scope: !3, file: !1, line: 3, type: !16, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit) +!16 = !DISubroutineType(types: !17) +!17 = !{null, !18, !19} +!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer) +!19 = !DIDerivedType(tag: DW_TAG_reference_type, baseType: !6, size: 64) +!20 = !{!21} +!21 = !DITemplateTypeParameter(name: "T", type: !6) +!22 = !{i32 7, !"Dwarf Version", i32 5} +!23 = !{i32 2, !"Debug Info Version", i32 3} +!24 = !{i32 1, !"wchar_size", i32 4} +!25 = !{i32 7, !"PIC Level", i32 2} +!26 = !{i32 7, !"PIE Level", i32 2} +!27 = !{i32 7, !"uwtable", i32 2} +!28 = !{i32 7, !"frame-pointer", i32 2} +!29 = !{!"clang version 15.0.0"} +!30 = !DILocalVariable(name: "objB", scope: !7, file: !1, line: 10, type: !6) +!31 = !DILocation(line: 10, column: 5, scope: !7) +!32 = !DILocalVariable(name: "objA", scope: !7, file: !1, line: 11, type: !3) +!33 = !DILocation(line: 11, column: 8, scope: !7) +!34 = !DILocation(line: 12, column: 1, scope: !7) +!35 = distinct !DISubprogram(name: "A", linkageName: "_ZN1AIZ3foovE1BEC2ERS0_", scope: !3, file: !1, line: 3, type: !16, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, declaration: !15, retainedNodes: !10) +!36 = !DILocalVariable(name: "this", arg: 1, scope: !35, type: !37, flags: DIFlagArtificial | DIFlagObjectPointer) +!37 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !3, size: 64) +!38 = !DILocation(line: 0, scope: !35) +!39 = !DILocalVariable(name: "in", arg: 2, scope: !35, file: !1, line: 3, type: !19) +!40 = !DILocation(line: 3, column: 8, scope: !35) +!41 = !DILocation(line: 3, column: 14, scope: !35) +!42 = !DILocation(line: 3, column: 16, scope: !35) +!43 = !DILocation(line: 3, column: 21, scope: !35) +!44 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !45, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !10) +!45 = !DISubroutineType(types: !46) +!46 = !{!14} +!47 = !DILocation(line: 10, column: 5, scope: !7, inlinedAt: !48) +!48 = distinct !DILocation(line: 15, column: 3, scope: !44) +!49 = !DILocation(line: 11, column: 8, scope: !7, inlinedAt: !48) +!50 = !DILocation(line: 16, column: 1, scope: !44) diff --git a/llvm/test/DebugInfo/Generic/namespace.ll b/llvm/test/DebugInfo/Generic/namespace.ll --- a/llvm/test/DebugInfo/Generic/namespace.ll +++ b/llvm/test/DebugInfo/Generic/namespace.ll @@ -22,15 +22,21 @@ ; CHECK: DW_TAG_formal_parameter ; CHECK: NULL +; CHECK: [[FUNC_FWD:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram +; CHECK: DW_AT_name ("func_fwd") +; CHECK-NOT: DW_AT_declaration + +; CHECK: [[I:0x[0-9a-f]*]]:{{ *}}DW_TAG_variable +; CHECK: DW_AT_name ("i") +; CHECK: [[VAR_FWD:0x[0-9a-f]*]]:{{ *}}DW_TAG_variable +; CHECK: DW_AT_name ("var_fwd") + ; CHECK: [[FOO:0x[0-9a-f]*]]:{{ *}}DW_TAG_structure_type ; CHECK: DW_AT_name ("foo") ; CHECK: DW_AT_declaration ; CHECK: [[BAR:0x[0-9a-f]*]]:{{ *}}DW_TAG_structure_type ; CHECK: DW_AT_name ("bar") -; CHECK: [[I:0x[0-9a-f]*]]:{{ *}}DW_TAG_variable -; CHECK: DW_AT_name ("i") - ; CHECK: [[BAZ:0x[0-9a-f]*]]:{{.*}}DW_TAG_typedef ; CHECK: DW_AT_name ("baz") @@ -41,13 +47,6 @@ ; CHECK: [[FUNC_DECL:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram ; CHECK: DW_AT_name ("func_decl") ; CHECK: DW_AT_declaration - -; CHECK: [[VAR_FWD:0x[0-9a-f]*]]:{{ *}}DW_TAG_variable -; CHECK: DW_AT_name ("var_fwd") - -; CHECK: [[FUNC_FWD:0x[0-9a-f]*]]:{{.*}}DW_TAG_subprogram -; CHECK: DW_AT_name ("func_fwd") -; CHECK-NOT: DW_AT_declaration ; CHECK: NULL ; CHECK: DW_TAG_imported_module @@ -62,6 +61,12 @@ ; CHECK: DW_AT_MIPS_linkage_name ; CHECK: DW_AT_name ("func") ; CHECK: DW_TAG_formal_parameter +; CHECK: DW_TAG_lexical_block +; CHECK: DW_TAG_imported_module +; CHECK: DW_AT_decl_file ([[F2]]) +; CHECK: DW_AT_decl_line (23) +; CHECK: DW_AT_import {{.*}} +; CHECK: NULL ; CHECK: DW_TAG_imported_module ; CHECK: DW_AT_decl_file ([[F2:.*]]) ; CHECK: DW_AT_decl_line (26) @@ -112,16 +117,10 @@ ; CHECK: DW_AT_decl_file ([[F2]]) ; CHECK: DW_AT_decl_line (37) ; CHECK: DW_AT_import ([[FUNC_FWD]]) -; CHECK: DW_TAG_lexical_block -; CHECK: DW_TAG_imported_module -; CHECK: DW_AT_decl_file ([[F2]]) -; CHECK: DW_AT_decl_line (23) -; CHECK: DW_AT_import {{.*}} -; CHECK: NULL ; CHECK: NULL -; CHECK: DW_TAG_base_type ; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_base_type ; CHECK: DW_TAG_imported_module ; CHECK: DW_AT_decl_file ([[F2:.*]]) ; CHECK: DW_AT_decl_line (18) @@ -293,7 +292,7 @@ !18 = !DIFile(filename: "foo.cpp", directory: "/tmp") !19 = !DISubroutineType(types: !20) !20 = !{null} -!21 = distinct !DISubprogram(name: "func", linkageName: "_Z4funcb", line: 21, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 21, file: !5, scope: !18, type: !22, retainedNodes: !2) +!21 = distinct !DISubprogram(name: "func", linkageName: "_Z4funcb", line: 21, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 21, file: !5, scope: !18, type: !22, retainedNodes: !77) !22 = !DISubroutineType(types: !23) !23 = !{!13, !24} !24 = !DIBasicType(tag: DW_TAG_base_type, name: "bool", size: 8, align: 8, encoding: DW_ATE_boolean) @@ -305,7 +304,7 @@ !30 = !{!131, !132} !31 = !DIGlobalVariable(name: "i", linkageName: "_ZN1A1B1iE", line: 20, isLocal: false, isDefinition: true, scope: !6, file: !18, type: !13) !32 = !DIGlobalVariable(name: "var_fwd", linkageName: "_ZN1A1B7var_fwdE", line: 44, isLocal: false, isDefinition: true, scope: !6, file: !18, type: !13) -!33 = !{!34, !35, !36, !37, !40, !41, !42, !43, !44, !45, !47, !48, !49, !51, !54, !55, !56} +!33 = !{!34, !35, !36, !56} !34 = !DIImportedEntity(tag: DW_TAG_imported_module, file: !5, line: 15, scope: !7, entity: !6) !35 = !DIImportedEntity(tag: DW_TAG_imported_module, file: !5, line: 18, scope: !0, entity: !7) !36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, file: !5, line: 19, name: "E", scope: !0, entity: !7) @@ -348,5 +347,6 @@ !73 = !DILocation(line: 47, column: 21, scope: !26) !74 = !DILocation(line: 0, scope: !75) !75 = !DILexicalBlockFile(discriminator: 0, file: !5, scope: !27) +!77 = !{!37, !40, !41, !42, !43, !44, !45, !47, !48, !49, !51, !54, !55} !131 = !DIGlobalVariableExpression(var: !31, expr: !DIExpression()) !132 = !DIGlobalVariableExpression(var: !32, expr: !DIExpression()) diff --git a/llvm/test/DebugInfo/Generic/split-dwarf-local-import.ll b/llvm/test/DebugInfo/Generic/split-dwarf-local-import.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/split-dwarf-local-import.ll @@ -0,0 +1,77 @@ +; RUN: %llc_dwarf -O1 -filetype=obj -split-dwarf-file=%t.dwo < %s | llvm-dwarfdump -debug-info - | FileCheck %s --implicit-check-not "{{DW_TAG|NULL}}" +; REQUIRES: object-emission + +; CHECK-LABEL: debug_info contents +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_GNU_dwo_name +; CHECK: DW_AT_GNU_dwo_id +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_inlined_subroutine +; CHECK: NULL +; CHECK: NULL + +; CHECK: DW_TAG_compile_unit +; CHECK-NOT: DW_AT_GNU_dwo_name +; CHECK-NOT: DW_AT_GNU_dwo_id +; CHECK: DW_TAG_subprogram +; CHECK: NULL + +; CHECK-LABEL: debug_info.dwo contents + +; CHECK: DW_TAG_compile_unit +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_imported_declaration +; CHECK: NULL +; CHECK: DW_TAG_subprogram +; CHECK: DW_TAG_inlined_subroutine +; CHECK: NULL +; CHECK: DW_TAG_namespace +; CHECK: DW_TAG_structure_type +; CHECK: NULL +; CHECK: DW_TAG_base_type +; CHECK: NULL + +%"struct.ns::t1" = type { i8 } + +declare void @llvm.dbg.declare(metadata, metadata, metadata) + +declare dso_local void @_Z3pinv() local_unnamed_addr + +define dso_local i32 @main() local_unnamed_addr !dbg !18 { +entry: + call void @llvm.dbg.declare(metadata %"struct.ns::t1"* undef, metadata !22, metadata !DIExpression()), !dbg !23 + call void @_Z3pinv(), !dbg !25 + ret i32 0, !dbg !26 +} + +!llvm.dbg.cu = !{!0, !10} +!llvm.ident = !{!12, !12} +!llvm.module.flags = !{!13, !14, !15, !16, !17} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: true, nameTableKind: GNU) +!1 = !DIFile(filename: "a.cpp", directory: "/") +!2 = !{!3} +!3 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !8, file: !1, line: 3) +!4 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 3, type: !5, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = !{} +!8 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1", scope: !9, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t1E") +!9 = !DINamespace(name: "ns", scope: null) +!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !11, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: true, nameTableKind: GNU) +!11 = !DIFile(filename: "b.cpp", directory: "/") +!12 = !{!"clang version 14.0.0"} +!13 = !{i32 7, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{i32 7, !"uwtable", i32 1} +!17 = !{i32 7, !"frame-pointer", i32 2} +!18 = distinct !DISubprogram(name: "main", scope: !11, file: !11, line: 2, type: !19, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !7) +!19 = !DISubroutineType(types: !20) +!20 = !{!21} +!21 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!22 = !DILocalVariable(name: "v1", scope: !4, file: !1, line: 3, type: !8) +!23 = !DILocation(line: 3, column: 37, scope: !4, inlinedAt: !24) +!24 = distinct !DILocation(line: 3, column: 3, scope: !18) +!25 = !DILocation(line: 3, column: 41, scope: !4, inlinedAt: !24) +!26 = !DILocation(line: 4, column: 1, scope: !18) diff --git a/llvm/test/DebugInfo/Generic/split-dwarf-local-import2.ll b/llvm/test/DebugInfo/Generic/split-dwarf-local-import2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/split-dwarf-local-import2.ll @@ -0,0 +1,40 @@ +; RUN: %llc_dwarf -split-dwarf-file=%t.dwo < %s | FileCheck %s + +; Ensure function-local DW_TAG_imported_declaration get skipped if its parent subprogram was not emitted. +; CHECK-NOT: DW_TAG_imported_declaration + +define void @f1() !dbg !13 { +lbl: + ret void, !dbg !16 +} + +define void @f2() !dbg !22 { +lbl: + ret void, !dbg !23 +} + +!llvm.dbg.cu = !{!0, !2, !10} +!llvm.module.flags = !{!12} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, emissionKind: FullDebug) +!1 = !DIFile(filename: "a.cc", directory: "") +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, emissionKind: FullDebug) +!3 = !DIFile(filename: "b.cc", directory: "") +!4 = !{!5} +!5 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !6, entity: !7) +!6 = !DISubprogram(scope: null, spFlags: DISPFlagOptimized, retainedNodes: !4) +!7 = !DINamespace(scope: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{} +!10 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !11, emissionKind: FullDebug) +!11 = !DIFile(filename: "c.cc", directory: "") +!12 = !{i32 2, !"Debug Info Version", i32 3} +!13 = distinct !DISubprogram(scope: null, type: !8, spFlags: DISPFlagDefinition, unit: !0) +!16 = !DILocation(line: 0, scope: !17, inlinedAt: !18) +!17 = distinct !DISubprogram(scope: null, unit: !10) +!18 = !DILocation(line: 0, scope: !21) +!21 = !DILexicalBlockFile(scope: !13, discriminator: 0) +!22 = distinct !DISubprogram(scope: null, type: !8, spFlags: DISPFlagDefinition, unit: !0) +!23 = !DILocation(line: 0, scope: !24, inlinedAt: !25) +!24 = distinct !DISubprogram(scope: null, unit: !2) +!25 = !DILocation(line: 0, scope: !22) diff --git a/llvm/test/DebugInfo/Generic/split-dwarf-local-import3.ll b/llvm/test/DebugInfo/Generic/split-dwarf-local-import3.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/Generic/split-dwarf-local-import3.ll @@ -0,0 +1,69 @@ +; RUN: %llc_dwarf -O1 -filetype=obj -split-dwarf-file=%t.dwo < %s \ +; RUN: | llvm-dwarfdump -debug-info - \ +; RUN: | FileCheck %s --implicit-check-not "{{DW_TAG|NULL}}" + +; Ensure that the imported entity 'nn::A' gets emitted in 'foo()'s abstract tree +; in the destination (where 'foo()' was inlined) compile unit. + +; CHECK-LABEL: .debug_info contents +; CHECK: DW_TAG_skeleton_unit +; CHECK: DW_AT_dwo_name + +; CHECK-LABEL: .debug_info.dwo contents: +; CHECK: DW_TAG_compile_unit +; CHECK: DW_AT_name ("test.cpp") +; CHECK: DW_AT_dwo_name + +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("foo") +; CHECK: DW_TAG_imported_declaration +; CHECK: NULL + +; CHECK: DW_TAG_base_type +; CHECK: DW_AT_name ("int") + +; CHECK: DW_TAG_subprogram +; CHECK: DW_AT_name ("main") +; CHECK: DW_TAG_inlined_subroutine +; CHECK: DW_AT_abstract_origin {{.*}} "_Z3foov" +; CHECK: NULL + +; CHECK: DW_TAG_namespace +; CHECK: DW_AT_name ("nn") +; CHECK: DW_TAG_variable +; CHECK: DW_AT_name ("A") +; CHECK: NULL +; CHECK: NULL + +define dso_local noundef i32 @main() local_unnamed_addr !dbg !20 { +entry: + ret i32 42, !dbg !21 +} + +!llvm.dbg.cu = !{!0, !2} +!llvm.module.flags = !{!13, !14, !15, !16, !17, !18} +!llvm.ident = !{!19, !19} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, splitDebugFilename: "test.dwo", emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: GNU) +!1 = !DIFile(filename: "test.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "e7c2808ee27614e496499d55e4b37962") +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 15.0.0", isOptimized: true, runtimeVersion: 0, splitDebugFilename: "cu1.dwo", emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: GNU) +!3 = !DIFile(filename: "cu1.cpp", directory: "/", checksumkind: CSK_MD5, checksum: "c0b84240ef5682b87083b33cf9038171") +!4 = !{!5} +!5 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !6, entity: !11, file: !3, line: 5) +!6 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !3, file: !3, line: 5, type: !7, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4) +!7 = !DISubroutineType(types: !8) +!8 = !{!9} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !{} +!11 = distinct !DIGlobalVariable(name: "A", linkageName: "_ZN2nn1AE", scope: !12, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true) +!12 = !DINamespace(name: "nn", scope: null) +!13 = !{i32 7, !"Dwarf Version", i32 5} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{i32 7, !"PIC Level", i32 2} +!17 = !{i32 7, !"PIE Level", i32 2} +!18 = !{i32 7, !"uwtable", i32 2} +!19 = !{!"clang version 15.0.0"} +!20 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !10) +!21 = !DILocation(line: 4, column: 3, scope: !6, inlinedAt: !22) +!22 = !DILocation(line: 4, column: 3, scope: !20) diff --git a/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll b/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll --- a/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll +++ b/llvm/test/DebugInfo/Generic/verifier-invalid-disubprogram.ll @@ -38,7 +38,7 @@ define void @invalid_retained_nodes_list() !dbg !10 { ret void } !10 = distinct !DISubprogram(retainedNodes: !0) -; CHECK: invalid retained nodes, expected DILocalVariable or DILabel +; CHECK: invalid retained nodes, expected DIGlobalVariableExpression, DIType, DIImportedEntity, DILocalVariable or DILabel define void @invalid_retained_nodes_expected() !dbg !11 { ret void } !11 = distinct !DISubprogram(retainedNodes: !{!0}) diff --git a/llvm/test/DebugInfo/X86/DW_AT_specification.ll b/llvm/test/DebugInfo/X86/DW_AT_specification.ll --- a/llvm/test/DebugInfo/X86/DW_AT_specification.ll +++ b/llvm/test/DebugInfo/X86/DW_AT_specification.ll @@ -23,13 +23,13 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = !DIGlobalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: null, file: !3, line: 4, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !8, declaration: !11) +!2 = distinct !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: null, file: !3, line: 4, type: !4, isLocal: false, isDefinition: true, scopeLine: 4, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !8, declaration: !11, retainedNodes: !10) !3 = !DIFile(filename: "nsNativeAppSupportBase.ii", directory: "/Users/espindola/mozilla-central/obj-x86_64-apple-darwin11.2.0/toolkit/library") !4 = !DISubroutineType(types: !5) !5 = !{null, !6} !6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64, align: 64, flags: DIFlagArtificial) !7 = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", file: !3, line: 1, flags: DIFlagFwdDecl) -!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.0 ()", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, retainedTypes: !9, globals: !10, imports: !9) +!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 3.0 ()", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !9, retainedTypes: !9, imports: !9) !9 = !{} !10 = !{!0} !11 = !DISubprogram(name: "bar", linkageName: "_ZN3foo3barEv", scope: !12, file: !3, line: 2, type: !4, isLocal: false, isDefinition: false, scopeLine: 2, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false) diff --git a/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll b/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll --- a/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll +++ b/llvm/test/DebugInfo/X86/dimodule-external-fortran.ll @@ -73,13 +73,11 @@ !3 = !DIFile(filename: "em.f90", directory: "tests") !4 = !DISubroutineType(types: !5) !5 = !{null} -!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, imports: !9, splitDebugInlining: false, nameTableKind: None) +!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2165", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, splitDebugInlining: false, nameTableKind: None) !7 = !{} -!8 = !{!0} -!9 = !{!10} !10 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !2, entity: !11, file: !3, line: 2) !11 = !DIModule(scope: !2, name: "external_module", isDecl: true) -!12 = !{!13} +!12 = !{!0, !10, !13} !13 = !DILocalVariable(name: "x", scope: !2, file: !3, line: 5, type: !14) !14 = !DIBasicType(name: "REAL*4", size: 32, encoding: DW_ATE_float) !15 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/llvm/test/DebugInfo/X86/distringtype.ll b/llvm/test/DebugInfo/X86/distringtype.ll --- a/llvm/test/DebugInfo/X86/distringtype.ll +++ b/llvm/test/DebugInfo/X86/distringtype.ll @@ -148,11 +148,11 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "deferred", linkageName: "assumedlength_$DEFERRED", scope: !2, file: !3, line: 2, type: !9, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "assumedlength", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !7) +!2 = distinct !DISubprogram(name: "assumedlength", linkageName: "MAIN__", scope: !3, file: !3, line: 1, type: !4, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !8) !3 = !DIFile(filename: "distring.f90", directory: "/iusers/cchen15/examples/tests") !4 = !DISubroutineType(types: !5) !5 = !{null} -!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2142", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, globals: !8, splitDebugInlining: false, nameTableKind: None) +!6 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !3, producer: "Intel(R) Fortran 21.0-2142", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !7, splitDebugInlining: false, nameTableKind: None) !7 = !{} !8 = !{!0} !9 = !DIStringType(name: ".str.DEFERRED", stringLengthExpression: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 8), stringLocationExpression: !DIExpression(DW_OP_push_object_address, DW_OP_deref)) diff --git a/llvm/test/DebugInfo/X86/dwarfdump-DIImportedEntity_elements.ll b/llvm/test/DebugInfo/X86/dwarfdump-DIImportedEntity_elements.ll --- a/llvm/test/DebugInfo/X86/dwarfdump-DIImportedEntity_elements.ll +++ b/llvm/test/DebugInfo/X86/dwarfdump-DIImportedEntity_elements.ll @@ -84,7 +84,7 @@ !1 = distinct !DIGlobalVariable(name: "var1", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true) !2 = !DIModule(scope: !4, name: "mymod", file: !3, line: 1) !3 = !DIFile(filename: "DIImportedEntity_elements.f90", directory: "/tmp") -!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang usemodulealias.f90 -g -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !12, nameTableKind: None) +!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang usemodulealias.f90 -g -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, nameTableKind: None) !5 = !{} !6 = !{!0, !7, !10} !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4)) @@ -94,7 +94,7 @@ !11 = distinct !DIGlobalVariable(name: "var3", scope: !2, file: !3, line: 4, type: !9, isLocal: false, isDefinition: true) !12 = !{!13} !13 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !14, entity: !2, file: !3, line: 10, elements: !19) -!14 = distinct !DISubprogram(name: "use_renamed", scope: !15, file: !3, line: 10, type: !18, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4) +!14 = distinct !DISubprogram(name: "use_renamed", scope: !15, file: !3, line: 10, type: !18, scopeLine: 10, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !4, retainedNodes: !12) !15 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 7, type: !16, scopeLine: 7, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4) !16 = !DISubroutineType(cc: DW_CC_program, types: !17) !17 = !{null} diff --git a/llvm/test/DebugInfo/X86/fission-inline.ll b/llvm/test/DebugInfo/X86/fission-inline.ll --- a/llvm/test/DebugInfo/X86/fission-inline.ll +++ b/llvm/test/DebugInfo/X86/fission-inline.ll @@ -97,7 +97,7 @@ !llvm.module.flags = !{!22, !23} !llvm.ident = !{!24} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !18) +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, file: !1, enums: !2, retainedTypes: !3, globals: !2) !1 = !DIFile(filename: "fission-inline.cpp", directory: "/tmp/dbginfo") !2 = !{} !3 = !{!4} @@ -106,7 +106,7 @@ !6 = !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 4, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 4, file: !1, scope: !4, type: !7) !7 = !DISubroutineType(types: !8) !8 = !{null, null} -!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !2) +!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !18) !11 = distinct !DISubprogram(name: "f2", linkageName: "_ZN3foo2f2IiEEvv", line: 10, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 10, file: !1, scope: !4, type: !12, templateParams: !14, declaration: !17, retainedNodes: !2) !12 = !DISubroutineType(types: !13) !13 = !{null} diff --git a/llvm/test/DebugInfo/X86/fission-local-import.ll b/llvm/test/DebugInfo/X86/fission-local-import.ll --- a/llvm/test/DebugInfo/X86/fission-local-import.ll +++ b/llvm/test/DebugInfo/X86/fission-local-import.ll @@ -16,12 +16,12 @@ !llvm.module.flags = !{!9, !10, !11} !llvm.ident = !{!12} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 (trunk 349508) (llvm/trunk 349520)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, imports: !3, nameTableKind: None) +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 8.0.0 (trunk 349508) (llvm/trunk 349520)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) !1 = !DIFile(filename: "test.cpp", directory: "/usr/local/google/home/blaikie/dev/scratch") !2 = !{} !3 = !{!4} !4 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !8, file: !1, line: 2) -!5 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!5 = distinct !DISubprogram(name: "test", linkageName: "_Z4testv", scope: !1, file: !1, line: 2, type: !6, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !3) !6 = !DISubroutineType(types: !7) !7 = !{null} !8 = !DINamespace(name: "ns1", scope: null) diff --git a/llvm/test/DebugInfo/X86/fission-no-inline-gsym.ll b/llvm/test/DebugInfo/X86/fission-no-inline-gsym.ll --- a/llvm/test/DebugInfo/X86/fission-no-inline-gsym.ll +++ b/llvm/test/DebugInfo/X86/fission-no-inline-gsym.ll @@ -53,7 +53,7 @@ !llvm.module.flags = !{!22, !23} !llvm.ident = !{!24} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, splitDebugInlining: false, file: !1, enums: !2, retainedTypes: !3, globals: !2, imports: !18) +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.6.0 ", isOptimized: false, splitDebugFilename: "fission-inline.dwo", emissionKind: FullDebug, splitDebugInlining: false, file: !1, enums: !2, retainedTypes: !3, globals: !2) !1 = !DIFile(filename: "fission-inline.cpp", directory: "") !2 = !{} !3 = !{!4} @@ -62,7 +62,7 @@ !6 = !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 4, isLocal: false, isDefinition: false, flags: DIFlagPrototyped, isOptimized: false, scopeLine: 4, file: !1, scope: !4, type: !7) !7 = !DISubroutineType(types: !8) !8 = !{null, null} -!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !2) +!10 = distinct !DISubprogram(name: "f3", linkageName: "_ZN3foo2f3Ez", line: 15, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 15, file: !1, scope: !4, type: !7, declaration: !6, retainedNodes: !18) !11 = distinct !DISubprogram(name: "f2", linkageName: "_ZN3foo2f2IiEEvv", line: 10, isLocal: false, isDefinition: true, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 10, file: !1, scope: !4, type: !12, templateParams: !14, declaration: !17, retainedNodes: !2) !12 = !DISubroutineType(types: !13) !13 = !{null} diff --git a/llvm/test/DebugInfo/X86/gnu-public-names.ll b/llvm/test/DebugInfo/X86/gnu-public-names.ll --- a/llvm/test/DebugInfo/X86/gnu-public-names.ll +++ b/llvm/test/DebugInfo/X86/gnu-public-names.ll @@ -196,12 +196,12 @@ ; CHECK-NEXT: [[OUTER_ANON_C]] STATIC VARIABLE "outer::(anonymous namespace)::c" ; CHECK-NEXT: [[ANON_I]] STATIC VARIABLE "(anonymous namespace)::i" ; CHECK-NEXT: [[GLOB_NS_FUNC]] EXTERNAL FUNCTION "ns::global_namespace_function" +; CHECK-NEXT: [[ANON]] EXTERNAL TYPE "(anonymous namespace)" ; GCC Doesn't put local statics in pubnames, but it seems not unreasonable and ; comes out naturally from LLVM's implementation, so I'm OK with it for now. If ; it's demonstrated that this is a major size concern or degrades debug info ; consumer behavior, feel free to change it. ; CHECK-NEXT: [[F3_Z]] STATIC VARIABLE "f3::z" -; CHECK-NEXT: [[ANON]] EXTERNAL TYPE "(anonymous namespace)" ; CHECK-NEXT: [[OUTER_ANON]] EXTERNAL TYPE "outer::(anonymous namespace)" ; CHECK-NEXT: [[ANON_INNER_B]] STATIC VARIABLE "(anonymous namespace)::inner::b" ; CHECK-NEXT: [[OUTER]] EXTERNAL TYPE "outer" @@ -319,7 +319,7 @@ !14 = !{!15} !15 = !DIEnumerator(name: "named_enum_class_enumerator", value: 0) !16 = !{!13} -!17 = !{!0, !18, !29, !32, !37, !44, !47, !50} +!17 = !{!0, !18, !29, !32, !44, !47, !50} !18 = !DIGlobalVariableExpression(var: !19, expr: !DIExpression()) !19 = distinct !DIGlobalVariable(name: "global_variable", scope: !2, file: !3, line: 13, type: !20, isLocal: false, isDefinition: true) !20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", file: !3, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !21, identifier: "_ZTS1C") @@ -341,7 +341,7 @@ !36 = !DIDerivedType(tag: DW_TAG_member, name: "A", scope: !34, file: !3, line: 22, baseType: !13, size: 32) !37 = !DIGlobalVariableExpression(var: !38, expr: !DIExpression()) !38 = distinct !DIGlobalVariable(name: "z", scope: !39, file: !3, line: 33, type: !13, isLocal: true, isDefinition: true) -!39 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !3, file: !3, line: 32, type: !40, scopeLine: 32, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !43) +!39 = distinct !DISubprogram(name: "f3", linkageName: "_Z2f3v", scope: !3, file: !3, line: 32, type: !40, scopeLine: 32, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !91) !40 = !DISubroutineType(types: !41) !41 = !{!42} !42 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64) @@ -393,3 +393,4 @@ !88 = !DILocation(line: 59, column: 68, scope: !78) !89 = !DILocation(line: 60, column: 32, scope: !78) !90 = !DILocation(line: 59, column: 3, scope: !78) +!91 = !{!37} diff --git a/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll b/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll --- a/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll +++ b/llvm/test/DebugInfo/X86/lexical-block-file-inline.ll @@ -119,10 +119,10 @@ !llvm.module.flags = !{!15, !16} !llvm.ident = !{!17} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 264349)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2, imports: !10) +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.9.0 (trunk 264349)", isOptimized: false, runtimeVersion: 0, emissionKind: 1, enums: !2) !1 = !DIFile(filename: "test.cpp", directory: "/") !2 = !{} -!4 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2) +!4 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 2, type: !5, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !10) !5 = !DISubroutineType(types: !6) !6 = !{!7} !7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed) diff --git a/llvm/test/DebugInfo/X86/namelist1.ll b/llvm/test/DebugInfo/X86/namelist1.ll --- a/llvm/test/DebugInfo/X86/namelist1.ll +++ b/llvm/test/DebugInfo/X86/namelist1.ll @@ -47,9 +47,9 @@ !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_plus_uconst, 120)) !1 = distinct !DIGlobalVariable(name: "a", scope: !2, file: !3, line: 3, type: !9, isLocal: true, isDefinition: true) -!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !7, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4) +!2 = distinct !DISubprogram(name: "main", scope: !4, file: !3, line: 1, type: !7, scopeLine: 1, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !4, retainedNodes: !6) !3 = !DIFile(filename: "namelist.f90", directory: "/dir") -!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !5, nameTableKind: None) +!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, imports: !5, nameTableKind: None) !5 = !{} !6 = !{!0} !7 = !DISubroutineType(cc: DW_CC_program, types: !8) diff --git a/llvm/test/DebugInfo/X86/namelist2.ll b/llvm/test/DebugInfo/X86/namelist2.ll --- a/llvm/test/DebugInfo/X86/namelist2.ll +++ b/llvm/test/DebugInfo/X86/namelist2.ll @@ -41,7 +41,7 @@ !1 = distinct !DIGlobalVariable(name: "aa", scope: !2, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true) !2 = !DIModule(scope: !4, name: "mm", file: !3, line: 1) !3 = !DIFile(filename: "namelist2.f90", directory: "/dir") -!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist2.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, imports: !14, nameTableKind: None) +!4 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang - 1.5 2017-05-01", isOptimized: false, flags: "'+flang -g namelist2.f90 -S -emit-llvm'", runtimeVersion: 0, emissionKind: FullDebug, enums: !5, retainedTypes: !5, globals: !6, nameTableKind: None) !5 = !{} !6 = !{!0, !7, !10} !7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_plus_uconst, 4)) @@ -53,7 +53,7 @@ !13 = !{!1, !8} !14 = !{!15} !15 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !16, entity: !2, file: !3, line: 6) -!16 = distinct !DISubprogram(name: "test", scope: !4, file: !3, line: 6, type: !17, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4) +!16 = distinct !DISubprogram(name: "test", scope: !4, file: !3, line: 6, type: !17, scopeLine: 6, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition, unit: !4, retainedNodes: !14) !17 = !DISubroutineType(types: !18) !18 = !{null} !19 = !{i32 2, !"Dwarf Version", i32 4} diff --git a/llvm/test/DebugInfo/omit-empty.ll b/llvm/test/DebugInfo/omit-empty.ll --- a/llvm/test/DebugInfo/omit-empty.ll +++ b/llvm/test/DebugInfo/omit-empty.ll @@ -6,15 +6,15 @@ !llvm.dbg.cu = !{!0, !5} !llvm.module.flags = !{!3, !4} -!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2, imports: !2) +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !2, retainedTypes: !2, globals: !2) !1 = !DIFile(filename: "", directory: "/") !2 = !{} !3 = !{i32 2, !"Dwarf Version", i32 4} !4 = !{i32 2, !"Debug Info Version", i32 3} -!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !6) +!5 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) !6 = !{!7} !7 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !8, entity: !8, file: !1, line: 3) -!8 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !5, retainedNodes: !2) +!8 = distinct !DISubprogram(name: "f2", linkageName: "_Z2f2v", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !5, retainedNodes: !6) !9 = !DISubroutineType(types: !10) !10 = !{null} !11 = !DINamespace(name: "ns", scope: null) diff --git a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll --- a/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll +++ b/llvm/test/Instrumentation/InstrProfiling/debug-info-correlate.ll @@ -20,7 +20,7 @@ define void @_Z3foov() !dbg !12 { call void @llvm.instrprof.increment(ptr @__profn_foo, i64 12345678, i32 2, i32 0) - ret void + ret void, !dbg !17 } declare void @llvm.instrprof.increment(ptr, i64, i32, i32) @@ -46,6 +46,7 @@ !14 = !DISubroutineType(types: !15) !15 = !{null} !16 = !{} +!17 = !DILocation(line: 1, scope: !12) ; CHECK-DWARF: DW_TAG_compile_unit ; CHECK-DWARF: DW_TAG_subprogram diff --git a/llvm/test/ThinLTO/X86/debuginfo-cu-import.ll b/llvm/test/ThinLTO/X86/debuginfo-cu-import.ll --- a/llvm/test/ThinLTO/X86/debuginfo-cu-import.ll +++ b/llvm/test/ThinLTO/X86/debuginfo-cu-import.ll @@ -5,15 +5,13 @@ ; RUN: opt -module-summary %p/Inputs/debuginfo-cu-import.ll -o %t2.bc ; RUN: llvm-lto -thinlto-action=thinlink -o %t.index.bc %t1.bc %t2.bc -; Don't import enums, macros, retainedTypes or globals lists. -; Only import local scope imported entities. +; Don't import enums, macros, retainedTypes, globals or imports lists. ; RUN: llvm-lto -thinlto-action=import %t2.bc -thinlto-index=%t.index.bc -o - | llvm-dis -o - | FileCheck %s ; CHECK-NOT: DICompileUnit{{.*}} enums: ; CHECK-NOT: DICompileUnit{{.*}} macros: ; CHECK-NOT: DICompileUnit{{.*}} retainedTypes: ; CHECK-NOT: DICompileUnit{{.*}} globals: -; CHECK: DICompileUnit{{.*}} imports: ![[IMP:[0-9]+]] -; CHECK: ![[IMP]] = !{!{{[0-9]+}}} +; CHECK-NOT: DICompileUnit{{.*}} imports: ; ModuleID = 'debuginfo-cu-import.c' source_filename = "debuginfo-cu-import.c" @@ -50,14 +48,14 @@ !8 = !{!9} !9 = !DIGlobalVariableExpression(var: !10, expr: !DIExpression()) !10 = !DIGlobalVariable(name: "version", scope: !4, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true) -!11 = !{!12, !16} +!11 = !{!12} !12 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !4, entity: !13, file: !1, line: 8) !13 = distinct !DISubprogram(name: "a", linkageName: "_ZN1A1aEv", scope: !4, file: !1, line: 7, type: !14, isLocal: false, isDefinition: true, scopeLine: 7, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5) !14 = !DISubroutineType(types: !15) !15 = !{null} !16 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !17, entity: !19, file: !1, line: 8) !17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 8) -!18 = distinct !DISubprogram(name: "c", linkageName: "_ZN1A1cEv", scope: !4, file: !1, line: 9, type: !14, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5) +!18 = distinct !DISubprogram(name: "c", linkageName: "_ZN1A1cEv", scope: !4, file: !1, line: 9, type: !14, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !33) !19 = distinct !DILexicalBlock(scope: !20, file: !1, line: 10, column: 8) !20 = distinct !DISubprogram(name: "d", linkageName: "_ZN1A1dEv", scope: !4, file: !1, line: 10, type: !14, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5) !21 = !{!22} @@ -72,4 +70,4 @@ !30 = !DILocation(line: 7, column: 12, scope: !13) !31 = distinct !DISubprogram(name: "b", linkageName: "_ZN1A1bEv", scope: !4, file: !1, line: 8, type: !14, isLocal: true, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !5) !32 = !DILocation(line: 8, column: 24, scope: !31) - +!33 = !{!16} diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp --- a/llvm/unittests/Transforms/Utils/CloningTest.cpp +++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -1010,6 +1010,15 @@ EXPECT_EQ(SP->getName(), "f"); EXPECT_EQ(SP->getFile()->getFilename(), "filename.c"); EXPECT_EQ(SP->getLine(), (unsigned)4); + + // Check static locals. + MDNodeArray LocalDeclsArray = SP->getRetainedNodes(); + EXPECT_EQ(LocalDeclsArray.size(), 2U); + for (auto *Node : LocalDeclsArray) { + auto *GVExpr = cast(Node); + DIGlobalVariable *GV = GVExpr->getVariable(); + EXPECT_EQ(GV->getScope(), SP); + } } TEST_F(CloneModule, FunctionDeclarationMetadata) { @@ -1067,14 +1076,6 @@ DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); EXPECT_TRUE(SP != nullptr); EXPECT_EQ(SP->getUnit(), CU); - - // Check globals listed in CU have the correct scope - DIGlobalVariableExpressionArray GlobalArray = CU->getGlobalVariables(); - EXPECT_EQ(GlobalArray.size(), 2U); - for (DIGlobalVariableExpression *GVExpr : GlobalArray) { - DIGlobalVariable *GV = GVExpr->getVariable(); - EXPECT_EQ(GV->getScope(), SP); - } } TEST_F(CloneModule, Comdat) {