Reland "[DebugMetadata][DwarfDebug] Support function-local types in lexical block scopes (4/7)"#165032
Conversation
|
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-llvm-ir Author: Vladislav Dzhidzhoev (dzhidzhoev) ChangesThis is an attempt to merge https://reviews.llvm.org/D144006 with LTO fix. The last merge attempt was #75385. To tackle that,
With this approach, clang builds without crashes in FullLTO (which is not the case for #75385). Additionally:
Commit #75385 and the new changes are separate commits to simplify review process. Patch is 112.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/165032.diff 40 Files Affected:
diff --git a/clang/test/Analysis/analyzeOneFunction.cpp b/clang/test/Analysis/analyzeOneFunction.cpp
index 3a362dfd9a08c..e4c96eb35f06b 100644
--- a/clang/test/Analysis/analyzeOneFunction.cpp
+++ b/clang/test/Analysis/analyzeOneFunction.cpp
@@ -5,9 +5,9 @@
// RUN: -analyze-function="c:@S@Window@F@overloaded#I#"
// RUN: %clang_extdef_map %s | FileCheck %s
-// CHECK: 27:c:@S@Window@F@overloaded#I#
+// CHECK: 27:c:@S@Window@F@overloaded#d#
// CHECK-NEXT: 27:c:@S@Window@F@overloaded#C#
-// CHECK-NEXT: 27:c:@S@Window@F@overloaded#d#
+// CHECK-NEXT: 27:c:@S@Window@F@overloaded#I#
void clang_analyzer_warnIfReached();
diff --git a/clang/test/DebugInfo/CXX/access.cpp b/clang/test/DebugInfo/CXX/access.cpp
index 9f2c044843d0f..7c0bf8ccb0384 100644
--- a/clang/test/DebugInfo/CXX/access.cpp
+++ b/clang/test/DebugInfo/CXX/access.cpp
@@ -18,9 +18,9 @@ class B : public A {
static int public_static;
protected:
+ // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+3]],{{.*}} flags: DIFlagProtected)
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_typedef",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected)
typedef int prot_typedef;
- // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected)
using prot_using = prot_typedef;
prot_using prot_member;
diff --git a/clang/test/DebugInfo/CXX/anon-union-vars.cpp b/clang/test/DebugInfo/CXX/anon-union-vars.cpp
index 3aca4e199ab8d..27e6c6850e013 100644
--- a/clang/test/DebugInfo/CXX/anon-union-vars.cpp
+++ b/clang/test/DebugInfo/CXX/anon-union-vars.cpp
@@ -51,13 +51,13 @@ void instantiate(int x) {
// 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/DebugInfo/CXX/codeview-unnamed.cpp b/clang/test/DebugInfo/CXX/codeview-unnamed.cpp
index 30815bda020ea..b625a80313c38 100644
--- a/clang/test/DebugInfo/CXX/codeview-unnamed.cpp
+++ b/clang/test/DebugInfo/CXX/codeview-unnamed.cpp
@@ -4,6 +4,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: "<unnamed-type-one>"
+ // MSVC-SAME: identifier: ".?AU<unnamed-type-one>@?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: "<unnamed-type-two>"
+ // MSVC-SAME: identifier: ".?AU<unnamed-type-two>@?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: "<lambda_0>"
+ // MSVC-SAME: identifier: ".?AV<lambda_0>@?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.
@@ -11,21 +65,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: "<unnamed-type-one>"
- // MSVC-SAME: identifier: ".?AU<unnamed-type-one>@?1??main@@9@"
+ // MSVC-SAME: type: [[TYPE_OF_ONE]]
// MSVC-SAME: )
@@ -37,21 +81,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: "<unnamed-type-two>"
- // MSVC-SAME: identifier: ".?AU<unnamed-type-two>@?2??main@@9@"
+ // MSVC-SAME: type: [[TYPE_OF_TWO]]
// MSVC-SAME: )
@@ -62,21 +96,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: )
@@ -88,21 +112,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: "<lambda_0>"
- // MSVC-SAME: identifier: ".?AV<lambda_0>@?0??main@@9@"
+ // MSVC-SAME: type: [[TYPE_OF_FOUR]]
// MSVC-SAME: )
return 0;
diff --git a/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp b/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp
index 6b9c9a243decd..122e4aa62ea7d 100644
--- a/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp
+++ b/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp
@@ -51,9 +51,9 @@ void test() {
// CHECK-SAME: name: "<lambda_2_1>",
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: "<lambda_1>",
// CHECK-SAME: flags: DIFlagFwdDecl
+ // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1]],
c.lambda2();
}
diff --git a/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp b/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp
index 021b85d4ce3a4..609a71c6ec015 100644
--- a/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp
+++ b/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp
@@ -2,14 +2,6 @@
// RUN: -debug-info-kind=standalone -std=c++26 %s -o - | FileCheck %s
-// CHECK: ![[PACK1:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int>"
-// CHECK: ![[PACK2:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int, int>"
-// CHECK: ![[PACK3:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int>"
-// CHECK: ![[PACK4:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int, int>"
-// CHECK: ![[PACK5:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int>"
-// CHECK: ![[PACK6:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int, int>"
-// CHECK: ![[PACK7:[0-9]+]] = distinct !DISubprogram(name: "capture_binding_and_param_pack<int, int>"
-
template<typename... Args>
auto capture_pack(Args... args) {
return [args..., ...params = args] {
@@ -17,6 +9,7 @@ auto capture_pack(Args... args) {
}();
}
+// CHECK: ![[PACK1:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK1]]
// CHECK-SAME: elements: ![[PACK1_ELEMS:[0-9]+]]
// CHECK-DAG: ![[PACK1_ELEMS]] = !{![[PACK1_ARGS:[0-9]+]], ![[PACK1_PARAMS:[0-9]+]]}
@@ -24,6 +17,7 @@ auto capture_pack(Args... args) {
// CHECK-DAG: ![[PACK1_PARAMS]] = !DIDerivedType(tag: DW_TAG_member, name: "params"
// CHECK-NOT: DW_TAG_member
+// CHECK: ![[PACK2:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK2]]
// CHECK-SAME: elements: ![[PACK2_ELEMS:[0-9]+]]
// CHECK: ![[PACK2_ELEMS]] = !{![[PACK2_ARGS:[0-9]+]]
@@ -42,6 +36,7 @@ auto capture_pack_and_locals(int x, Args... args) {
}();
}
+// CHECK: ![[PACK3:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK3]]
// CHECK-SAME: elements: ![[PACK3_ELEMS:[0-9]+]]
// CHECK: ![[PACK3_ELEMS]] = !{![[PACK3_ARGS:[0-9]+]]
@@ -55,6 +50,7 @@ auto capture_pack_and_locals(int x, Args... args) {
// CHECK-DAG: ![[PACK3_W]] = !DIDerivedType(tag: DW_TAG_member, name: "w"
// CHECK-NOT: DW_TAG_member
+// CHECK: ![[PACK4:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK4]]
// CHECK-SAME: elements: ![[PACK4_ELEMS:[0-9]+]]
// CHECK: ![[PACK4_ELEMS]] = !{![[PACK4_ARGS:[0-9]+]]
@@ -90,6 +86,7 @@ struct Foo {
int w = 10;
} f;
+// CHECK: ![[PACK5:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK5]]
// CHECK-SAME: elements: ![[PACK5a_ELEMS:[0-9]+]]
// CHECK: ![[PACK5a_ELEMS]] = !{![[PACK5a_THIS:[0-9]+]]
@@ -120,6 +117,7 @@ struct Foo {
// CHECK-DAG: ![[PACK5c_THIS]] = !DIDerivedType(tag: DW_TAG_member, name: "this"
// CHECK-NOT: DW_TAG_member
+// CHECK: ![[PACK6:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK6]]
// CHECK-SAME: elements: ![[PACK6a_ELEMS:[0-9]+]]
// CHECK: ![[PACK6a_ELEMS]] = !{![[PACK6a_THIS:[0-9]+]]
@@ -168,6 +166,7 @@ auto capture_binding_and_param_pack(Args... args) {
}();
}
+// CHECK: ![[PACK7:[0-9]+]] = distinct !DISubprogram(name: "capture_binding_and_param_pack<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK7]]
// CHECK-SAME: elements: ![[PACK7_ELEMS:[0-9]+]]
diff --git a/clang/test/DebugInfo/CXX/lambda-this.cpp b/clang/test/DebugInfo/CXX/lambda-this.cpp
index 019d09c48f858..1df210953ac2e 100644
--- a/clang/test/DebugInfo/CXX/lambda-this.cpp
+++ b/clang/test/DebugInfo/CXX/lambda-this.cpp
@@ -13,10 +13,10 @@ void D::d(int x) {
}
// 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/DebugInfo/Generic/codeview-unnamed.c b/clang/test/DebugInfo/Generic/codeview-unnamed.c
index 0df6e1a0419bb..7b88f53a92e42 100644
--- a/clang/test/DebugInfo/Generic/codeview-unnamed.c
+++ b/clang/test/DebugInfo/Generic/codeview-unnamed.c
@@ -8,23 +8,23 @@ int main(int argc, char* argv[], char* arge[]) {
//
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/DebugInfo/Generic/unused-types.c b/clang/test/DebugInfo/Generic/unused-types.c
index 3e9f7b07658e3..31d608d92a06b 100644
--- a/clang/test/DebugInfo/Generic/unused-types.c
+++ b/clang/test/DebugInfo/Generic/unused-types.c
@@ -18,13 +18,15 @@ void quux(void) {
// 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]+}}}
+// 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: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]]
+// CHECK: [[SPRETNODES]] = !{[[TYPE5:![0-9]+]], [[TYPE6:![0-9]+]], [[TYPE8:![0-9]+]]}
+// 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/DebugInfo/Generic/unused-types.cpp b/clang/test/DebugInfo/Generic/unused-types.cpp
index 023cac159faa4..5b01c6dbb3941 100644
--- a/clang/test/DebugInfo/Generic/unused-types.cpp
+++ b/clang/test/DebugInfo/Generic/unused-types.cpp
@@ -13,12 +13,14 @@ void quux() {
// 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]+}}}
+// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo"
+// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar"
+// CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]]
+// CHECK: [[SPRETNODES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]]}
+// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y", scope: [[SP]]
+// CHECK: [[TYPE5]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: [[SP]]
+// CHECK: [[TYPE6:![0-9]+]] = !DIEnumerator(name: "Z"
// NODBG-NOT: !DI{{CompositeType|Enumerator|DerivedType}}
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 9eb31d7e0a451..ae568f8ead039 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -181,6 +181,10 @@ namespace llvm {
/// Keeps track of so...
[truncated]
|
|
@llvm/pr-subscribers-backend-arm Author: Vladislav Dzhidzhoev (dzhidzhoev) ChangesThis is an attempt to merge https://reviews.llvm.org/D144006 with LTO fix. The last merge attempt was #75385. To tackle that,
With this approach, clang builds without crashes in FullLTO (which is not the case for #75385). Additionally:
Commit #75385 and the new changes are separate commits to simplify review process. Patch is 112.61 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/165032.diff 40 Files Affected:
diff --git a/clang/test/Analysis/analyzeOneFunction.cpp b/clang/test/Analysis/analyzeOneFunction.cpp
index 3a362dfd9a08c..e4c96eb35f06b 100644
--- a/clang/test/Analysis/analyzeOneFunction.cpp
+++ b/clang/test/Analysis/analyzeOneFunction.cpp
@@ -5,9 +5,9 @@
// RUN: -analyze-function="c:@S@Window@F@overloaded#I#"
// RUN: %clang_extdef_map %s | FileCheck %s
-// CHECK: 27:c:@S@Window@F@overloaded#I#
+// CHECK: 27:c:@S@Window@F@overloaded#d#
// CHECK-NEXT: 27:c:@S@Window@F@overloaded#C#
-// CHECK-NEXT: 27:c:@S@Window@F@overloaded#d#
+// CHECK-NEXT: 27:c:@S@Window@F@overloaded#I#
void clang_analyzer_warnIfReached();
diff --git a/clang/test/DebugInfo/CXX/access.cpp b/clang/test/DebugInfo/CXX/access.cpp
index 9f2c044843d0f..7c0bf8ccb0384 100644
--- a/clang/test/DebugInfo/CXX/access.cpp
+++ b/clang/test/DebugInfo/CXX/access.cpp
@@ -18,9 +18,9 @@ class B : public A {
static int public_static;
protected:
+ // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+3]],{{.*}} flags: DIFlagProtected)
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_typedef",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected)
typedef int prot_typedef;
- // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected)
using prot_using = prot_typedef;
prot_using prot_member;
diff --git a/clang/test/DebugInfo/CXX/anon-union-vars.cpp b/clang/test/DebugInfo/CXX/anon-union-vars.cpp
index 3aca4e199ab8d..27e6c6850e013 100644
--- a/clang/test/DebugInfo/CXX/anon-union-vars.cpp
+++ b/clang/test/DebugInfo/CXX/anon-union-vars.cpp
@@ -51,13 +51,13 @@ void instantiate(int x) {
// 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/DebugInfo/CXX/codeview-unnamed.cpp b/clang/test/DebugInfo/CXX/codeview-unnamed.cpp
index 30815bda020ea..b625a80313c38 100644
--- a/clang/test/DebugInfo/CXX/codeview-unnamed.cpp
+++ b/clang/test/DebugInfo/CXX/codeview-unnamed.cpp
@@ -4,6 +4,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: "<unnamed-type-one>"
+ // MSVC-SAME: identifier: ".?AU<unnamed-type-one>@?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: "<unnamed-type-two>"
+ // MSVC-SAME: identifier: ".?AU<unnamed-type-two>@?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: "<lambda_0>"
+ // MSVC-SAME: identifier: ".?AV<lambda_0>@?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.
@@ -11,21 +65,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: "<unnamed-type-one>"
- // MSVC-SAME: identifier: ".?AU<unnamed-type-one>@?1??main@@9@"
+ // MSVC-SAME: type: [[TYPE_OF_ONE]]
// MSVC-SAME: )
@@ -37,21 +81,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: "<unnamed-type-two>"
- // MSVC-SAME: identifier: ".?AU<unnamed-type-two>@?2??main@@9@"
+ // MSVC-SAME: type: [[TYPE_OF_TWO]]
// MSVC-SAME: )
@@ -62,21 +96,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: )
@@ -88,21 +112,11 @@ int main(int argc, char* argv[], char* arge[]) {
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: "<lambda_0>"
- // MSVC-SAME: identifier: ".?AV<lambda_0>@?0??main@@9@"
+ // MSVC-SAME: type: [[TYPE_OF_FOUR]]
// MSVC-SAME: )
return 0;
diff --git a/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp b/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp
index 6b9c9a243decd..122e4aa62ea7d 100644
--- a/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp
+++ b/clang/test/DebugInfo/CXX/gline-tables-only-codeview.cpp
@@ -51,9 +51,9 @@ void test() {
// CHECK-SAME: name: "<lambda_2_1>",
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: "<lambda_1>",
// CHECK-SAME: flags: DIFlagFwdDecl
+ // CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1]],
c.lambda2();
}
diff --git a/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp b/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp
index 021b85d4ce3a4..609a71c6ec015 100644
--- a/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp
+++ b/clang/test/DebugInfo/CXX/lambda-capture-packs.cpp
@@ -2,14 +2,6 @@
// RUN: -debug-info-kind=standalone -std=c++26 %s -o - | FileCheck %s
-// CHECK: ![[PACK1:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int>"
-// CHECK: ![[PACK2:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int, int>"
-// CHECK: ![[PACK3:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int>"
-// CHECK: ![[PACK4:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int, int>"
-// CHECK: ![[PACK5:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int>"
-// CHECK: ![[PACK6:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int, int>"
-// CHECK: ![[PACK7:[0-9]+]] = distinct !DISubprogram(name: "capture_binding_and_param_pack<int, int>"
-
template<typename... Args>
auto capture_pack(Args... args) {
return [args..., ...params = args] {
@@ -17,6 +9,7 @@ auto capture_pack(Args... args) {
}();
}
+// CHECK: ![[PACK1:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK1]]
// CHECK-SAME: elements: ![[PACK1_ELEMS:[0-9]+]]
// CHECK-DAG: ![[PACK1_ELEMS]] = !{![[PACK1_ARGS:[0-9]+]], ![[PACK1_PARAMS:[0-9]+]]}
@@ -24,6 +17,7 @@ auto capture_pack(Args... args) {
// CHECK-DAG: ![[PACK1_PARAMS]] = !DIDerivedType(tag: DW_TAG_member, name: "params"
// CHECK-NOT: DW_TAG_member
+// CHECK: ![[PACK2:[0-9]+]] = distinct !DISubprogram(name: "capture_pack<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK2]]
// CHECK-SAME: elements: ![[PACK2_ELEMS:[0-9]+]]
// CHECK: ![[PACK2_ELEMS]] = !{![[PACK2_ARGS:[0-9]+]]
@@ -42,6 +36,7 @@ auto capture_pack_and_locals(int x, Args... args) {
}();
}
+// CHECK: ![[PACK3:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK3]]
// CHECK-SAME: elements: ![[PACK3_ELEMS:[0-9]+]]
// CHECK: ![[PACK3_ELEMS]] = !{![[PACK3_ARGS:[0-9]+]]
@@ -55,6 +50,7 @@ auto capture_pack_and_locals(int x, Args... args) {
// CHECK-DAG: ![[PACK3_W]] = !DIDerivedType(tag: DW_TAG_member, name: "w"
// CHECK-NOT: DW_TAG_member
+// CHECK: ![[PACK4:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_locals<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK4]]
// CHECK-SAME: elements: ![[PACK4_ELEMS:[0-9]+]]
// CHECK: ![[PACK4_ELEMS]] = !{![[PACK4_ARGS:[0-9]+]]
@@ -90,6 +86,7 @@ struct Foo {
int w = 10;
} f;
+// CHECK: ![[PACK5:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK5]]
// CHECK-SAME: elements: ![[PACK5a_ELEMS:[0-9]+]]
// CHECK: ![[PACK5a_ELEMS]] = !{![[PACK5a_THIS:[0-9]+]]
@@ -120,6 +117,7 @@ struct Foo {
// CHECK-DAG: ![[PACK5c_THIS]] = !DIDerivedType(tag: DW_TAG_member, name: "this"
// CHECK-NOT: DW_TAG_member
+// CHECK: ![[PACK6:[0-9]+]] = distinct !DISubprogram(name: "capture_pack_and_this<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK6]]
// CHECK-SAME: elements: ![[PACK6a_ELEMS:[0-9]+]]
// CHECK: ![[PACK6a_ELEMS]] = !{![[PACK6a_THIS:[0-9]+]]
@@ -168,6 +166,7 @@ auto capture_binding_and_param_pack(Args... args) {
}();
}
+// CHECK: ![[PACK7:[0-9]+]] = distinct !DISubprogram(name: "capture_binding_and_param_pack<int, int>"
// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C"
// CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, scope: ![[PACK7]]
// CHECK-SAME: elements: ![[PACK7_ELEMS:[0-9]+]]
diff --git a/clang/test/DebugInfo/CXX/lambda-this.cpp b/clang/test/DebugInfo/CXX/lambda-this.cpp
index 019d09c48f858..1df210953ac2e 100644
--- a/clang/test/DebugInfo/CXX/lambda-this.cpp
+++ b/clang/test/DebugInfo/CXX/lambda-this.cpp
@@ -13,10 +13,10 @@ void D::d(int x) {
}
// 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/DebugInfo/Generic/codeview-unnamed.c b/clang/test/DebugInfo/Generic/codeview-unnamed.c
index 0df6e1a0419bb..7b88f53a92e42 100644
--- a/clang/test/DebugInfo/Generic/codeview-unnamed.c
+++ b/clang/test/DebugInfo/Generic/codeview-unnamed.c
@@ -8,23 +8,23 @@ int main(int argc, char* argv[], char* arge[]) {
//
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/DebugInfo/Generic/unused-types.c b/clang/test/DebugInfo/Generic/unused-types.c
index 3e9f7b07658e3..31d608d92a06b 100644
--- a/clang/test/DebugInfo/Generic/unused-types.c
+++ b/clang/test/DebugInfo/Generic/unused-types.c
@@ -18,13 +18,15 @@ void quux(void) {
// 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]+}}}
+// 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: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]]
+// CHECK: [[SPRETNODES]] = !{[[TYPE5:![0-9]+]], [[TYPE6:![0-9]+]], [[TYPE8:![0-9]+]]}
+// 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/DebugInfo/Generic/unused-types.cpp b/clang/test/DebugInfo/Generic/unused-types.cpp
index 023cac159faa4..5b01c6dbb3941 100644
--- a/clang/test/DebugInfo/Generic/unused-types.cpp
+++ b/clang/test/DebugInfo/Generic/unused-types.cpp
@@ -13,12 +13,14 @@ void quux() {
// 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]+}}}
+// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo"
+// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar"
+// CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]]
+// CHECK: [[SPRETNODES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]]}
+// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y", scope: [[SP]]
+// CHECK: [[TYPE5]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z", scope: [[SP]]
+// CHECK: [[TYPE6:![0-9]+]] = !DIEnumerator(name: "Z"
// NODBG-NOT: !DI{{CompositeType|Enumerator|DerivedType}}
diff --git a/llvm/include/llvm/AsmParser/LLParser.h b/llvm/include/llvm/AsmParser/LLParser.h
index 9eb31d7e0a451..ae568f8ead039 100644
--- a/llvm/include/llvm/AsmParser/LLParser.h
+++ b/llvm/include/llvm/AsmParser/LLParser.h
@@ -181,6 +181,10 @@ namespace llvm {
/// Keeps track of so...
[truncated]
|
|
✅ With the latest revision this PR passed the undef deprecator. |
Seems to be a false alarm, triggered due to the file being moved. |
bfee696 to
e97af0a
Compare
|
Fixed failing checks. |
|
Gentle ping |
These checks ensure that retained nodes of a DISubprogram belong to the subprogram. This was helpful to find issues with https://reviews.llvm.org/D144004, llvm#75385, llvm#165032. Also, interface for accessing DISubprogram's retained nodes is slightly refactored. `DISubprogram::visitRetainedNodes` and `DISubprogram::forEachRetainedNode` are added to avoid repeating checks like ``` if (const auto *LV = dyn_cast<DILocalVariable>(N)) ... else if (const auto *L = dyn_cast<DILabel>(N)) ... else if (const auto *IE = dyn_cast<DIImportedEntity>(N)) ... ``` Tests with wrongly scoped retained nodes are fixed.
e97af0a to
99884a4
Compare
|
Gentle ping |
jmorse
left a comment
There was a problem hiding this comment.
Added some shallow comments; I'm still getting my head around the major differences here and haven't looked at the tests, but see:
- We're directly un-doing the effect of ODRUniqing by filtering for vulnerable retainedNodes lists on bitcode/IR load,
- Types that have been ODRUnique'd get cross-scope and possibly cross-CU references to them,
Which seems like a proportionate solution: ORDUniquing is saving memory in this very direct and unstructured way, and we have to work around it. Which sucks, but it's the price of the design decision.
Is there any protection against a part of LLVM duplicating a type and silently getting an ODRUnique'd type back, which then leads to confusion later -- or is that what the createIdentityMDPredicate code is protecting against? I wonder whether this could lead to a situation where creating type metadata is vulnerable to accidents (however if it is, we should protect against it with lots of assertions, instead of trying to design around it).
The potential expansion of the types being cloned due to changing createIdentityMDPredicate might affect compile-time performance; we can look at that in due course though.
Thanks for sticking with this, it's been a rollercoaster, hopefully this will cover all the complications seen to date!
| const_iterator begin() { return MetadataPtrs.begin(); } | ||
| const_iterator end() { return MetadataPtrs.end(); } |
| /// retainedNodes of these subprograms should be cleaned up from incorrectly | ||
| /// scoped local types. |
There was a problem hiding this comment.
IMO to avoid confusing future readers, we need to signal something about the fact that it's LLVM/ORDUniquing that's causing things to be invalid, not the input. Possibly "See the comment on \ref DISubprogram::cleanupRetainedNodes"?
| NewEnums.push_back(Op); | ||
|
|
||
| // Find DISubprogram corresponding to each entity. | ||
| std::map<DISubprogram *, SmallVector<Metadata *>> SPToEntities; |
There was a problem hiding this comment.
Note that std::map is usually discouraged due to allocating for each new element; I think we can get away with this as it's on the autoupgrade path, which isn't going to be fast anyway.
| SetVector<Metadata *> MetadataToRemove; | ||
| // Collect imported entities to be moved. | ||
| if (CU->getRawImportedEntities()) |
There was a problem hiding this comment.
Could you give an overview of the algorithm being used in this function, as I can't piece it together: we've got the collection of metadata-to-remove from the CU, and the NewImports NewEnums collections are the remainder of retainedNodes elements that won't be moved to DISubprograms? If so, I think the term "New" is giving me slight confusion, could we use the term "remaining" or "KeepInCU" or something like that?
There was a problem hiding this comment.
I've rewritten this function to make it more clear, and to decrease the indentation level.
The algorithm is the following:
- For each CU:
1.1. Collect local metadata nodes from CU'simports:andenums:lists in MetadataToRemove set.
1.2. Remove metadata nodes of MetadataToRemove set from CU'simports:andenums:lists.
1.3. Group MetadataToRemove items by their parent subprograms (in SPToEntities map).
1.4. For each subprogram SP in SPToEntities:
1.4.1. Append SP's local metadata nodes to SP'sretainedNodes:list.
| void resolveLoadedMetadata(PlaceholderQueue &Placeholders, | ||
| bool IsModuleLevelDIUpgrade) { |
There was a problem hiding this comment.
As far as I can see this overload is to assist two call-sites that already have a bool? IMO it would be better to sink the selection of DebugInfoUpgradeMode into :MetadataLoaderImpl::parseMetadata rather than rely on this overload, on the principle of "explicit is better than implicit".
| // FIXME: We may have a concrete DIE for this scope already created. | ||
| // This may happen when we emit local variables for an abstract tree of | ||
| // an inlined function: if a local variable has a templated type with | ||
| // a function-local type as a template parameter. See PR55680 for details | ||
| // (see also llvm/test/DebugInfo/Generic/local-type-as-template-parameter.ll). |
There was a problem hiding this comment.
It's unclear what's to be fixed here: the concrete DIE isn't supposed to exist already but we accept it temporarily, or we should intend on creating a duplicate, or placing it somewhere else?
There was a problem hiding this comment.
Hmm, this piece of code was added in the original PR https://reviews.llvm.org/D144006. I've been trying to understand why @chbessonova added it.
From my analysis, it seems that we will not encounter a situation where a concrete, out-of-line lexical block DIE for Scope already exists at the start of DwarfCompileUnit::getOrCreateLexicalBlockDIE.
It is possible for a concrete DIE for a subprogram to be created in the DwarfUnit before the corresponding abstract DIE exists (as described in the issue #55680). However, I don’t think this ever happens for concrete DIEs of lexical blocks. Concrete lexical scope DIEs are created only during the population of a concrete subprogram, specifically in DwarfCompileUnit::constructSubprogramScopeDIE, which is called from DwarfDebug::endFunctionImpl after all relevant abstract scopes are created.
In other words,
• DwarfCompileUnit::getOrCreateContextDIE can create a concrete subprogram DIE.
• DwarfCompileUnit::getOrCreateContextDIE never creates concrete lexical scope DIEs.
• Therefore, the code in question that handles already-existing concrete lexical scope DIEs is unnecessary.
I've reverted the change of DwarfCompileUnit::getOrCreateLexicalBlockDIE.
dwblaikie
left a comment
There was a problem hiding this comment.
a few thoughts - thanks @jmorse for taking a look at this too! (it's been a long term project and I'm more distant from LLVM over the course of it & getting a bit change-blind/struggling to keep up with the state of things)
clang/lib/CodeGen/CGVTables.cpp
Outdated
| // Some types may be still unresolved. As they can't be cloned, keep | ||
| // references to the types from the base subprogram. |
There was a problem hiding this comment.
"some" feels concerningly vague - could you be more specific?
| // FIXME: As a result, variables of cloned subprogram may refer to local types | ||
| // from base subprogram. In such case, type locality information is damaged. |
There was a problem hiding this comment.
FIXME is a bit unclear about what should be fixed, and explains more about the problem?
Perhaps the explanation should go above, and the FIXME should be more specific about what should be fixed?
| /// Move function-local enums from DICompileUnit's enums | ||
| /// to DISubprogram's retainedNodes. |
There was a problem hiding this comment.
This could probably go in a separate standalone patch?
There was a problem hiding this comment.
Do you mean separating out the non-functional, refactoring changes to upgradeCULocals?
If separating out upgradeCULocals change as a whole was meant, could you please clarify that? Should we allow local enums in both DISubprogram's retainedNodes: and DICompileUnit's enums: fields?
There was a problem hiding this comment.
I think the functional change of moving function-local enums from the CU to the Subprogram seems like it could be a distinct change? It has observable effects (so it's not NFC) but they can be implemented/tested separately from the rest of this work.
Maybe worth discussing the tradeoffs of that change too (like what happens if that function-local enum is referenced from somewhere else, like a template instantiation but then the original function is optimized away (not sure if we could quite get the stars to align with all those things, but maybe)) - but I feel this has all drawn out far enough so if you just want to go ahead with this, you could separate out that work without it being in a separate patch/review/etc.
There was a problem hiding this comment.
I think the functional change of moving function-local enums from the CU to the Subprogram seems like it could be a distinct change? It has observable effects (so it's not NFC) but they can be implemented/tested separately from the rest of this work.
IMO we definitely want to keep all local enums either in DICompileUnit's enums: or in DISubprogram's retainedNodes:, to simplify local types handling.
And we want to postpone their emission to DwarfDebug::endModule(), where we know for sure whether a local scope will have an abstract DIE or only a concrete DIE (to get rid of the hack made in #160786, where emission of abstract subprogram DIEs is split in two stages, at the cost of maintaining SP->llvm::Function map).
I assume, initially @chbessonova was trying to avoid complexity by implementing both of the things in one patch.
But I agree that we could achieve them by first allowing local enums being present in both DICompileUnit's enums: and in DISubprogram's retainedNodes:, and then moving the ownership of local enums completely to DISubprogram's retainedNodes: (as a separate patch).
but I feel this has all drawn out far enough so if you just want to go ahead with this, you could separate out that work without it being in a separate patch/review/etc.
I think I will take the approach above if the current merge attempt fails (again :). I can try merging stripped version of this PR, without local enums ownership transfer (if this part will be a culprit).
Maybe worth discussing the tradeoffs of that change too (like what happens if that function-local enum is referenced from somewhere else, like a template instantiation but then the original function is optimized away (not sure if we could quite get the stars to align with all those things, but maybe))
Will it create a problem for DWARF emission? If I understand your concern right, this is covered in llvm/test/DebugInfo/Generic/inlined-local-type.ll.
When it comes to keeping local enums tracked only by DICompileUnit's enums: instead of transfering the ownership to DISubprogram, I think we can achieve the same as what can be done with this PR. However, we will have to keep some mapping between subprograms and their local enums, so as not to skip emitting lexical blocks where only a local enum DIE is present, without DIEs for anything else (see logic in skipLexicalScope lambda in DwarfCompileUnit::createAndAddScopeChildren).
| @@ -703,13 +727,41 @@ class MetadataLoader::MetadataLoaderImpl { | |||
| return Error::success(); | |||
| } | |||
|
|
|||
| void upgradeDebugInfo(bool ModuleLevel) { | |||
| /// Specifies which kind of debug info upgrade should be performed. | |||
There was a problem hiding this comment.
Maybe there could be some more details in this comment about why there are different kinds of debug info upgrade?
There was a problem hiding this comment.
Added more detailed comment.
jmorse
left a comment
There was a problem hiding this comment.
Looked at the tests; only thing I've missed now is the unittests (out of time today).
funcimport-debug-retained-nodes.ll is enjoyably thorough -- I wonder whether it's so specific that it'll easily lose coverage of what it's testing though. Sometimes we use -debug output to ensure we're taking the correct codepath, would it be feasible to check that to ensure we're hitting the lazy-metadata-loading path? (This is usually discouraged, but given how hard it is to debug this area, IMO it's worth doing to avoid future quiet loss of coverage)
| // This test checks that the varargs thunk is correctly created if types of | ||
| // DILocalVariables of the base function are unresolved at the cloning time. |
There was a problem hiding this comment.
Could you elaborate on the test criteria -- as I understand it this test is to avoid a crash in a tricky situation where types have no full definition? If so, please say that explicitly, and what kind of DILocalVariable information should be produced (currently none / incorrect information).
(I'm thinking ahead to if/when this test fails and someone has to determine the intention behind it).
There was a problem hiding this comment.
Clarified that in the comment.
clang/test/DebugInfo/CXX/access.cpp
Outdated
| static int public_static; | ||
|
|
||
| protected: | ||
| // CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+3]],{{.*}} flags: DIFlagProtected) |
There was a problem hiding this comment.
I'm interested in why this is failing / necessary -- the '-DAG' suffix should mean the check lines are re-orderable anyway, and as far as I read the diff you're only changing the CHECK-line position and updating the relative-line-num calculation accordingly?
There was a problem hiding this comment.
Oops, it's a rebasing artifact. Reverted this change.
| // CHECK: !DILocalVariable(name: "c", {{.*}}, flags: DIFlagArtificial | ||
| // CHECK: !DILocalVariable( | ||
| // CHECK-NOT: name: | ||
| // CHECK: type: ![[UNION]] |
There was a problem hiding this comment.
Should this be CHECK-SAME, to ensure that we're on the same line as the nameless DILocalVariable? Otherwise this (while unlikely) could match an unrelated later type.
| ; RUN: llvm-as --disable-verify < %s -o %t0 | ||
| ; RUN: opt --passes=verify %t0 -o /dev/null | ||
| ; RUN: llvm-dis %t0 -o - | FileCheck %s --implicit-check-not=DICompositeType |
There was a problem hiding this comment.
This is a good test; but isn't the retainedNodes field going to be normalised by the first llvm-as, meaning that opt and llvm-dis only see a normalised input? If so, perhaps a round-trip test is sufficient, and something else is needed to exercise the metadata-loader for bitcode?
There was a problem hiding this comment.
Ouch, when making this PR, I moved the logic of the test to llvm/test/DebugInfo/X86/cleanup-retained-nodes.ll, llvm/test/DebugInfo/X86/llparser-cleanup-retained-nodes.ll (and changed it a bit).
But I dind't remove llvm/test/Bitcode/local-type-scope.ll. Done now.
I've removed extra opt invocations from [llparser-]cleanup-retained-nodes.ll.
| ; CHECK: distinct !DICompositeType(tag: DW_TAG_class_type, {{.*}}, identifier: "type_global_in_another_module") | ||
| ; CHECK: [[EMPTY:![0-9]+]] = !{} | ||
| ; CHECK: [[BAR1:![0-9]+]] = distinct !DISubprogram(name: "bar", {{.*}}, retainedNodes: [[RN_BAR1:![0-9]+]]) | ||
| ; CHECK: [[RN_BAR1]] = !{[[T1:![0-9]+]], [[T1:![0-9]+]], [[T1:![0-9]+]], [[T2:![0-9]+]]} |
There was a problem hiding this comment.
Each of these T1 variables capture, can the second and third just be [[T1]]? The fact that the same node appears multiple times is presumably something intended to be checked, to ensure type_global_in_another_module doesn't appear here.
There was a problem hiding this comment.
Thank you for the catch!
Original DISubprogram(name: "bar", ...) (before loading) has repeating "local_type" ([[T1]] in check lines). I did it to ensure that all occurences of "local_type" are removed from the clone of DISubprogram "bar". It is checked at the line:
; CHECK: {{![0-9]+}} = distinct !DISubprogram(name: "bar", {{.*}}, retainedNodes: [[EMPTY:![0-9]+]])
| ; CHECK: DW_TAG_subprogram | ||
| ; CHECK: DW_AT_abstract_origin {{.*}} "_Z3foov" | ||
|
|
||
| ; FIXME: 'struct B' should be in the abstract tree below, not here. |
There was a problem hiding this comment.
Could I request more indentation, or ';' characters at the start, to make this standout: otherwise it's the same width as CHECK: and could easily be mistaken for a check line.
| ; CHECK: DW_AT_abstract_origin {{.*}} "objA" | ||
| ; CHECK: NULL | ||
|
|
||
| %struct.B = type { i32 } |
There was a problem hiding this comment.
I could be misreading, but shouldn't we have some type information for "A" above, or otherwise something for the objA variable to refer to?
There was a problem hiding this comment.
I've added check lines for DW_TAG_structure DIE of "A".
| ; CHECK: ![[EMPTY:[0-9]+]] = !{} | ||
| ; CHECK: !DISubprogram(name: "inlined_out_clone", {{.*}}, retainedNodes: ![[EMPTY]] | ||
| ; CHECK: !DICompositeType({{.*}}, identifier: "local_type" | ||
| ; CHECK: !DISubprogram(name: "inlined_out_clone", {{.*}}, retainedNodes: ![[EMPTY]] |
There was a problem hiding this comment.
I wouldn't say I completely follow the premise but -- shouldn't we also check that the DICompositeType is in the correct scope?
There was a problem hiding this comment.
The primary purpose is to check that DISubprogram of the imported function has empty retained nodes list (cleaned up from the reference to the ODR-uniqued local type).
Indeed, DICompositeType should be in the scope of one of the "inlined_out_clone" subprograms. Added a check for scope and an explanatory comment.
| ; RUN: opt --bitcode-mdindex-threshold=0 -module-summary %s -o %t.bc | ||
| ; RUN: opt --bitcode-mdindex-threshold=0 -module-summary %p/Inputs/funcimport-debug-retained-nodes.ll -o %t2.bc | ||
| ; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc | ||
| ; RUN: llvm-lto --thinlto-action=run %t.bc %t2.bc --thinlto-save-temps=%t3 2>&1 | FileCheck --allow-empty --check-prefix=LTO %s | ||
| ; RUN: llvm-dis %t30.3.imported.bc -o - | FileCheck %s \ | ||
| ; RUN: --implicit-check-not='DISubprogram(name: "inlined_out_clone"' \ | ||
| ; RUN: --implicit-check-not='DICompositeType({{.*}}, identifier: "local_type"' |
There was a problem hiding this comment.
Great explanation above; these RUN lines should be above it though to meet the LLVM convention.
| ; Ensure that function-local types have the correct subprogram parent even if | ||
| ; those subprograms are inlined. |
There was a problem hiding this comment.
Could we specify which is the correct subprogram parent for future readers; the abstract subprogram, right?
…lock scopes (4/7) RFC https://discourse.llvm.org/t/rfc-dwarfdebug-fix-and-improve-handling-imported-entities-types-and-static-local-in-subprogram-and-lexical-block-scopes/68544 Similar to imported declarations, the patch tracks function-local types in DISubprogram's 'retainedNodes' field. DwarfDebug is adjusted in accordance with the aforementioned metadata change and provided a support of function-local types scoped within a lexical block. The patch assumes that DICompileUnit's 'enums field' no longer tracks local types and DwarfDebug would assert if any locally-scoped types get placed there. Reviewed By: jmmartinez Authored-by: Kristina Bessonova <[email protected]> Differential Revision: https://reviews.llvm.org/D144006 (cherry picked from commit 2953d4a) Signed-off-by: Jeremy Morse <[email protected]> Conflicts: llvm/lib/IR/DIBuilder.cpp llvm/lib/IR/DebugInfo.cpp llvm/lib/Transforms/Utils/CloneFunction.cpp
…exical block scopes (4/7)" This is an attempt to merge https://reviews.llvm.org/D144006 with LTO fix. The last merge attempt was llvm#75385. The issue with it was investigated in llvm#75385 (comment). If the same (in the sense of ODR identifier/ODR uniquing rules) local type is present in two modules, and these modules are linked together, the type gets uniqued. A DIType, that happens to be loaded first, survives linking, and the references on other types with the same ODR identifier from the modules loaded later are replaced with the references on the DIType loaded first. Since defintion subprograms, in scope of which these types are located, are not deduplicated, the linker output may contain multiple DISubprogram's having the same (uniqued) type in their retainedNodes lists. Further compilation of such modules causes crashes. To tackle that, * previous solution to handle LTO linking with local types in retainedNodes is removed (cloneLocalTypes() function), * for each loaded distinct (definition) DISubprogram, its retainedNodes list is scanned after loading, and DITypes with a scope of another subprogram are removed. If something from a Function corresponding to the DISubprogram references uniqued type, we rely on cross-CU links. With this approach, clang builds without crashes in FullLTO (which is not the case for llvm#75385). Additionally: * a check is added to Verifier to report about local types located in a wrong retainedNodes list, * DIBuilder's methods for type creation are updated, as https://reviews.llvm.org/D144006 has gotten slightly out-of-date. Commit llvm#75385 and the new changes are placed in separate commits to simplify review process.
…e cloned CGVTables: hide unresolved local types from ValueMapper
332fa01 to
5176fec
Compare
|
Thank you @jmorse and @dwblaikie for the rich and detailed feedback — this is very helpful! Sorry for the delay, I was out of office for quite some time. Now I've updated the PR to address the comments. |
Yes, that's right.
There is no such protection, as far as I understand. createIdentityMDPredicate was rather made to speed up function cloning/metadata values (re)mapping, not to protect against type cloning in particular.
The most concerning part for me is type units generation. LLVM uses "type identifier+CU" pair to generate type signature to distinguish different type units. Technically, we can get multiple type units emitted with the same signature for cloned types. But I'm not sure how bad it is, since such units essentially represent the same type (although placed in different scopes). I would appreciate any advice on that. Probably, it will be easier (and still provide debug info improvement) if we choose to clean local types from retainedNodes of a cloned function in CloneFunctionInto(), and rely on cross-subprogram references (similarly to how this PR is trying to handle the case of ODR-uniquing during LTO), instead of dealing with consequences of mutliple local types having the same ID. |
jmorse
left a comment
There was a problem hiding this comment.
Thanks for sticking with this; github has done its favourite thing of chucking away half the comments, so it's a bit difficult to re-review. Looking at what I wrote last time, I think everything's been addressed, I would only add that you could put the explanation of the MetadataLoader.cpp upgradeCULocals function into a comment there for future reference.
This LGTM, modulo Davids comments.
|
Thank you! I've added upgradeCULocals algorithm description as a comment. Will wait for David's response. |
dwblaikie
left a comment
There was a problem hiding this comment.
Some optional thoughts
|
Thank you! |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/66/builds/25891 Here is the relevant piece of the build log for the reference |
…s in DIBuilder Fix a regression introduced by llvm#165032 where DIBuilder could attach local metadata nodes to the wrong subprogram during finalization. DIBuilder tracks local variables, labels, and types in `DIBuilder::SubprogramTrackedNodes` and later attaches them to their parent subprogram's retainedNodes in `finalizeSubprogram()`. However, temporary local types created via `createReplaceableCompositeType()` may later be replaced by a type with a different scope. DIBuilder does not currently verify that the scopes of the original and replacement types match. As a result, local types can be incorrectly attached to the retainedNodes of an unrelated subprogram. This issue is observable in clang with limited debug info mode (see `clang/test/DebugInfo/CXX/ctor-homing-local-type.cpp`). This patch updates DIBuilder::finalizeSubprogram() to verify that tracked metadata nodes still belong to the subprogram being finalized, and skips nodes whose scopes no longer match.
|
This PR has introduced a clang regression in limited debug info mode. A fix is proposed in #180294. |
…exical block scopes (4/7)" (llvm#165032) This is an attempt to merge https://reviews.llvm.org/D144006 with LTO fix. The last merge attempt was llvm#75385. The issue with it was investigated in llvm#75385 (comment). The problem happens when 1. Several modules are being linked. 2. There are several DISubprograms that initially belong to different modules but represent the same source code function (for example, a function included from the same source code file). 3. Some of such DISubprograms survive IR linking. It may happen if one of them is inlined somewhere or if the functions that have these DISubprograms attached have internal linkage. 4. Each of these DISubprograms has a local type that corresponds to the same source code type. These types are initially from different modules, but have the same ODR identifier. If the same (in the sense of ODR identifier/ODR uniquing rules) local type is present in two modules, and these modules are linked together, the type gets uniqued. A DIType, that happens to be loaded first, survives linking, and the references on other types with the same ODR identifier from the modules loaded later are replaced with the references on the DIType loaded first. Since defintion subprograms, in scope of which these types are located, are not deduplicated, the linker output may contain multiple DISubprogram's having the same (uniqued) type in their retainedNodes lists. Further compilation of such modules causes crashes. To tackle that, * previous solution to handle LTO linking with local types in retainedNodes is removed (cloneLocalTypes() function), * for each loaded distinct (definition) DISubprogram, its retainedNodes list is scanned after loading, and DITypes with a scope of another subprogram are removed. If something from a Function corresponding to the DISubprogram references uniqued type, we rely on cross-CU links. Additionally: * a check is added to Verifier to report about local types located in a wrong retainedNodes list, Original commit message follows. --------- RFC https://discourse.llvm.org/t/rfc-dwarfdebug-fix-and-improve-handling-imported-entities-types-and-static-local-in-subprogram-and-lexical-block-scopes/68544 Similar to imported declarations, the patch tracks function-local types in DISubprogram's 'retainedNodes' field. DwarfDebug is adjusted in accordance with the aforementioned metadata change and provided a support of function-local types scoped within a lexical block. The patch assumes that DICompileUnit's 'enums field' no longer tracks local types and DwarfDebug would assert if any locally-scoped types get placed there. Authored-by: Kristina Bessonova <[email protected]> Co-authored-by: Jeremy Morse <[email protected]>
…rams in DIBuilder (#180294) Fix a regression introduced by #165032, where DIBuilder could attach local metadata nodes to the wrong subprogram during finalization. DIBuilder records freshly created local variables, labels, and types in `DIBuilder::SubprogramTrackedNodes`, and later attaches them to their parent subprogram's retainedNodes in `finalizeSubprogram()`. However, a temporary local type created via `createReplaceableCompositeType()` may later be replaced by a type with a different scope. DIBuilder does not currently verify that the scopes of the original and replacement types match. As a result, local types can be incorrectly attached to the retainedNodes of an unrelated subprogram. This issue is observable in clang with limited debug info mode (see `clang/test/DebugInfo/CXX/ctor-homing-local-type.cpp`). This patch updates `DIBuilder::finalizeSubprogram()` to verify that tracked metadata nodes still belong to the subprogram being finalized, and avoids adding nodes whose scopes no longer match to retainedNodes field of an unrelated subprogram.
…ted subprograms in DIBuilder (#180294) Fix a regression introduced by llvm/llvm-project#165032, where DIBuilder could attach local metadata nodes to the wrong subprogram during finalization. DIBuilder records freshly created local variables, labels, and types in `DIBuilder::SubprogramTrackedNodes`, and later attaches them to their parent subprogram's retainedNodes in `finalizeSubprogram()`. However, a temporary local type created via `createReplaceableCompositeType()` may later be replaced by a type with a different scope. DIBuilder does not currently verify that the scopes of the original and replacement types match. As a result, local types can be incorrectly attached to the retainedNodes of an unrelated subprogram. This issue is observable in clang with limited debug info mode (see `clang/test/DebugInfo/CXX/ctor-homing-local-type.cpp`). This patch updates `DIBuilder::finalizeSubprogram()` to verify that tracked metadata nodes still belong to the subprogram being finalized, and avoids adding nodes whose scopes no longer match to retainedNodes field of an unrelated subprogram.
Since llvm#165032, DwarfDebug asserts if function-local enums are present in the enums field of DICompileUnit. This patch adds a check to the Verifier to detect such invalid IR earlier. Incorrect occurence of a local enum in DICompileUnit's enums field in llvm/test/DebugInfo/COFF/enum-co.ll is fixed. This change is extracted from https://reviews.llvm.org/D144008.
…185228) Since #165032, DwarfDebug asserts if function-local enums are present in the enums field of DICompileUnit. This patch adds a check to the Verifier to detect such invalid IR earlier. Incorrect occurence of a local enum in DICompileUnit's enums field in `llvm/test/DebugInfo/COFF/enum-co.ll` is fixed. This change is extracted from https://reviews.llvm.org/D144008.
…lvm#185228) Since llvm#165032, DwarfDebug asserts if function-local enums are present in the enums field of DICompileUnit. This patch adds a check to the Verifier to detect such invalid IR earlier. Incorrect occurence of a local enum in DICompileUnit's enums field in `llvm/test/DebugInfo/COFF/enum-co.ll` is fixed. This change is extracted from https://reviews.llvm.org/D144008.
This is an attempt to merge https://reviews.llvm.org/D144006 with LTO fix.
The last merge attempt was #75385.
The issue with it was investigated in #75385 (comment).
The problem happens when
If the same (in the sense of ODR identifier/ODR uniquing rules) local type is present in two modules, and these modules are linked together, the type gets uniqued. A DIType, that happens to be loaded first, survives linking, and the references on other types with the same ODR identifier from the modules loaded later are replaced with the references on the DIType loaded first. Since defintion subprograms, in scope of which these types are located, are not deduplicated, the linker output may contain multiple DISubprogram's having the same (uniqued) type in their retainedNodes lists.
Further compilation of such modules causes crashes.
To tackle that,
With this approach, clang builds without crashes in FullLTO (which is not the case for #75385).
Additionally:
Commit #75385 and the new changes are separate commits to simplify review process.