forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(New) Add option to generate additional debug info for expression der…
…eferencing pointer to pointers (llvm#95298) This is a different implementation to llvm#94100, which has been reverted. When -fdebug-info-for-profiling is specified, for any Load expression if the pointer operand is not a declared variable, clang will emit debug info describing the type of the pointer operand (which can be an intermediate expr)
- Loading branch information
Showing
4 changed files
with
183 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// Test debug info for intermediate value of a chained pointer deferencing | ||
// expression when the flag -fdebug-info-for-pointer-type is enabled. | ||
// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -fdebug-info-for-profiling -debug-info-kind=constructor -o - | FileCheck %s | ||
|
||
class A { | ||
public: | ||
int i; | ||
char c; | ||
void *p; | ||
int arr[3]; | ||
}; | ||
|
||
class B { | ||
public: | ||
A* a; | ||
}; | ||
|
||
class C { | ||
public: | ||
B* b; | ||
A* a; | ||
A arr[10]; | ||
}; | ||
|
||
// CHECK-LABEL: define dso_local noundef i32 @{{.*}}func1{{.*}}( | ||
// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds %class.B, ptr {{%.*}}, i32 0, i32 0, !dbg [[DBG1:![0-9]+]] | ||
// CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[A_ADDR]], align {{.*}}, !dbg [[DBG1]] | ||
// CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[A]], metadata [[META1:![0-9]+]], metadata !DIExpression()), !dbg [[DBG1]] | ||
// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.A, ptr [[A]], i32 0, i32 0, | ||
int func1(B *b) { | ||
return b->a->i; | ||
} | ||
|
||
// Should generate a pseudo variable when pointer is type-casted. | ||
// CHECK-LABEL: define dso_local noundef ptr @{{.*}}func2{{.*}}( | ||
// CHECK: call void @llvm.dbg.declare(metadata ptr [[B_ADDR:%.*]], metadata [[META2:![0-9]+]], metadata !DIExpression()) | ||
// CHECK-NEXT: [[B:%.*]] = load ptr, ptr [[B_ADDR]], | ||
// CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[B]], metadata [[META3:![0-9]+]], metadata !DIExpression()) | ||
// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.B, ptr [[B]], i32 0, | ||
A* func2(void *b) { | ||
return ((B*)b)->a; | ||
} | ||
|
||
// Should not generate pseudo variable in this case. | ||
// CHECK-LABEL: define dso_local noundef i32 @{{.*}}func3{{.*}}( | ||
// CHECK: call void @llvm.dbg.declare(metadata ptr [[B_ADDR:%.*]], metadata [[META4:![0-9]+]], metadata !DIExpression()) | ||
// CHECK: call void @llvm.dbg.declare(metadata ptr [[LOCAL1:%.*]], metadata [[META5:![0-9]+]], metadata !DIExpression()) | ||
// CHECK-NOT: call void @llvm.dbg.value(metadata ptr | ||
int func3(B *b) { | ||
A *local1 = b->a; | ||
return local1->i; | ||
} | ||
|
||
// CHECK-LABEL: define dso_local noundef signext i8 @{{.*}}func4{{.*}}( | ||
// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds %class.C, ptr {{%.*}}, i32 0, i32 1 | ||
// CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[A_ADDR]], | ||
// CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[A]], metadata [[META6:![0-9]+]], metadata !DIExpression()) | ||
// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.A, ptr [[A]], i32 0, i32 0, | ||
// CHECK: [[CALL:%.*]] = call noundef ptr @{{.*}}foo{{.*}}( | ||
// CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[CALL]], metadata [[META6]], metadata !DIExpression()) | ||
// CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds %class.A, ptr [[CALL]], i32 0, i32 1 | ||
char func4(C *c) { | ||
extern A* foo(int x); | ||
return foo(c->a->i)->c; | ||
} | ||
|
||
// CHECK-LABEL: define dso_local noundef signext i8 @{{.*}}func5{{.*}}( | ||
// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META7:![0-9]+]], metadata !DIExpression()) | ||
// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META8:![0-9]+]], metadata !DIExpression()) | ||
// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds %class.A, ptr {{%.*}}, i64 {{%.*}}, | ||
// CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[A_ADDR]], metadata [[META9:![0-9]+]], metadata !DIExpression()) | ||
// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.A, ptr [[A_ADDR]], i32 0, i32 1, | ||
char func5(void *arr, int n) { | ||
return ((A*)arr)[n].c; | ||
} | ||
|
||
// CHECK-LABEL: define dso_local noundef i32 @{{.*}}func6{{.*}}( | ||
// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META10:![0-9]+]], metadata !DIExpression()) | ||
// CHECK: call void @llvm.dbg.value(metadata ptr {{%.*}}, metadata [[META11:![0-9]+]], metadata !DIExpression()) | ||
int func6(B &b) { | ||
return reinterpret_cast<A&>(b).i; | ||
} | ||
|
||
// CHECK-LABEL: define dso_local noundef i32 @{{.*}}global{{.*}}( | ||
// CHECK: [[GA:%.*]] = load ptr, ptr @ga | ||
// CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[GA]], metadata [[META12:![0-9]+]], metadata !DIExpression()) | ||
A *ga; | ||
int global() { | ||
return ga->i; | ||
} | ||
|
||
|
||
// CHECK-DAG: [[META_A:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", | ||
// CHECK-DAG: [[META_AP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META_A]], | ||
// CHECK-DAG: [[META_B:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B", | ||
// CHECK-DAG: [[META_BP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META_B]], | ||
// CHECK-DAG: [[META_C:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "C", | ||
// CHECK-DAG: [[META_CP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META_C]], | ||
// CHECK-DAG: [[META_VP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, | ||
// CHECK-DAG: [[META_I32:![0-9]+]] = !DIBasicType(name: "int", size: 32, | ||
// CHECK-DAG: [[META_BR:![0-9]+]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[META_B]], | ||
|
||
// CHECK-DAG: [[DBG1]] = !DILocation(line: 31, column: 13, | ||
// CHECK-DAG: [[META1]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) | ||
// CHECK-DAG: [[META2]] = !DILocalVariable(name: "b", arg: 1, scope: {{.*}}, file: {{.*}}, line: 40, type: [[META_VP]]) | ||
// CHECK-DAG: [[META3]] = !DILocalVariable(scope: {{.*}}, type: [[META_BP]], flags: DIFlagArtificial) | ||
// CHECK-DAG: [[META4]] = !DILocalVariable(name: "b", arg: 1, scope: {{.*}}, file: {{.*}}, line: 49, type: [[META_BP]]) | ||
// CHECK-DAG: [[META5]] = !DILocalVariable(name: "local1", scope: {{.*}}, file: {{.*}}, line: 50, type: [[META_AP]]) | ||
// CHECK-DAG: [[META6]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) | ||
// CHECK-DAG: [[META7]] = !DILocalVariable(name: "arr", arg: 1, scope: {{.*}}, file: {{.*}}, line: 73, type: [[META_VP]]) | ||
// CHECK-DAG: [[META8]] = !DILocalVariable(name: "n", arg: 2, scope: {{.*}}, file: {{.*}}, line: 73, type: [[META_I32]]) | ||
// CHECK-DAG: [[META9]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) | ||
// CHECK-DAG: [[META10]] = !DILocalVariable(name: "b", arg: 1, scope: {{.*}}, file: {{.*}}, line: 80, type: [[META_BR]]) | ||
// CHECK-DAG: [[META11]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) | ||
// CHECK-DAG: [[META12]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) |