mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 09:06:06 +00:00
[DebugMetadata][DwarfDebug] Support function-local types in lexical block 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 <kbessonova@accesssoftek.com> Differential Revision: https://reviews.llvm.org/D144006
This commit is contained in:
parent
98bd0d9dd2
commit
3b449bd46a
@ -8,23 +8,23 @@ int main(int argc, char* argv[], char* arge[]) {
|
|||||||
//
|
//
|
||||||
struct { int bar; } one = {42};
|
struct { int bar; } one = {42};
|
||||||
//
|
//
|
||||||
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
// LINUX: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType(
|
||||||
// LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
|
|
||||||
// LINUX-SAME: )
|
|
||||||
// LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType(
|
|
||||||
// LINUX-SAME: tag: DW_TAG_structure_type
|
// LINUX-SAME: tag: DW_TAG_structure_type
|
||||||
// LINUX-NOT: name:
|
// LINUX-NOT: name:
|
||||||
// LINUX-NOT: identifier:
|
// LINUX-NOT: identifier:
|
||||||
// LINUX-SAME: )
|
// LINUX-SAME: )
|
||||||
|
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
||||||
|
// LINUX-SAME: type: [[TYPE_OF_ONE]]
|
||||||
|
// LINUX-SAME: )
|
||||||
//
|
//
|
||||||
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
// MSVC: [[TYPE_OF_ONE:![0-9]+]] = distinct !DICompositeType
|
||||||
// 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: tag: DW_TAG_structure_type
|
||||||
// MSVC-NOT: name:
|
// MSVC-NOT: name:
|
||||||
// MSVC-NOT: identifier:
|
// MSVC-NOT: identifier:
|
||||||
// MSVC-SAME: )
|
// MSVC-SAME: )
|
||||||
|
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
||||||
|
// MSVC-SAME: type: [[TYPE_OF_ONE]]
|
||||||
|
// MSVC-SAME: )
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -18,13 +18,15 @@ void quux(void) {
|
|||||||
// CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]]
|
// CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]]
|
||||||
// CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar"
|
// CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "bar"
|
||||||
// CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAR"
|
// CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAR"
|
||||||
// CHECK: [[TYPE2:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z"
|
// CHECK: [[RETTYPES]] = !{[[TYPE2:![0-9]+]], [[TYPE3:![0-9]+]], [[TYPE0]], [[TYPE4:![0-9]+]], {{![0-9]+}}}
|
||||||
// CHECK: [[TYPE3:![0-9]+]] = !DIEnumerator(name: "Z"
|
// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int"
|
||||||
// CHECK: [[RETTYPES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]], [[TYPE0]], [[TYPE6:![0-9]+]], {{![0-9]+}}, [[TYPE7:![0-9]+]], [[TYPE2]], [[TYPE8:![0-9]+]]}
|
// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
|
||||||
// CHECK: [[TYPE4]] = !DIDerivedType(tag: DW_TAG_typedef, name: "my_int"
|
// CHECK: [[TYPE4]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz"
|
||||||
// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo"
|
// CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]]
|
||||||
// CHECK: [[TYPE6]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "baz"
|
// CHECK: [[SPRETNODES]] = !{[[TYPE5:![0-9]+]], [[TYPE6:![0-9]+]], [[TYPE8:![0-9]+]]}
|
||||||
// CHECK: [[TYPE7]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "y"
|
// 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: [[TYPE8]] = distinct !DICompositeType(tag: DW_TAG_union_type, name: "w"
|
||||||
|
|
||||||
// Check that debug info is not emitted for the typedef, struct, enum, and
|
// Check that debug info is not emitted for the typedef, struct, enum, and
|
||||||
|
@ -13,12 +13,14 @@ void quux() {
|
|||||||
// CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]]
|
// CHECK: !DICompileUnit{{.+}}retainedTypes: [[RETTYPES:![0-9]+]]
|
||||||
// CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz"
|
// CHECK: [[TYPE0:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "baz"
|
||||||
// CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAZ"
|
// CHECK: [[TYPE1:![0-9]+]] = !DIEnumerator(name: "BAZ"
|
||||||
// CHECK: [[TYPE2:![0-9]+]] = !DICompositeType(tag: DW_TAG_enumeration_type, name: "z"
|
// CHECK: [[RETTYPES]] = !{[[TYPE2:![0-9]+]], [[TYPE3:![0-9]+]], [[TYPE0]], {{![0-9]+}}}
|
||||||
// CHECK: [[TYPE3:![0-9]+]] = !DIEnumerator(name: "Z"
|
// CHECK: [[TYPE2]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo"
|
||||||
// CHECK: [[RETTYPES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]], [[TYPE0]], {{![0-9]+}}, [[TYPE6:![0-9]+]], [[TYPE2]]}
|
// CHECK: [[TYPE3]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar"
|
||||||
// CHECK: [[TYPE4]] = !DIDerivedType(tag: DW_TAG_typedef, name: "foo"
|
// CHECK: [[SP:![0-9]+]] = distinct !DISubprogram(name: "quux", {{.*}}, retainedNodes: [[SPRETNODES:![0-9]+]]
|
||||||
// CHECK: [[TYPE5]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "bar"
|
// CHECK: [[SPRETNODES]] = !{[[TYPE4:![0-9]+]], [[TYPE5:![0-9]+]]}
|
||||||
// CHECK: [[TYPE6]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "y"
|
// 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}}
|
// NODBG-NOT: !DI{{CompositeType|Enumerator|DerivedType}}
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ public:
|
|||||||
static int public_static;
|
static int public_static;
|
||||||
|
|
||||||
protected:
|
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)
|
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_typedef",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected)
|
||||||
typedef int prot_typedef;
|
typedef int prot_typedef;
|
||||||
// CHECK-DAG: !DIDerivedType(tag: DW_TAG_typedef, name: "prot_using",{{.*}} line: [[@LINE+1]],{{.*}} flags: DIFlagProtected)
|
|
||||||
using prot_using = prot_typedef;
|
using prot_using = prot_typedef;
|
||||||
prot_using prot_member;
|
prot_using prot_member;
|
||||||
|
|
||||||
|
@ -51,13 +51,13 @@ void instantiate(int x) {
|
|||||||
// CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true
|
// CHECK: !DIGlobalVariable(name: "b",{{.*}} file: [[FILE]], line: 6,{{.*}} isLocal: true, isDefinition: true
|
||||||
// CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true
|
// CHECK: !DIGlobalVariable(name: "result", {{.*}} isLocal: false, isDefinition: true
|
||||||
// CHECK: !DIGlobalVariable(name: "value", {{.*}} isLocal: false, isDefinition: true
|
// CHECK: !DIGlobalVariable(name: "value", {{.*}} isLocal: false, isDefinition: true
|
||||||
// CHECK: !DILocalVariable(name: "i", {{.*}}, flags: DIFlagArtificial
|
// CHECK: ![[UNION:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_union_type,
|
||||||
// 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-NOT: name:
|
// CHECK-NOT: name:
|
||||||
// CHECK: elements
|
// CHECK: elements
|
||||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i", scope: ![[UNION]],
|
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i", scope: ![[UNION]],
|
||||||
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "c", 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]]
|
||||||
|
@ -3,6 +3,60 @@
|
|||||||
|
|
||||||
int main(int argc, char* argv[], char* arge[]) {
|
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
|
// In CodeView, the LF_MFUNCTION entry for "bar()" refers to the forward
|
||||||
// reference of the unnamed struct. Visual Studio requires a unique
|
// reference of the unnamed struct. Visual Studio requires a unique
|
||||||
// identifier to match the LF_STRUCTURE forward reference to the definition.
|
// identifier to match the LF_STRUCTURE forward reference to the definition.
|
||||||
@ -10,21 +64,11 @@ int main(int argc, char* argv[], char* arge[]) {
|
|||||||
struct { void bar() {} } one;
|
struct { void bar() {} } one;
|
||||||
//
|
//
|
||||||
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
||||||
// LINUX-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
|
// LINUX-SAME: type: [[TYPE_OF_ONE]]
|
||||||
// LINUX-SAME: )
|
|
||||||
// LINUX: [[TYPE_OF_ONE]] = distinct !DICompositeType(
|
|
||||||
// LINUX-SAME: tag: DW_TAG_structure_type
|
|
||||||
// LINUX-NOT: name:
|
|
||||||
// LINUX-NOT: identifier:
|
|
||||||
// LINUX-SAME: )
|
// LINUX-SAME: )
|
||||||
//
|
//
|
||||||
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "one"
|
||||||
// MSVC-SAME: type: [[TYPE_OF_ONE:![0-9]+]]
|
// MSVC-SAME: type: [[TYPE_OF_ONE]]
|
||||||
// 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: )
|
// MSVC-SAME: )
|
||||||
|
|
||||||
|
|
||||||
@ -36,21 +80,11 @@ int main(int argc, char* argv[], char* arge[]) {
|
|||||||
int decltype(two)::*ptr2unnamed = &decltype(two)::bar;
|
int decltype(two)::*ptr2unnamed = &decltype(two)::bar;
|
||||||
//
|
//
|
||||||
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two"
|
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "two"
|
||||||
// LINUX-SAME: type: [[TYPE_OF_TWO:![0-9]+]]
|
// LINUX-SAME: type: [[TYPE_OF_TWO]]
|
||||||
// LINUX-SAME: )
|
|
||||||
// LINUX: [[TYPE_OF_TWO]] = distinct !DICompositeType(
|
|
||||||
// LINUX-SAME: tag: DW_TAG_structure_type
|
|
||||||
// LINUX-NOT: name:
|
|
||||||
// LINUX-NOT: identifier:
|
|
||||||
// LINUX-SAME: )
|
// LINUX-SAME: )
|
||||||
//
|
//
|
||||||
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two"
|
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "two"
|
||||||
// MSVC-SAME: type: [[TYPE_OF_TWO:![0-9]+]]
|
// MSVC-SAME: type: [[TYPE_OF_TWO]]
|
||||||
// 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: )
|
// MSVC-SAME: )
|
||||||
|
|
||||||
|
|
||||||
@ -61,21 +95,11 @@ int main(int argc, char* argv[], char* arge[]) {
|
|||||||
struct named { int bar; int named::* p2mem; } three = { 42, &named::bar };
|
struct named { int bar; int named::* p2mem; } three = { 42, &named::bar };
|
||||||
//
|
//
|
||||||
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three"
|
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "three"
|
||||||
// LINUX-SAME: type: [[TYPE_OF_THREE:![0-9]+]]
|
// LINUX-SAME: type: [[TYPE_OF_THREE]]
|
||||||
// LINUX-SAME: )
|
|
||||||
// LINUX: [[TYPE_OF_THREE]] = distinct !DICompositeType(
|
|
||||||
// LINUX-SAME: tag: DW_TAG_structure_type
|
|
||||||
// LINUX-SAME: name: "named"
|
|
||||||
// LINUX-NOT: identifier:
|
|
||||||
// LINUX-SAME: )
|
// LINUX-SAME: )
|
||||||
//
|
//
|
||||||
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three"
|
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "three"
|
||||||
// MSVC-SAME: type: [[TYPE_OF_THREE:![0-9]+]]
|
// MSVC-SAME: type: [[TYPE_OF_THREE]]
|
||||||
// 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: )
|
// MSVC-SAME: )
|
||||||
|
|
||||||
|
|
||||||
@ -87,21 +111,11 @@ int main(int argc, char* argv[], char* arge[]) {
|
|||||||
auto four = [argc](int i) -> int { return argc == i ? 1 : 0; };
|
auto four = [argc](int i) -> int { return argc == i ? 1 : 0; };
|
||||||
//
|
//
|
||||||
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four"
|
// LINUX: !{{[0-9]+}} = !DILocalVariable(name: "four"
|
||||||
// LINUX-SAME: type: [[TYPE_OF_FOUR:![0-9]+]]
|
// LINUX-SAME: type: [[TYPE_OF_FOUR]]
|
||||||
// LINUX-SAME: )
|
|
||||||
// LINUX: [[TYPE_OF_FOUR]] = distinct !DICompositeType(
|
|
||||||
// LINUX-SAME: tag: DW_TAG_class_type
|
|
||||||
// LINUX-NOT: name:
|
|
||||||
// LINUX-NOT: identifier:
|
|
||||||
// LINUX-SAME: )
|
// LINUX-SAME: )
|
||||||
//
|
//
|
||||||
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four"
|
// MSVC: !{{[0-9]+}} = !DILocalVariable(name: "four"
|
||||||
// MSVC-SAME: type: [[TYPE_OF_FOUR:![0-9]+]]
|
// MSVC-SAME: type: [[TYPE_OF_FOUR]]
|
||||||
// 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: )
|
// MSVC-SAME: )
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -51,9 +51,9 @@ void test() {
|
|||||||
// CHECK-SAME: name: "<lambda_2_1>",
|
// CHECK-SAME: name: "<lambda_2_1>",
|
||||||
c.lambda_params();
|
c.lambda_params();
|
||||||
|
|
||||||
// CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1:[0-9]+]],
|
// CHECK: ![[LAMBDA1:[0-9]+]] = !DICompositeType(tag: DW_TAG_class_type,
|
||||||
// CHECK: ![[LAMBDA1]] = !DICompositeType(tag: DW_TAG_class_type,
|
|
||||||
// CHECK-SAME: name: "<lambda_1>",
|
// CHECK-SAME: name: "<lambda_1>",
|
||||||
// CHECK-SAME: flags: DIFlagFwdDecl
|
// CHECK-SAME: flags: DIFlagFwdDecl
|
||||||
|
// CHECK: !DISubprogram(name: "operator()", scope: ![[LAMBDA1]],
|
||||||
c.lambda2();
|
c.lambda2();
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@ int D::d(int x) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CHECK: ![[D:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "D",
|
// 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: !DIDerivedType(tag: DW_TAG_member, name: "this",
|
||||||
// CHECK-SAME: line: 11
|
// CHECK-SAME: line: 11
|
||||||
// CHECK-SAME: baseType: ![[POINTER]]
|
// CHECK-SAME: baseType: ![[POINTER:[0-9]+]]
|
||||||
// CHECK-SAME: size: 64
|
// CHECK-SAME: size: 64
|
||||||
// CHECK-NOT: offset: 0
|
// CHECK-NOT: offset: 0
|
||||||
// CHECK-SAME: ){{$}}
|
// CHECK-SAME: ){{$}}
|
||||||
|
// CHECK: ![[POINTER]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: ![[D]], size: 64)
|
||||||
|
@ -49,7 +49,7 @@ namespace llvm {
|
|||||||
Function *LabelFn; ///< llvm.dbg.label
|
Function *LabelFn; ///< llvm.dbg.label
|
||||||
Function *AssignFn; ///< llvm.dbg.assign
|
Function *AssignFn; ///< llvm.dbg.assign
|
||||||
|
|
||||||
SmallVector<TrackingMDNodeRef, 4> AllEnumTypes;
|
SmallVector<TrackingMDNodeRef, 4> EnumTypes;
|
||||||
/// Track the RetainTypes, since they can be updated later on.
|
/// Track the RetainTypes, since they can be updated later on.
|
||||||
SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
|
SmallVector<TrackingMDNodeRef, 4> AllRetainTypes;
|
||||||
SmallVector<DISubprogram *, 4> AllSubprograms;
|
SmallVector<DISubprogram *, 4> AllSubprograms;
|
||||||
@ -64,8 +64,8 @@ namespace llvm {
|
|||||||
SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
|
SmallVector<TrackingMDNodeRef, 4> UnresolvedNodes;
|
||||||
bool AllowUnresolvedNodes;
|
bool AllowUnresolvedNodes;
|
||||||
|
|
||||||
/// Each subprogram's preserved local variables, labels and imported
|
/// Each subprogram's preserved local variables, labels, imported entities,
|
||||||
/// entities.
|
/// and types.
|
||||||
///
|
///
|
||||||
/// Do not use a std::vector. Some versions of libc++ apparently copy
|
/// Do not use a std::vector. Some versions of libc++ apparently copy
|
||||||
/// instead of move on grow operations, and TrackingMDRef is expensive to
|
/// instead of move on grow operations, and TrackingMDRef is expensive to
|
||||||
|
@ -114,6 +114,7 @@ private:
|
|||||||
void processCompileUnit(DICompileUnit *CU);
|
void processCompileUnit(DICompileUnit *CU);
|
||||||
void processScope(DIScope *Scope);
|
void processScope(DIScope *Scope);
|
||||||
void processType(DIType *DT);
|
void processType(DIType *DT);
|
||||||
|
void processLocalVariable(DILocalVariable *DV);
|
||||||
bool addCompileUnit(DICompileUnit *CU);
|
bool addCompileUnit(DICompileUnit *CU);
|
||||||
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
|
bool addGlobalVariable(DIGlobalVariableExpression *DIG);
|
||||||
bool addScope(DIScope *Scope);
|
bool addScope(DIScope *Scope);
|
||||||
|
@ -547,6 +547,8 @@ class MetadataLoader::MetadataLoaderImpl {
|
|||||||
|
|
||||||
/// Move local imports from DICompileUnit's 'imports' field to
|
/// Move local imports from DICompileUnit's 'imports' field to
|
||||||
/// DISubprogram's retainedNodes.
|
/// DISubprogram's retainedNodes.
|
||||||
|
/// Move fucntion-local enums from DICompileUnit's enums
|
||||||
|
/// to DISubprogram's retainedNodes.
|
||||||
void upgradeCULocals() {
|
void upgradeCULocals() {
|
||||||
if (NamedMDNode *CUNodes = TheModule.getNamedMetadata("llvm.dbg.cu")) {
|
if (NamedMDNode *CUNodes = TheModule.getNamedMetadata("llvm.dbg.cu")) {
|
||||||
for (unsigned I = 0, E = CUNodes->getNumOperands(); I != E; ++I) {
|
for (unsigned I = 0, E = CUNodes->getNumOperands(); I != E; ++I) {
|
||||||
@ -554,48 +556,66 @@ class MetadataLoader::MetadataLoaderImpl {
|
|||||||
if (!CU)
|
if (!CU)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (CU->getRawImportedEntities()) {
|
SetVector<Metadata *> MetadataToRemove;
|
||||||
// Collect a set of imported entities to be moved.
|
// Collect imported entities to be moved.
|
||||||
SetVector<Metadata *> EntitiesToRemove;
|
if (CU->getRawImportedEntities())
|
||||||
for (Metadata *Op : CU->getImportedEntities()->operands()) {
|
for (Metadata *Op : CU->getImportedEntities()->operands()) {
|
||||||
auto *IE = cast<DIImportedEntity>(Op);
|
auto *IE = cast<DIImportedEntity>(Op);
|
||||||
if (dyn_cast_or_null<DILocalScope>(IE->getScope())) {
|
if (dyn_cast_or_null<DILocalScope>(IE->getScope()))
|
||||||
EntitiesToRemove.insert(IE);
|
MetadataToRemove.insert(IE);
|
||||||
}
|
}
|
||||||
|
// Collect enums to be moved.
|
||||||
|
if (CU->getRawEnumTypes())
|
||||||
|
for (Metadata *Op : CU->getEnumTypes()->operands()) {
|
||||||
|
auto *Enum = cast<DICompositeType>(Op);
|
||||||
|
if (dyn_cast_or_null<DILocalScope>(Enum->getScope()))
|
||||||
|
MetadataToRemove.insert(Enum);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!EntitiesToRemove.empty()) {
|
if (!MetadataToRemove.empty()) {
|
||||||
// Make a new list of CU's 'imports'.
|
// Make a new list of CU's 'imports'.
|
||||||
SmallVector<Metadata *> NewImports;
|
SmallVector<Metadata *> NewImports;
|
||||||
for (Metadata *Op : CU->getImportedEntities()->operands()) {
|
if (CU->getRawImportedEntities())
|
||||||
if (!EntitiesToRemove.contains(cast<DIImportedEntity>(Op))) {
|
for (Metadata *Op : CU->getImportedEntities()->operands())
|
||||||
|
if (!MetadataToRemove.contains(Op))
|
||||||
NewImports.push_back(Op);
|
NewImports.push_back(Op);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find DISubprogram corresponding to each entity.
|
// Make a new list of CU's 'enums'.
|
||||||
std::map<DISubprogram *, SmallVector<Metadata *>> SPToEntities;
|
SmallVector<Metadata *> NewEnums;
|
||||||
for (auto *I : EntitiesToRemove) {
|
if (CU->getRawEnumTypes())
|
||||||
auto *Entity = cast<DIImportedEntity>(I);
|
for (Metadata *Op : CU->getEnumTypes()->operands())
|
||||||
if (auto *SP = findEnclosingSubprogram(
|
if (!MetadataToRemove.contains(Op))
|
||||||
cast<DILocalScope>(Entity->getScope()))) {
|
NewEnums.push_back(Op);
|
||||||
SPToEntities[SP].push_back(Entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update DISubprograms' retainedNodes.
|
// Find DISubprogram corresponding to each entity.
|
||||||
for (auto I = SPToEntities.begin(); I != SPToEntities.end(); ++I) {
|
std::map<DISubprogram *, SmallVector<Metadata *>> SPToEntities;
|
||||||
auto *SP = I->first;
|
for (auto *I : MetadataToRemove) {
|
||||||
auto RetainedNodes = SP->getRetainedNodes();
|
DILocalScope *Scope = nullptr;
|
||||||
SmallVector<Metadata *> MDs(RetainedNodes.begin(),
|
if (auto *Entity = dyn_cast<DIImportedEntity>(I))
|
||||||
RetainedNodes.end());
|
Scope = cast<DILocalScope>(Entity->getScope());
|
||||||
MDs.append(I->second);
|
else if (auto *Enum = dyn_cast<DICompositeType>(I))
|
||||||
SP->replaceRetainedNodes(MDNode::get(Context, MDs));
|
Scope = cast<DILocalScope>(Enum->getScope());
|
||||||
}
|
|
||||||
|
|
||||||
// Remove entities with local scope from CU.
|
if (auto *SP = findEnclosingSubprogram(Scope))
|
||||||
CU->replaceImportedEntities(MDTuple::get(Context, NewImports));
|
SPToEntities[SP].push_back(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update DISubprograms' retainedNodes.
|
||||||
|
for (auto I = SPToEntities.begin(); I != SPToEntities.end(); ++I) {
|
||||||
|
auto *SP = I->first;
|
||||||
|
auto RetainedNodes = SP->getRetainedNodes();
|
||||||
|
SmallVector<Metadata *> MDs(RetainedNodes.begin(),
|
||||||
|
RetainedNodes.end());
|
||||||
|
MDs.append(I->second);
|
||||||
|
SP->replaceRetainedNodes(MDNode::get(Context, MDs));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove entities with local scope from CU.
|
||||||
|
if (CU->getRawImportedEntities())
|
||||||
|
CU->replaceImportedEntities(MDTuple::get(Context, NewImports));
|
||||||
|
// Remove enums with local scope from CU.
|
||||||
|
if (CU->getRawEnumTypes())
|
||||||
|
CU->replaceEnumTypes(MDTuple::get(Context, NewEnums));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -711,6 +731,29 @@ class MetadataLoader::MetadataLoaderImpl {
|
|||||||
upgradeCULocals();
|
upgradeCULocals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cloneLocalTypes() {
|
||||||
|
for (unsigned I = 0; I < MetadataList.size(); ++I) {
|
||||||
|
if (auto *SP = dyn_cast_or_null<DISubprogram>(MetadataList[I])) {
|
||||||
|
auto RetainedNodes = SP->getRetainedNodes();
|
||||||
|
SmallVector<Metadata *> MDs(RetainedNodes.begin(), RetainedNodes.end());
|
||||||
|
bool HasChanged = false;
|
||||||
|
for (auto &N : MDs)
|
||||||
|
if (auto *T = dyn_cast<DIType>(N))
|
||||||
|
if (auto *LS = dyn_cast_or_null<DILocalScope>(T->getScope()))
|
||||||
|
if (auto *Parent = findEnclosingSubprogram(LS))
|
||||||
|
if (Parent != SP) {
|
||||||
|
HasChanged = true;
|
||||||
|
auto NewT = T->clone();
|
||||||
|
NewT->replaceOperandWith(1, SP);
|
||||||
|
N = MDNode::replaceWithUniqued(std::move(NewT));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasChanged)
|
||||||
|
SP->replaceRetainedNodes(MDNode::get(Context, MDs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void callMDTypeCallback(Metadata **Val, unsigned TypeID);
|
void callMDTypeCallback(Metadata **Val, unsigned TypeID);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -1086,6 +1129,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
|||||||
// placeholders, that we flush here.
|
// placeholders, that we flush here.
|
||||||
resolveForwardRefsAndPlaceholders(Placeholders);
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
||||||
upgradeDebugInfo(ModuleLevel);
|
upgradeDebugInfo(ModuleLevel);
|
||||||
|
cloneLocalTypes();
|
||||||
// Return at the beginning of the block, since it is easy to skip it
|
// Return at the beginning of the block, since it is easy to skip it
|
||||||
// entirely from there.
|
// entirely from there.
|
||||||
Stream.ReadBlockEnd(); // Pop the abbrev block context.
|
Stream.ReadBlockEnd(); // Pop the abbrev block context.
|
||||||
@ -1117,6 +1161,7 @@ Error MetadataLoader::MetadataLoaderImpl::parseMetadata(bool ModuleLevel) {
|
|||||||
case BitstreamEntry::EndBlock:
|
case BitstreamEntry::EndBlock:
|
||||||
resolveForwardRefsAndPlaceholders(Placeholders);
|
resolveForwardRefsAndPlaceholders(Placeholders);
|
||||||
upgradeDebugInfo(ModuleLevel);
|
upgradeDebugInfo(ModuleLevel);
|
||||||
|
cloneLocalTypes();
|
||||||
return Error::success();
|
return Error::success();
|
||||||
case BitstreamEntry::Record:
|
case BitstreamEntry::Record:
|
||||||
// The interesting case.
|
// The interesting case.
|
||||||
|
@ -592,10 +592,9 @@ void DwarfCompileUnit::constructScopeDIE(LexicalScope *Scope,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Emit lexical blocks.
|
// Emit lexical blocks.
|
||||||
DIE *ScopeDIE = constructLexicalScopeDIE(Scope);
|
DIE *ScopeDIE = getOrCreateLexicalBlockDIE(Scope, ParentScopeDIE);
|
||||||
assert(ScopeDIE && "Scope DIE should not be null.");
|
assert(ScopeDIE && "Scope DIE should not be null.");
|
||||||
|
|
||||||
ParentScopeDIE.addChild(ScopeDIE);
|
|
||||||
createAndAddScopeChildren(Scope, *ScopeDIE);
|
createAndAddScopeChildren(Scope, *ScopeDIE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,24 +714,39 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope,
|
|||||||
return ScopeDIE;
|
return ScopeDIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct new DW_TAG_lexical_block for this scope and attach
|
DIE *DwarfCompileUnit::getOrCreateLexicalBlockDIE(LexicalScope *Scope,
|
||||||
// DW_AT_low_pc/DW_AT_high_pc labels.
|
DIE &ParentScopeDIE) {
|
||||||
DIE *DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) {
|
|
||||||
if (DD->isLexicalScopeDIENull(Scope))
|
if (DD->isLexicalScopeDIENull(Scope))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
const auto *DS = Scope->getScopeNode();
|
const auto *DS = Scope->getScopeNode();
|
||||||
|
DIE *ScopeDIE = nullptr;
|
||||||
|
|
||||||
auto ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block);
|
// FIXME: We may have a concrete DIE for this scope already created.
|
||||||
if (Scope->isAbstractScope()) {
|
// This may happen when we emit local variables for an abstract tree of
|
||||||
assert(!getAbstractScopeDIEs().count(DS) &&
|
// an inlined function: if a local variable has a templated type with
|
||||||
"Abstract DIE for this scope exists!");
|
// a function-local type as a template parameter. See PR55680 for details
|
||||||
getAbstractScopeDIEs()[DS] = ScopeDIE;
|
// (see also llvm/test/DebugInfo/Generic/local-type-as-template-parameter.ll).
|
||||||
return ScopeDIE;
|
if (!Scope->isAbstractScope() && !Scope->getInlinedAt()) {
|
||||||
|
if (auto It = LexicalBlockDIEs.find(DS); It != LexicalBlockDIEs.end()) {
|
||||||
|
ScopeDIE = It->second;
|
||||||
|
assert(!ScopeDIE->findAttribute(dwarf::DW_AT_low_pc) &&
|
||||||
|
!ScopeDIE->findAttribute(dwarf::DW_AT_ranges));
|
||||||
|
assert(ScopeDIE->getParent() == &ParentScopeDIE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!Scope->getInlinedAt()) {
|
if (!ScopeDIE) {
|
||||||
assert(!LexicalBlockDIEs.count(DS) &&
|
ScopeDIE = DIE::get(DIEValueAllocator, dwarf::DW_TAG_lexical_block);
|
||||||
"Concrete out-of-line DIE for this scope exists!");
|
ParentScopeDIE.addChild(ScopeDIE);
|
||||||
LexicalBlockDIEs[DS] = ScopeDIE;
|
|
||||||
|
if (Scope->isAbstractScope()) {
|
||||||
|
assert(!getAbstractScopeDIEs().count(DS) &&
|
||||||
|
"Abstract DIE for this scope exists!");
|
||||||
|
getAbstractScopeDIEs()[DS] = ScopeDIE;
|
||||||
|
return ScopeDIE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Scope->getInlinedAt())
|
||||||
|
LexicalBlockDIEs[DS] = ScopeDIE;
|
||||||
}
|
}
|
||||||
|
|
||||||
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
|
attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges());
|
||||||
@ -1686,15 +1700,21 @@ void DwarfCompileUnit::createBaseTypeDIEs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DIE *DwarfCompileUnit::getLexicalBlockDIE(const DILexicalBlock *LB) {
|
DIE *DwarfCompileUnit::getLocalContextDIE(const DILexicalBlock *LB) {
|
||||||
// Assume if there is an abstract tree all the DIEs are already emitted.
|
// Assume if there is an abstract tree all the DIEs are already emitted.
|
||||||
bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram());
|
bool isAbstract = getAbstractScopeDIEs().count(LB->getSubprogram());
|
||||||
if (isAbstract && getAbstractScopeDIEs().count(LB))
|
if (isAbstract && getAbstractScopeDIEs().count(LB))
|
||||||
return getAbstractScopeDIEs()[LB];
|
return getAbstractScopeDIEs()[LB];
|
||||||
assert(!isAbstract && "Missed lexical block DIE in abstract tree!");
|
assert(!isAbstract && "Missed lexical block DIE in abstract tree!");
|
||||||
|
|
||||||
// Return a concrete DIE if it exists or nullptr otherwise.
|
// Check if we have a concrete DIE.
|
||||||
return LexicalBlockDIEs.lookup(LB);
|
if (auto It = LexicalBlockDIEs.find(LB); It != LexicalBlockDIEs.end())
|
||||||
|
return It->second;
|
||||||
|
|
||||||
|
// If nothing available found, we cannot just create a new lexical block,
|
||||||
|
// because it isn't known where to put it into the DIE tree.
|
||||||
|
// So, we may only try to find the most close avaiable parent DIE.
|
||||||
|
return getOrCreateContextDIE(LB->getScope()->getNonLexicalBlockFileScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) {
|
DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) {
|
||||||
@ -1702,7 +1722,7 @@ DIE *DwarfCompileUnit::getOrCreateContextDIE(const DIScope *Context) {
|
|||||||
if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Context))
|
if (auto *LFScope = dyn_cast<DILexicalBlockFile>(Context))
|
||||||
Context = LFScope->getNonLexicalBlockFileScope();
|
Context = LFScope->getNonLexicalBlockFileScope();
|
||||||
if (auto *LScope = dyn_cast<DILexicalBlock>(Context))
|
if (auto *LScope = dyn_cast<DILexicalBlock>(Context))
|
||||||
return getLexicalBlockDIE(LScope);
|
return getLocalContextDIE(LScope);
|
||||||
|
|
||||||
// Otherwise the context must be a DISubprogram.
|
// Otherwise the context must be a DISubprogram.
|
||||||
auto *SPScope = cast<DISubprogram>(Context);
|
auto *SPScope = cast<DISubprogram>(Context);
|
||||||
|
@ -234,14 +234,9 @@ public:
|
|||||||
/// DIE to represent this concrete inlined copy of the function.
|
/// DIE to represent this concrete inlined copy of the function.
|
||||||
DIE *constructInlinedScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE);
|
DIE *constructInlinedScopeDIE(LexicalScope *Scope, DIE &ParentScopeDIE);
|
||||||
|
|
||||||
/// Construct new DW_TAG_lexical_block for this scope and
|
/// Get if available or create a new DW_TAG_lexical_block for the given
|
||||||
/// attach DW_AT_low_pc/DW_AT_high_pc labels.
|
/// LexicalScope and attach DW_AT_low_pc/DW_AT_high_pc labels.
|
||||||
DIE *constructLexicalScopeDIE(LexicalScope *Scope);
|
DIE *getOrCreateLexicalBlockDIE(LexicalScope *Scope, DIE &ParentDIE);
|
||||||
|
|
||||||
/// Get a DIE for the given DILexicalBlock.
|
|
||||||
/// Note that this function assumes that the DIE has been already created
|
|
||||||
/// and it's an error, if it hasn't.
|
|
||||||
DIE *getLexicalBlockDIE(const DILexicalBlock *LB);
|
|
||||||
|
|
||||||
/// Construct a DIE for the given DbgVariable.
|
/// Construct a DIE for the given DbgVariable.
|
||||||
DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false);
|
DIE *constructVariableDIE(DbgVariable &DV, bool Abstract = false);
|
||||||
@ -260,6 +255,11 @@ public:
|
|||||||
/// This instance of 'getOrCreateContextDIE()' can handle DILocalScope.
|
/// This instance of 'getOrCreateContextDIE()' can handle DILocalScope.
|
||||||
DIE *getOrCreateContextDIE(const DIScope *Ty) override;
|
DIE *getOrCreateContextDIE(const DIScope *Ty) override;
|
||||||
|
|
||||||
|
/// Get DW_TAG_lexical_block for the given DILexicalBlock if available,
|
||||||
|
/// or the most close parent DIE, if no correspoding DW_TAG_lexical_block
|
||||||
|
/// exists.
|
||||||
|
DIE *getLocalContextDIE(const DILexicalBlock *LB);
|
||||||
|
|
||||||
/// Construct a DIE for this subprogram scope.
|
/// Construct a DIE for this subprogram scope.
|
||||||
DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
|
DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
|
||||||
LexicalScope *Scope);
|
LexicalScope *Scope);
|
||||||
|
@ -1211,12 +1211,13 @@ void DwarfDebug::beginModule(Module *M) {
|
|||||||
CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
|
CU.getOrCreateGlobalVariableDIE(GV, sortGlobalExprs(GVMap[GV]));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto *Ty : CUNode->getEnumTypes())
|
for (auto *Ty : CUNode->getEnumTypes()) {
|
||||||
|
assert(!isa_and_nonnull<DILocalScope>(Ty->getScope()) &&
|
||||||
|
"Unexpected function-local entity in 'enums' CU field.");
|
||||||
CU.getOrCreateTypeDIE(cast<DIType>(Ty));
|
CU.getOrCreateTypeDIE(cast<DIType>(Ty));
|
||||||
|
}
|
||||||
|
|
||||||
for (auto *Ty : CUNode->getRetainedTypes()) {
|
for (auto *Ty : CUNode->getRetainedTypes()) {
|
||||||
// The retained types array by design contains pointers to
|
|
||||||
// MDNodes rather than DIRefs. Unique them here.
|
|
||||||
if (DIType *RT = dyn_cast<DIType>(Ty))
|
if (DIType *RT = dyn_cast<DIType>(Ty))
|
||||||
// There is no point in force-emitting a forward declaration.
|
// There is no point in force-emitting a forward declaration.
|
||||||
CU.getOrCreateTypeDIE(RT);
|
CU.getOrCreateTypeDIE(RT);
|
||||||
@ -1414,9 +1415,13 @@ void DwarfDebug::endModule() {
|
|||||||
"Unexpected function-local entity in 'imports' CU field.");
|
"Unexpected function-local entity in 'imports' CU field.");
|
||||||
CU->getOrCreateImportedEntityDIE(IE);
|
CU->getOrCreateImportedEntityDIE(IE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit function-local entities.
|
||||||
for (const auto *D : CU->getDeferredLocalDecls()) {
|
for (const auto *D : CU->getDeferredLocalDecls()) {
|
||||||
if (auto *IE = dyn_cast<DIImportedEntity>(D))
|
if (auto *IE = dyn_cast<DIImportedEntity>(D))
|
||||||
CU->getOrCreateImportedEntityDIE(IE);
|
CU->getOrCreateImportedEntityDIE(IE);
|
||||||
|
else if (auto *Ty = dyn_cast<DIType>(D))
|
||||||
|
CU->getOrCreateTypeDIE(Ty);
|
||||||
else
|
else
|
||||||
llvm_unreachable("Unexpected local retained node!");
|
llvm_unreachable("Unexpected local retained node!");
|
||||||
}
|
}
|
||||||
@ -1514,6 +1519,8 @@ static const DILocalScope *getRetainedNodeScope(const MDNode *N) {
|
|||||||
S = L->getScope();
|
S = L->getScope();
|
||||||
else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
|
else if (const auto *IE = dyn_cast<DIImportedEntity>(N))
|
||||||
S = IE->getScope();
|
S = IE->getScope();
|
||||||
|
else if (const auto *T = dyn_cast<DIType>(N))
|
||||||
|
S = T->getScope();
|
||||||
else
|
else
|
||||||
llvm_unreachable("Unexpected retained node!");
|
llvm_unreachable("Unexpected retained node!");
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes, DICompileUnit *CU)
|
|||||||
AllowUnresolvedNodes(AllowUnresolvedNodes) {
|
AllowUnresolvedNodes(AllowUnresolvedNodes) {
|
||||||
if (CUNode) {
|
if (CUNode) {
|
||||||
if (const auto &ETs = CUNode->getEnumTypes())
|
if (const auto &ETs = CUNode->getEnumTypes())
|
||||||
AllEnumTypes.assign(ETs.begin(), ETs.end());
|
EnumTypes.assign(ETs.begin(), ETs.end());
|
||||||
if (const auto &RTs = CUNode->getRetainedTypes())
|
if (const auto &RTs = CUNode->getRetainedTypes())
|
||||||
AllRetainTypes.assign(RTs.begin(), RTs.end());
|
AllRetainTypes.assign(RTs.begin(), RTs.end());
|
||||||
if (const auto &GVs = CUNode->getGlobalVariables())
|
if (const auto &GVs = CUNode->getGlobalVariables())
|
||||||
@ -68,10 +68,10 @@ void DIBuilder::finalize() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AllEnumTypes.empty())
|
if (!EnumTypes.empty())
|
||||||
CUNode->replaceEnumTypes(MDTuple::get(
|
CUNode->replaceEnumTypes(MDTuple::get(
|
||||||
VMContext, SmallVector<Metadata *, 16>(AllEnumTypes.begin(),
|
VMContext, SmallVector<Metadata *, 16>(EnumTypes.begin(),
|
||||||
AllEnumTypes.end())));
|
EnumTypes.end())));
|
||||||
|
|
||||||
SmallVector<Metadata *, 16> RetainValues;
|
SmallVector<Metadata *, 16> RetainValues;
|
||||||
// Declarations and definitions of the same type may be retained. Some
|
// Declarations and definitions of the same type may be retained. Some
|
||||||
@ -336,10 +336,13 @@ DIDerivedType *DIBuilder::createTypedef(DIType *Ty, StringRef Name,
|
|||||||
DIScope *Context, uint32_t AlignInBits,
|
DIScope *Context, uint32_t AlignInBits,
|
||||||
DINode::DIFlags Flags,
|
DINode::DIFlags Flags,
|
||||||
DINodeArray Annotations) {
|
DINodeArray Annotations) {
|
||||||
return DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File,
|
auto *T =
|
||||||
LineNo, getNonCompileUnitScope(Context), Ty, 0,
|
DIDerivedType::get(VMContext, dwarf::DW_TAG_typedef, Name, File, LineNo,
|
||||||
AlignInBits, 0, std::nullopt, Flags, nullptr,
|
getNonCompileUnitScope(Context), Ty, 0, AlignInBits, 0,
|
||||||
Annotations);
|
std::nullopt, Flags, nullptr, Annotations);
|
||||||
|
if (isa_and_nonnull<DILocalScope>(Context))
|
||||||
|
getSubprogramNodesTrackingVector(Context).emplace_back(T);
|
||||||
|
return T;
|
||||||
}
|
}
|
||||||
|
|
||||||
DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
|
DIDerivedType *DIBuilder::createFriend(DIType *Ty, DIType *FriendTy) {
|
||||||
@ -487,6 +490,8 @@ DICompositeType *DIBuilder::createClassType(
|
|||||||
OffsetInBits, Flags, Elements, 0, VTableHolder,
|
OffsetInBits, Flags, Elements, 0, VTableHolder,
|
||||||
cast_or_null<MDTuple>(TemplateParams), UniqueIdentifier);
|
cast_or_null<MDTuple>(TemplateParams), UniqueIdentifier);
|
||||||
trackIfUnresolved(R);
|
trackIfUnresolved(R);
|
||||||
|
if (isa_and_nonnull<DILocalScope>(Context))
|
||||||
|
getSubprogramNodesTrackingVector(Context).emplace_back(R);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,6 +505,8 @@ DICompositeType *DIBuilder::createStructType(
|
|||||||
getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits, 0,
|
getNonCompileUnitScope(Context), DerivedFrom, SizeInBits, AlignInBits, 0,
|
||||||
Flags, Elements, RunTimeLang, VTableHolder, nullptr, UniqueIdentifier);
|
Flags, Elements, RunTimeLang, VTableHolder, nullptr, UniqueIdentifier);
|
||||||
trackIfUnresolved(R);
|
trackIfUnresolved(R);
|
||||||
|
if (isa_and_nonnull<DILocalScope>(Context))
|
||||||
|
getSubprogramNodesTrackingVector(Context).emplace_back(R);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,6 +519,8 @@ DICompositeType *DIBuilder::createUnionType(
|
|||||||
getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
|
getNonCompileUnitScope(Scope), nullptr, SizeInBits, AlignInBits, 0, Flags,
|
||||||
Elements, RunTimeLang, nullptr, nullptr, UniqueIdentifier);
|
Elements, RunTimeLang, nullptr, nullptr, UniqueIdentifier);
|
||||||
trackIfUnresolved(R);
|
trackIfUnresolved(R);
|
||||||
|
if (isa_and_nonnull<DILocalScope>(Scope))
|
||||||
|
getSubprogramNodesTrackingVector(Scope).emplace_back(R);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,7 +553,10 @@ DICompositeType *DIBuilder::createEnumerationType(
|
|||||||
getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0,
|
getNonCompileUnitScope(Scope), UnderlyingType, SizeInBits, AlignInBits, 0,
|
||||||
IsScoped ? DINode::FlagEnumClass : DINode::FlagZero, Elements, 0, nullptr,
|
IsScoped ? DINode::FlagEnumClass : DINode::FlagZero, Elements, 0, nullptr,
|
||||||
nullptr, UniqueIdentifier);
|
nullptr, UniqueIdentifier);
|
||||||
AllEnumTypes.emplace_back(CTy);
|
if (isa_and_nonnull<DILocalScope>(Scope))
|
||||||
|
getSubprogramNodesTrackingVector(Scope).emplace_back(CTy);
|
||||||
|
else
|
||||||
|
EnumTypes.emplace_back(CTy);
|
||||||
trackIfUnresolved(CTy);
|
trackIfUnresolved(CTy);
|
||||||
return CTy;
|
return CTy;
|
||||||
}
|
}
|
||||||
@ -625,7 +637,8 @@ void DIBuilder::retainType(DIScope *T) {
|
|||||||
assert((isa<DIType>(T) || (isa<DISubprogram>(T) &&
|
assert((isa<DIType>(T) || (isa<DISubprogram>(T) &&
|
||||||
cast<DISubprogram>(T)->isDefinition() == false)) &&
|
cast<DISubprogram>(T)->isDefinition() == false)) &&
|
||||||
"Expected type or subprogram declaration");
|
"Expected type or subprogram declaration");
|
||||||
AllRetainTypes.emplace_back(T);
|
if (!isa_and_nonnull<DILocalScope>(T->getScope()))
|
||||||
|
AllRetainTypes.emplace_back(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
DIBasicType *DIBuilder::createUnspecifiedParameter() { return nullptr; }
|
DIBasicType *DIBuilder::createUnspecifiedParameter() { return nullptr; }
|
||||||
@ -642,6 +655,8 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIScope *Scope,
|
|||||||
SizeInBits, AlignInBits, 0, DINode::FlagFwdDecl, nullptr, RuntimeLang,
|
SizeInBits, AlignInBits, 0, DINode::FlagFwdDecl, nullptr, RuntimeLang,
|
||||||
nullptr, nullptr, UniqueIdentifier);
|
nullptr, nullptr, UniqueIdentifier);
|
||||||
trackIfUnresolved(RetTy);
|
trackIfUnresolved(RetTy);
|
||||||
|
if (isa_and_nonnull<DILocalScope>(Scope))
|
||||||
|
getSubprogramNodesTrackingVector(Scope).emplace_back(RetTy);
|
||||||
return RetTy;
|
return RetTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,6 +673,8 @@ DICompositeType *DIBuilder::createReplaceableCompositeType(
|
|||||||
nullptr, Annotations)
|
nullptr, Annotations)
|
||||||
.release();
|
.release();
|
||||||
trackIfUnresolved(RetTy);
|
trackIfUnresolved(RetTy);
|
||||||
|
if (isa_and_nonnull<DILocalScope>(Scope))
|
||||||
|
getSubprogramNodesTrackingVector(Scope).emplace_back(RetTy);
|
||||||
return RetTy;
|
return RetTy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +267,12 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
|
|||||||
processType(TVal->getType());
|
processType(TVal->getType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto *N : SP->getRetainedNodes()) {
|
||||||
|
if (auto *Var = dyn_cast<DILocalVariable>(N)) {
|
||||||
|
processLocalVariable(Var);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugInfoFinder::processVariable(const Module &M,
|
void DebugInfoFinder::processVariable(const Module &M,
|
||||||
@ -275,7 +281,10 @@ void DebugInfoFinder::processVariable(const Module &M,
|
|||||||
if (!N)
|
if (!N)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto *DV = dyn_cast<DILocalVariable>(N);
|
processLocalVariable(dyn_cast<DILocalVariable>(N));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugInfoFinder::processLocalVariable(DILocalVariable *DV) {
|
||||||
if (!DV)
|
if (!DV)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1404,9 +1404,9 @@ void Verifier::visitDISubprogram(const DISubprogram &N) {
|
|||||||
CheckDI(Node, "invalid retained nodes list", &N, RawNode);
|
CheckDI(Node, "invalid retained nodes list", &N, RawNode);
|
||||||
for (Metadata *Op : Node->operands()) {
|
for (Metadata *Op : Node->operands()) {
|
||||||
CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op) ||
|
CheckDI(Op && (isa<DILocalVariable>(Op) || isa<DILabel>(Op) ||
|
||||||
isa<DIImportedEntity>(Op)),
|
isa<DIImportedEntity>(Op) || isa<DIType>(Op)),
|
||||||
"invalid retained nodes, expected DILocalVariable, DILabel or "
|
"invalid retained nodes, expected DILocalVariable, DILabel, "
|
||||||
"DIImportedEntity",
|
"DIImportedEntity or DIType",
|
||||||
&N, Node, Op);
|
&N, Node, Op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,12 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
|
|||||||
mapToSelfIfNew(CU);
|
mapToSelfIfNew(CU);
|
||||||
|
|
||||||
for (DIType *Type : DIFinder->types())
|
for (DIType *Type : DIFinder->types())
|
||||||
mapToSelfIfNew(Type);
|
// Don't skip subprogram's local types.
|
||||||
|
if (!isa_and_present<DILocalScope>(Type->getScope()) ||
|
||||||
|
SPClonedWithinModule == nullptr ||
|
||||||
|
dyn_cast<DILocalScope>(Type->getScope())->getSubprogram() !=
|
||||||
|
SPClonedWithinModule)
|
||||||
|
mapToSelfIfNew(Type);
|
||||||
} else {
|
} else {
|
||||||
assert(!SPClonedWithinModule &&
|
assert(!SPClonedWithinModule &&
|
||||||
"Subprogram should be in DIFinder->subprogram_count()...");
|
"Subprogram should be in DIFinder->subprogram_count()...");
|
||||||
|
46
llvm/test/Bitcode/clone-local-types.ll
Normal file
46
llvm/test/Bitcode/clone-local-types.ll
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
; RUN: llvm-as < %s -o %t0
|
||||||
|
; RUN: llvm-dis %t0 -o - | FileCheck %s
|
||||||
|
|
||||||
|
; Ensure that function-local types with the same ODR identifier belonging
|
||||||
|
; to different subprograms are not deduplicated when a module is being loaded.
|
||||||
|
|
||||||
|
; CHECK: [[CU:![0-9]+]] = distinct !DICompileUnit
|
||||||
|
; CHECK: [[BAR:![0-9]+]] = distinct !DISubprogram(name: "bar", {{.*}}, retainedNodes: [[RN_BAR:![0-9]+]])
|
||||||
|
; CHECK: [[RN_BAR]] = !{[[T2:![0-9]+]]}
|
||||||
|
; CHECK: [[T2]] = !DICompositeType(tag: DW_TAG_class_type, {{.*}}, identifier: "local_type")
|
||||||
|
; CHECK: [[FOO:![0-9]+]] = distinct !DISubprogram(name: "foo", {{.*}}, retainedNodes: [[RN_FOO:![0-9]+]])
|
||||||
|
; CHECK: [[RN_FOO]] = !{[[T1:![0-9]+]]}
|
||||||
|
; CHECK: [[T1]] = !DICompositeType(tag: DW_TAG_class_type, {{.*}}, identifier: "local_type")
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
declare void @foo()
|
||||||
|
|
||||||
|
define void @bar(ptr %this) !dbg !10 {
|
||||||
|
call void @foo(), !dbg !17
|
||||||
|
ret void, !dbg !13
|
||||||
|
}
|
||||||
|
|
||||||
|
!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7}
|
||||||
|
!llvm.dbg.cu = !{!8}
|
||||||
|
|
||||||
|
!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 11, i32 4]}
|
||||||
|
!1 = !{i32 7, !"Dwarf Version", i32 2}
|
||||||
|
!2 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!3 = !{i32 1, !"wchar_size", i32 4}
|
||||||
|
!4 = !{i32 7, !"openmp", i32 50}
|
||||||
|
!5 = !{i32 7, !"openmp-device", i32 50}
|
||||||
|
!6 = !{i32 7, !"PIC Level", i32 2}
|
||||||
|
!7 = !{i32 7, !"frame-pointer", i32 2}
|
||||||
|
!8 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !9, producer: "clang version 14.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
|
||||||
|
!9 = !DIFile(filename: "tmp.cpp", directory: "/tmp/")
|
||||||
|
!10 = distinct !DISubprogram(name: "bar", scope: !9, file: !9, line: 68, type: !12, scopeLine: 68, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !8, retainedNodes: !16)
|
||||||
|
!11 = distinct !DISubprogram(name: "foo", scope: !9, file: !9, line: 68, type: !12, scopeLine: 68, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !8, retainedNodes: !16)
|
||||||
|
!12 = !DISubroutineType(types: !15)
|
||||||
|
!13 = !DILocation(line: 69, column: 18, scope: !10)
|
||||||
|
!14 = !DICompositeType(tag: DW_TAG_class_type, scope: !11, file: !9, line: 210, size: 8, flags: DIFlagTypePassByValue, elements: !15, identifier: "local_type")
|
||||||
|
!15 = !{}
|
||||||
|
!16 = !{!14}
|
||||||
|
!17 = !DILocation(line: 69, column: 18, scope: !11, inlinedAt: !18)
|
||||||
|
!18 = !DILocation(line: 4, column: 1, scope: !10)
|
@ -1,4 +1,4 @@
|
|||||||
; Test moving of local imports from DICompileUnit's 'imports' to DISubprogram's 'retainedNodes'
|
; Test moving of local imports/enums from DICompileUnit to DISubprogram's 'retainedNodes'
|
||||||
;
|
;
|
||||||
; RUN: llvm-dis -o - %s.bc | FileCheck %s
|
; RUN: llvm-dis -o - %s.bc | FileCheck %s
|
||||||
|
|
||||||
@ -31,31 +31,36 @@ attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memo
|
|||||||
; CHECK: !4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t4"
|
; CHECK: !4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t4"
|
||||||
|
|
||||||
; CHECK: !5 = !{}
|
; CHECK: !5 = !{}
|
||||||
; CHECK: !6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !7, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !5, nameTableKind: GNU)
|
; CHECK: !6 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !7, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !8, imports: !5, nameTableKind: GNU)
|
||||||
|
; CHECK: !7 = !DIFile(filename: "b.cpp"
|
||||||
|
; CHECK: !8 = !{!9}
|
||||||
|
; CHECK: !9 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum2", scope: !6, file: !7, line: 4, size: 8, align: 8, elements: !5)
|
||||||
|
|
||||||
; CHECK: !14 = distinct !DISubprogram(name: "main", scope: !7, file: !7, line: 2, type: !15, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !18)
|
; CHECK: !16 = distinct !DISubprogram(name: "main", scope: !7, file: !7, line: 2, type: !17, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !20)
|
||||||
; CHECK: !18 = !{!19}
|
; CHECK: !20 = !{!21}
|
||||||
; CHECK: !19 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !20, entity: !23,
|
; CHECK: !21 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !22, entity: !25,
|
||||||
; CHECK: !20 = !DILexicalBlock(scope: !21, file: !7, line: 7, column: 35)
|
; CHECK: !22 = !DILexicalBlock(scope: !23, file: !7, line: 7, column: 35)
|
||||||
; CHECK: !21 = !DILexicalBlock(scope: !22, file: !7, line: 7, column: 35)
|
; CHECK: !23 = !DILexicalBlock(scope: !24, file: !7, line: 7, column: 35)
|
||||||
; CHECK: !22 = !DILexicalBlock(scope: !14, file: !7, line: 7, column: 35)
|
; CHECK: !24 = !DILexicalBlock(scope: !16, file: !7, line: 7, column: 35)
|
||||||
; CHECK: !23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t5", scope: !20,
|
; CHECK: !25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t5", scope: !22,
|
||||||
|
|
||||||
; CHECK: !25 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 3, type: !26, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !28)
|
; CHECK: !27 = distinct !DISubprogram(name: "f1", linkageName: "_Z2f1v", scope: !1, file: !1, line: 3, type: !28, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !30)
|
||||||
; CHECK: !28 = !{!29, !32, !34}
|
; CHECK: !30 = !{!31, !34, !36}
|
||||||
; CHECK: !29 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !25, entity: !30,
|
; CHECK: !31 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !27, entity: !32,
|
||||||
; CHECK: !30 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1",
|
; CHECK: !32 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1",
|
||||||
; CHECK: !32 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !25, entity: !33,
|
; CHECK: !34 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !27, entity: !35,
|
||||||
; CHECK: !33 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2",
|
; CHECK: !35 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2",
|
||||||
; CHECK: !34 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !25, entity: !35,
|
; CHECK: !36 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !27, entity: !37,
|
||||||
; CHECK: !35 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t3",
|
; CHECK: !37 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t3",
|
||||||
|
|
||||||
; CHECK: !40 = distinct !DISubprogram(name: "main2", scope: !7, file: !7, line: 10, type: !15, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !41)
|
; CHECK: !42 = distinct !DISubprogram(name: "main2", scope: !7, file: !7, line: 10, type: !17, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !6, retainedNodes: !43)
|
||||||
; CHECK: !41 = !{!42, !44}
|
; CHECK: !43 = !{!44, !46, !48, !49}
|
||||||
; CHECK: !42 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !40, entity: !43,
|
; CHECK: !44 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !42, entity: !45,
|
||||||
; CHECK: !43 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t6"
|
; CHECK: !45 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t6"
|
||||||
; CHECK: !44 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !40, entity: !45,
|
; CHECK: !46 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !42, entity: !47,
|
||||||
; CHECK: !45 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t7",
|
; CHECK: !47 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t7",
|
||||||
|
; CHECK: !48 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !42, file: !7, line: 3, size: 8, align: 8, elements: !5)
|
||||||
|
; CHECK: !49 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum3", scope: !42, file: !7, line: 5, size: 8, align: 8, elements: !5)
|
||||||
|
|
||||||
|
|
||||||
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !2, nameTableKind: GNU)
|
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !2, nameTableKind: GNU)
|
||||||
@ -82,7 +87,7 @@ attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memo
|
|||||||
; Leave t4 in CU
|
; Leave t4 in CU
|
||||||
!14 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !15, file: !1, line: 3)
|
!14 = !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !15, file: !1, line: 3)
|
||||||
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t4", scope: !0, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t4E")
|
!15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t4", scope: !0, file: !1, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !7, identifier: "_ZTSN2ns2t4E")
|
||||||
!16 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !17, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !18, nameTableKind: GNU)
|
!16 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !17, producer: "clang version 14.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, imports: !18, enums: !50, nameTableKind: GNU)
|
||||||
!17 = !DIFile(filename: "b.cpp", directory: "/")
|
!17 = !DIFile(filename: "b.cpp", directory: "/")
|
||||||
!18 = !{!19, !28, !31}
|
!18 = !{!19, !28, !31}
|
||||||
|
|
||||||
@ -116,3 +121,12 @@ attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memo
|
|||||||
!41 = distinct !DILocation(line: 3, column: 3, scope: !23)
|
!41 = distinct !DILocation(line: 3, column: 3, scope: !23)
|
||||||
!42 = !DILocation(line: 3, column: 41, scope: !4, inlinedAt: !41)
|
!42 = !DILocation(line: 3, column: 41, scope: !4, inlinedAt: !41)
|
||||||
!43 = !DILocation(line: 4, column: 1, scope: !23)
|
!43 = !DILocation(line: 4, column: 1, scope: !23)
|
||||||
|
|
||||||
|
!50 = !{!51, !52, !53}
|
||||||
|
; Move to main2
|
||||||
|
!51 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !29, file: !17, line: 3, size: 8, align: 8, elements: !7)
|
||||||
|
; Leave in b.cpp's CU
|
||||||
|
!52 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum2", scope: !16, file: !17, line: 4, size: 8, align: 8, elements: !7)
|
||||||
|
; Move to main2
|
||||||
|
!53 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum3", scope: !29, file: !17, line: 5, size: 8, align: 8, elements: !7)
|
||||||
|
|
||||||
|
Binary file not shown.
128
llvm/test/DebugInfo/Generic/inlined-local-type.ll
Normal file
128
llvm/test/DebugInfo/Generic/inlined-local-type.ll
Normal file
@ -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}
|
55
llvm/test/DebugInfo/Generic/lexical-block-retained-types.ll
Normal file
55
llvm/test/DebugInfo/Generic/lexical-block-retained-types.ll
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
; RUN: %llc_dwarf -O0 -filetype=obj < %s | llvm-dwarfdump - | FileCheck --implicit-check-not "{{DW_TAG|NULL}}" %s
|
||||||
|
|
||||||
|
; Test that retained unused (unreferenced) types emission.
|
||||||
|
|
||||||
|
; 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")
|
||||||
|
|
||||||
|
; FIXME: here should be DW_TAG_lexical_block as a parent of structure 'X'.
|
||||||
|
; But it's not possible to reliably emit a lexical block for which a LexicalScope
|
||||||
|
; wasn't created, so we just fallback to the most close parent DIE
|
||||||
|
; (see DwarfCompileUnit::getOrCreateLexicalBlockDIE() for details).
|
||||||
|
|
||||||
|
; CHECK: DW_TAG_structure_type
|
||||||
|
; CHECK: DW_AT_name ("X")
|
||||||
|
; 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: "<stdin>", 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)
|
425
llvm/test/DebugInfo/Generic/lexical-block-types.ll
Normal file
425
llvm/test/DebugInfo/Generic/lexical-block-types.ll
Normal file
@ -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 {{.*}} "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 {{.*}} "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 {{.*}} "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}
|
@ -38,7 +38,7 @@ define void @invalid_subprogram_declaration() !dbg !9 { ret void }
|
|||||||
define void @invalid_retained_nodes_list() !dbg !10 { ret void }
|
define void @invalid_retained_nodes_list() !dbg !10 { ret void }
|
||||||
!10 = distinct !DISubprogram(retainedNodes: !0)
|
!10 = distinct !DISubprogram(retainedNodes: !0)
|
||||||
|
|
||||||
; CHECK: invalid retained nodes, expected DILocalVariable, DILabel or DIImportedEntity
|
; CHECK: invalid retained nodes, expected DILocalVariable, DILabel, DIImportedEntity or DIType
|
||||||
define void @invalid_retained_nodes_expected() !dbg !11 { ret void }
|
define void @invalid_retained_nodes_expected() !dbg !11 { ret void }
|
||||||
!11 = distinct !DISubprogram(retainedNodes: !{!0})
|
!11 = distinct !DISubprogram(retainedNodes: !{!0})
|
||||||
|
|
||||||
|
161
llvm/test/DebugInfo/X86/local-type-as-template-parameter.ll
Normal file
161
llvm/test/DebugInfo/X86/local-type-as-template-parameter.ll
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
; REQUIERES: system-linux
|
||||||
|
; RUN: %llc_dwarf -mtriple=x86_64-linux -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<typename T>
|
||||||
|
; struct A {
|
||||||
|
; A(T &in) : a(in) {}
|
||||||
|
; T a;
|
||||||
|
; };
|
||||||
|
;
|
||||||
|
; __attribute__((always_inline))
|
||||||
|
; void foo() {
|
||||||
|
; struct B { int i; };
|
||||||
|
; B objB;
|
||||||
|
; A<B> objA(objB);
|
||||||
|
; }
|
||||||
|
;
|
||||||
|
; int main() {
|
||||||
|
; foo();
|
||||||
|
; }
|
||||||
|
|
||||||
|
; Concrete out-of-line tree of foo().
|
||||||
|
; CHECK: DW_TAG_subprogram
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} "_Z3foov"
|
||||||
|
|
||||||
|
; 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: DW_TAG_variable
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} "objB"
|
||||||
|
; CHECK: DW_TAG_variable
|
||||||
|
; CHECK: DW_AT_abstract_origin {{.*}} "objA"
|
||||||
|
|
||||||
|
; 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<B>", 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)
|
@ -68,11 +68,11 @@ attributes #1 = { nofree nosync nounwind readnone speculatable willreturn }
|
|||||||
!llvm.module.flags = !{!18, !19, !20}
|
!llvm.module.flags = !{!18, !19, !20}
|
||||||
|
|
||||||
!0 = !{!"versions- cm3: d5.10.0 llvm: 9.0"}
|
!0 = !{!"versions- cm3: d5.10.0 llvm: 9.0"}
|
||||||
!1 = distinct !DICompileUnit(language: DW_LANG_Modula3, file: !2, producer: "cm3", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
|
!1 = distinct !DICompileUnit(language: DW_LANG_Modula3, file: !2, producer: "cm3", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
|
||||||
!2 = !DIFile(filename: "Main.m3", directory: "/home/cm3/settest/src")
|
!2 = !DIFile(filename: "Main.m3", directory: "/home/cm3/settest/src")
|
||||||
!3 = !{!4}
|
!3 = !{!4}
|
||||||
!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !5, file: !2, line: 11, size: 8, align: 8, elements: !9)
|
!4 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum", scope: !5, file: !2, line: 11, size: 8, align: 8, elements: !9)
|
||||||
!5 = distinct !DISubprogram(name: "Test", linkageName: "Main__Test", scope: !2, file: !2, line: 11, type: !6, scopeLine: 11, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !8)
|
!5 = distinct !DISubprogram(name: "Test", linkageName: "Main__Test", scope: !2, file: !2, line: 11, type: !6, scopeLine: 11, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !3)
|
||||||
!6 = !DISubroutineType(types: !7)
|
!6 = !DISubroutineType(types: !7)
|
||||||
!7 = !{null}
|
!7 = !{null}
|
||||||
!8 = !{}
|
!8 = !{}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
; REQUIRES: x86-registered-target
|
|
||||||
; RUN: %llc_dwarf -O1 -filetype=obj -split-dwarf-file=%t.dwo < %s | llvm-dwarfdump -debug-info - | FileCheck %s --implicit-check-not "{{DW_TAG|NULL}}"
|
; RUN: %llc_dwarf -O1 -filetype=obj -split-dwarf-file=%t.dwo < %s | llvm-dwarfdump -debug-info - | FileCheck %s --implicit-check-not "{{DW_TAG|NULL}}"
|
||||||
|
|
||||||
; CHECK-LABEL: debug_info contents
|
; CHECK-LABEL: debug_info contents
|
@ -1,4 +1,3 @@
|
|||||||
; REQUIRES: x86-registered-target
|
|
||||||
; RUN: %llc_dwarf -split-dwarf-file=%t.dwo < %s | FileCheck %s
|
; 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.
|
; Ensure function-local DW_TAG_imported_declaration get skipped if its parent subprogram was not emitted.
|
@ -801,6 +801,99 @@ TEST(CloneFunction, CloneFunctionWithSubprograms) {
|
|||||||
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
|
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(CloneFunction, CloneFunctionWithRetainedNodes) {
|
||||||
|
StringRef ImplAssembly = R"(
|
||||||
|
declare void @llvm.dbg.declare(metadata, metadata, metadata)
|
||||||
|
|
||||||
|
define void @test() !dbg !3 {
|
||||||
|
call void @llvm.dbg.declare(metadata i8* undef, metadata !5, metadata !DIExpression()), !dbg !7
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @cloned()
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!2}
|
||||||
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, enums: !{!14})
|
||||||
|
!1 = !DIFile(filename: "test.cpp", directory: "")
|
||||||
|
!2 = !{i32 1, !"Debug Info Version", i32 3}
|
||||||
|
!3 = distinct !DISubprogram(name: "test", scope: !1, unit: !0, retainedNodes: !9)
|
||||||
|
!4 = distinct !DISubprogram(name: "inlined", scope: !1, unit: !0, retainedNodes: !{!5})
|
||||||
|
!5 = !DILocalVariable(name: "awaitables", scope: !4, type: !23)
|
||||||
|
!6 = distinct !DILexicalBlock(scope: !4, file: !1, line: 1)
|
||||||
|
!7 = !DILocation(line: 1, scope: !6, inlinedAt: !8)
|
||||||
|
!8 = !DILocation(line: 10, scope: !3)
|
||||||
|
!9 = !{!15, !17, !18}
|
||||||
|
!14 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, scope: !0, file: !1, line: 13, size: 200, elements: !{})
|
||||||
|
!15 = !DILocalVariable(name: "a", scope: !3)
|
||||||
|
!16 = distinct !DICompositeType(tag: DW_TAG_enumeration_type, scope: !3, file: !1, line: 13, size: 208, elements: !{})
|
||||||
|
!17 = !DIImportedEntity(tag: DW_TAG_imported_declaration, name: "imported_l", file: !1, line: 14, scope: !3, entity: !16)
|
||||||
|
!18 = !DILabel(scope: !3, name: "l", file: !1, line: 22)
|
||||||
|
!22 = !DIBasicType(name: "real", size: 32, align: 32, encoding: DW_ATE_float)
|
||||||
|
!23 = !DIDerivedType(name: "local_float", tag: DW_TAG_const_type, baseType: !22, scope: !3)
|
||||||
|
!float_type = !{!23}
|
||||||
|
)";
|
||||||
|
|
||||||
|
LLVMContext Context;
|
||||||
|
SMDiagnostic Error;
|
||||||
|
|
||||||
|
auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context);
|
||||||
|
llvm::errs() << Error.getMessage() << Error.getLineNo() << "\n";
|
||||||
|
EXPECT_TRUE(ImplModule != nullptr);
|
||||||
|
auto *Func = ImplModule->getFunction("test");
|
||||||
|
EXPECT_TRUE(Func != nullptr);
|
||||||
|
auto *ClonedFunc = ImplModule->getFunction("cloned");
|
||||||
|
EXPECT_TRUE(ClonedFunc != nullptr);
|
||||||
|
|
||||||
|
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
|
||||||
|
|
||||||
|
ValueToValueMapTy VMap;
|
||||||
|
SmallVector<ReturnInst *, 8> Returns;
|
||||||
|
ClonedCodeInfo CCI;
|
||||||
|
CloneFunctionInto(ClonedFunc, Func, VMap,
|
||||||
|
CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI);
|
||||||
|
|
||||||
|
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
|
||||||
|
|
||||||
|
// Check that retained and local types are copied.
|
||||||
|
DISubprogram *FuncSP = Func->getSubprogram();
|
||||||
|
DISubprogram *ClonedSP = ClonedFunc->getSubprogram();
|
||||||
|
EXPECT_NE(FuncSP, nullptr);
|
||||||
|
EXPECT_NE(ClonedSP, nullptr);
|
||||||
|
EXPECT_EQ(FuncSP->getRetainedNodes().size(), 3u);
|
||||||
|
EXPECT_EQ(FuncSP->getRetainedNodes().size(),
|
||||||
|
ClonedSP->getRetainedNodes().size());
|
||||||
|
for (unsigned I = 0; I < FuncSP->getRetainedNodes().size(); ++I) {
|
||||||
|
auto *Node = FuncSP->getRetainedNodes()[I];
|
||||||
|
auto *Copy = ClonedSP->getRetainedNodes()[I];
|
||||||
|
|
||||||
|
// Check that the order of retainedNodes is preserved by
|
||||||
|
// checking that the corresponding node has the same name.
|
||||||
|
if (auto *Var = dyn_cast<DILocalVariable>(Node)) {
|
||||||
|
auto *VarCopy = dyn_cast<DILocalVariable>(Copy);
|
||||||
|
EXPECT_NE(VarCopy, nullptr);
|
||||||
|
EXPECT_EQ(Var->getName(), VarCopy->getName());
|
||||||
|
} else if (auto *Label = dyn_cast<DILabel>(Node)) {
|
||||||
|
auto *LabelCopy = dyn_cast<DILabel>(Copy);
|
||||||
|
EXPECT_NE(LabelCopy, nullptr);
|
||||||
|
EXPECT_EQ(Label->getName(), LabelCopy->getName());
|
||||||
|
} else if (auto *IE = dyn_cast<DIImportedEntity>(Node)) {
|
||||||
|
auto *IECopy = dyn_cast<DIImportedEntity>(Copy);
|
||||||
|
EXPECT_NE(IECopy, nullptr);
|
||||||
|
EXPECT_EQ(IE->getName(), IECopy->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that node was copied
|
||||||
|
EXPECT_NE(Node, Copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *FloatType = dyn_cast<DIType>(
|
||||||
|
ImplModule->getNamedMetadata("float_type")->getOperand(0));
|
||||||
|
EXPECT_EQ(FloatType->getName(), "local_float");
|
||||||
|
EXPECT_TRUE(VMap.MD().contains(FloatType));
|
||||||
|
EXPECT_NE(FloatType, VMap.MD()[FloatType]);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(CloneFunction, CloneFunctionWithInlinedSubprograms) {
|
TEST(CloneFunction, CloneFunctionWithInlinedSubprograms) {
|
||||||
StringRef ImplAssembly = R"(
|
StringRef ImplAssembly = R"(
|
||||||
declare void @llvm.dbg.declare(metadata, metadata, metadata)
|
declare void @llvm.dbg.declare(metadata, metadata, metadata)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user