Skip to content

Commit 347273d

Browse files
authored
[KeyInstr][Clang] Coerced store atoms (#134653)
[KeyInstr][Clang] Coerced store atoms This patch is part of a stack that teaches Clang to generate Key Instructions metadata for C and C++. RFC: https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668 The feature is only functional in LLVM if LLVM is built with CMake flag LLVM_EXPERIMENTAL_KEY_INSTRUCTIONs. Eventually that flag will be removed.
1 parent 6206d7d commit 347273d

File tree

5 files changed

+114
-8
lines changed

5 files changed

+114
-8
lines changed

clang/lib/CodeGen/CGCall.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,24 +1425,30 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
14251425
SrcSize == CGM.getDataLayout().getTypeAllocSize(Dst.getElementType())) {
14261426
// If the value is supposed to be a pointer, convert it before storing it.
14271427
Src = CoerceIntOrPtrToIntOrPtr(Src, Dst.getElementType(), *this);
1428-
Builder.CreateStore(Src, Dst, DstIsVolatile);
1428+
auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
1429+
addInstToCurrentSourceAtom(I, Src);
14291430
} else if (llvm::StructType *STy =
14301431
dyn_cast<llvm::StructType>(Src->getType())) {
14311432
// Prefer scalar stores to first-class aggregate stores.
14321433
Dst = Dst.withElementType(SrcTy);
14331434
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
14341435
Address EltPtr = Builder.CreateStructGEP(Dst, i);
14351436
llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
1436-
Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
1437+
auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
1438+
addInstToCurrentSourceAtom(I, Elt);
14371439
}
14381440
} else {
1439-
Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile);
1441+
auto *I =
1442+
Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile);
1443+
addInstToCurrentSourceAtom(I, Src);
14401444
}
14411445
} else if (SrcTy->isIntegerTy()) {
14421446
// If the source is a simple integer, coerce it directly.
14431447
llvm::Type *DstIntTy = Builder.getIntNTy(DstSize.getFixedValue() * 8);
14441448
Src = CoerceIntOrPtrToIntOrPtr(Src, DstIntTy, *this);
1445-
Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile);
1449+
auto *I =
1450+
Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile);
1451+
addInstToCurrentSourceAtom(I, Src);
14461452
} else {
14471453
// Otherwise do coercion through memory. This is stupid, but
14481454
// simple.
@@ -1456,10 +1462,11 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
14561462
RawAddress Tmp =
14571463
CreateTempAllocaForCoercion(*this, SrcTy, Dst.getAlignment());
14581464
Builder.CreateStore(Src, Tmp);
1459-
Builder.CreateMemCpy(Dst.emitRawPointer(*this),
1460-
Dst.getAlignment().getAsAlign(), Tmp.getPointer(),
1461-
Tmp.getAlignment().getAsAlign(),
1462-
Builder.CreateTypeSize(IntPtrTy, DstSize));
1465+
auto *I = Builder.CreateMemCpy(
1466+
Dst.emitRawPointer(*this), Dst.getAlignment().getAsAlign(),
1467+
Tmp.getPointer(), Tmp.getAlignment().getAsAlign(),
1468+
Builder.CreateTypeSize(IntPtrTy, DstSize));
1469+
addInstToCurrentSourceAtom(I, Src);
14631470
}
14641471
}
14651472

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple arm64-apple-ios11 \
2+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
3+
4+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple arm64-apple-ios11 \
5+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
6+
7+
typedef struct {
8+
char a;
9+
int x;
10+
} __attribute((packed)) S;
11+
12+
S getS();
13+
void f() {
14+
// CHECK: [[call:%.*]] = call i40{{.*}}getS{{.*}}, !dbg [[G1R2:!.*]]
15+
// CHECK: store i40 [[call]], ptr %s, align 1, !dbg [[G1R1:!.*]]
16+
S s = getS();
17+
}
18+
19+
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
20+
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-windows-msvc \
2+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
3+
4+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-windows-msvc \
5+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
6+
7+
typedef struct { int *p; } Ptr;
8+
Ptr getPtr();
9+
void f() {
10+
// CHECK: %call = call i64{{.*}}, !dbg [[G1R3:!.*]]
11+
// CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Ptr, ptr %p, i32 0, i32 0
12+
// CHECK: [[i2p:%.*]] = inttoptr i64 %call to ptr, !dbg [[G1R2:!.*]]
13+
// CHECK: store ptr [[i2p]], ptr [[gep]], align 8, !dbg [[G1R1:!.*]]
14+
Ptr p = getPtr();
15+
}
16+
17+
// CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3)
18+
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
19+
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple aarch64-windows-msvc \
2+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
3+
4+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple aarch64-windows-msvc \
5+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
6+
7+
typedef struct {
8+
short a;
9+
int b;
10+
short c;
11+
} S;
12+
13+
S getS(void);
14+
15+
void f() {
16+
// CHECK: %call = call [2 x i64] {{.*}}getS{{.*}}(), !dbg [[G1R2:!.*]]
17+
//// Note: The store to the tmp alloca isn't part of the atom.
18+
// CHECK: store [2 x i64] %call, ptr %tmp.coerce, align 8
19+
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %s, ptr align 8 %tmp.coerce, i64 12, i1 false), !dbg [[G1R1:!.*]]
20+
S s = getS();
21+
}
22+
23+
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
24+
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-unknown-linux \
2+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX
3+
4+
// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple x86_64-unknown-linux \
5+
// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C
6+
7+
typedef struct {
8+
void* a;
9+
void* b;
10+
} Struct;
11+
Struct get();
12+
13+
void test() {
14+
// CHECK: %1 = extractvalue { ptr, ptr } %call, 0, !dbg [[G1R2:!.*]]
15+
// CHECK: store ptr %1, ptr {{.*}}, !dbg [[G1R1:!.*]]
16+
// CHECK: %3 = extractvalue { ptr, ptr } %call, 1, !dbg [[G1R2]]
17+
// CHECK: store ptr %3, ptr {{.*}}, !dbg [[G1R1:!.*]]
18+
Struct s = get();
19+
}
20+
21+
typedef struct { int i; } Int;
22+
Int getInt(void);
23+
24+
// CHECK-C: @test2
25+
// CHECK-CXX: @_Z5test2v
26+
void test2() {
27+
// CHECK: %call = call i32 @{{(_Z6)?}}getInt{{v?}}(), !dbg [[T2_G1R2:!.*]]
28+
// CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Int, ptr %i, i32 0, i32 0
29+
// CHECK: store i32 %call, ptr [[gep]]{{.*}}, !dbg [[T2_G1R1:!.*]]
30+
Int i = getInt();
31+
}
32+
33+
// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
34+
// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
35+
// CHECK: [[T2_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
36+
// CHECK: [[T2_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)

0 commit comments

Comments
 (0)