[clang] 347273d - [KeyInstr][Clang] Coerced store atoms (#134653)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 3 01:22:41 PDT 2025
Author: Orlando Cazalet-Hyams
Date: 2025-06-03T09:22:37+01:00
New Revision: 347273db2f33938e8f35de7b6c384d042b890052
URL: https://github.com/llvm/llvm-project/commit/347273db2f33938e8f35de7b6c384d042b890052
DIFF: https://github.com/llvm/llvm-project/commit/347273db2f33938e8f35de7b6c384d042b890052.diff
LOG: [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.
Added:
clang/test/DebugInfo/KeyInstructions/coerced-packed.c
clang/test/DebugInfo/KeyInstructions/coerced-ptr.c
clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c
clang/test/DebugInfo/KeyInstructions/coerced.c
Modified:
clang/lib/CodeGen/CGCall.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index c58b8dc67410b..056caf64525a5 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -1425,7 +1425,8 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
SrcSize == CGM.getDataLayout().getTypeAllocSize(Dst.getElementType())) {
// If the value is supposed to be a pointer, convert it before storing it.
Src = CoerceIntOrPtrToIntOrPtr(Src, Dst.getElementType(), *this);
- Builder.CreateStore(Src, Dst, DstIsVolatile);
+ auto *I = Builder.CreateStore(Src, Dst, DstIsVolatile);
+ addInstToCurrentSourceAtom(I, Src);
} else if (llvm::StructType *STy =
dyn_cast<llvm::StructType>(Src->getType())) {
// Prefer scalar stores to first-class aggregate stores.
@@ -1433,16 +1434,21 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
Address EltPtr = Builder.CreateStructGEP(Dst, i);
llvm::Value *Elt = Builder.CreateExtractValue(Src, i);
- Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
+ auto *I = Builder.CreateStore(Elt, EltPtr, DstIsVolatile);
+ addInstToCurrentSourceAtom(I, Elt);
}
} else {
- Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile);
+ auto *I =
+ Builder.CreateStore(Src, Dst.withElementType(SrcTy), DstIsVolatile);
+ addInstToCurrentSourceAtom(I, Src);
}
} else if (SrcTy->isIntegerTy()) {
// If the source is a simple integer, coerce it directly.
llvm::Type *DstIntTy = Builder.getIntNTy(DstSize.getFixedValue() * 8);
Src = CoerceIntOrPtrToIntOrPtr(Src, DstIntTy, *this);
- Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile);
+ auto *I =
+ Builder.CreateStore(Src, Dst.withElementType(DstIntTy), DstIsVolatile);
+ addInstToCurrentSourceAtom(I, Src);
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
@@ -1456,10 +1462,11 @@ void CodeGenFunction::CreateCoercedStore(llvm::Value *Src, Address Dst,
RawAddress Tmp =
CreateTempAllocaForCoercion(*this, SrcTy, Dst.getAlignment());
Builder.CreateStore(Src, Tmp);
- Builder.CreateMemCpy(Dst.emitRawPointer(*this),
- Dst.getAlignment().getAsAlign(), Tmp.getPointer(),
- Tmp.getAlignment().getAsAlign(),
- Builder.CreateTypeSize(IntPtrTy, DstSize));
+ auto *I = Builder.CreateMemCpy(
+ Dst.emitRawPointer(*this), Dst.getAlignment().getAsAlign(),
+ Tmp.getPointer(), Tmp.getAlignment().getAsAlign(),
+ Builder.CreateTypeSize(IntPtrTy, DstSize));
+ addInstToCurrentSourceAtom(I, Src);
}
}
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-packed.c b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c
new file mode 100644
index 0000000000000..90ec8420b0d8c
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/coerced-packed.c
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple arm64-apple-ios11 \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple arm64-apple-ios11 \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+typedef struct {
+ char a;
+ int x;
+} __attribute((packed)) S;
+
+S getS();
+void f() {
+// CHECK: [[call:%.*]] = call i40{{.*}}getS{{.*}}, !dbg [[G1R2:!.*]]
+// CHECK: store i40 [[call]], ptr %s, align 1, !dbg [[G1R1:!.*]]
+ S s = getS();
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c
new file mode 100644
index 0000000000000..0002e9051220b
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/coerced-ptr.c
@@ -0,0 +1,19 @@
+// 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 \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// 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 \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+typedef struct { int *p; } Ptr;
+Ptr getPtr();
+void f() {
+// CHECK: %call = call i64{{.*}}, !dbg [[G1R3:!.*]]
+// CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Ptr, ptr %p, i32 0, i32 0
+// CHECK: [[i2p:%.*]] = inttoptr i64 %call to ptr, !dbg [[G1R2:!.*]]
+// CHECK: store ptr [[i2p]], ptr [[gep]], align 8, !dbg [[G1R1:!.*]]
+ Ptr p = getPtr();
+}
+
+// CHECK: [[G1R3]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 3)
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c
new file mode 100644
index 0000000000000..98361aa9806ef
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/coerced-through-memory.c
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c++ %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple aarch64-windows-msvc \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+// RUN: %clang_cc1 -gkey-instructions -gno-column-info -x c %s -debug-info-kind=line-tables-only -emit-llvm -o - -triple aarch64-windows-msvc \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank
+
+typedef struct {
+ short a;
+ int b;
+ short c;
+} S;
+
+S getS(void);
+
+void f() {
+// CHECK: %call = call [2 x i64] {{.*}}getS{{.*}}(), !dbg [[G1R2:!.*]]
+//// Note: The store to the tmp alloca isn't part of the atom.
+// CHECK: store [2 x i64] %call, ptr %tmp.coerce, align 8
+// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %s, ptr align 8 %tmp.coerce, i64 12, i1 false), !dbg [[G1R1:!.*]]
+ S s = getS();
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
diff --git a/clang/test/DebugInfo/KeyInstructions/coerced.c b/clang/test/DebugInfo/KeyInstructions/coerced.c
new file mode 100644
index 0000000000000..b5a254fb641c9
--- /dev/null
+++ b/clang/test/DebugInfo/KeyInstructions/coerced.c
@@ -0,0 +1,36 @@
+// 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 \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-CXX
+
+// 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 \
+// RUN: | FileCheck %s --implicit-check-not atomGroup --implicit-check-not atomRank --check-prefixes=CHECK,CHECK-C
+
+typedef struct {
+ void* a;
+ void* b;
+} Struct;
+Struct get();
+
+void test() {
+// CHECK: %1 = extractvalue { ptr, ptr } %call, 0, !dbg [[G1R2:!.*]]
+// CHECK: store ptr %1, ptr {{.*}}, !dbg [[G1R1:!.*]]
+// CHECK: %3 = extractvalue { ptr, ptr } %call, 1, !dbg [[G1R2]]
+// CHECK: store ptr %3, ptr {{.*}}, !dbg [[G1R1:!.*]]
+ Struct s = get();
+}
+
+typedef struct { int i; } Int;
+Int getInt(void);
+
+// CHECK-C: @test2
+// CHECK-CXX: @_Z5test2v
+void test2() {
+// CHECK: %call = call i32 @{{(_Z6)?}}getInt{{v?}}(), !dbg [[T2_G1R2:!.*]]
+// CHECK: [[gep:%.*]] = getelementptr inbounds nuw %struct.Int, ptr %i, i32 0, i32 0
+// CHECK: store i32 %call, ptr [[gep]]{{.*}}, !dbg [[T2_G1R1:!.*]]
+ Int i = getInt();
+}
+
+// CHECK: [[G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
+// CHECK: [[T2_G1R2]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 2)
+// CHECK: [[T2_G1R1]] = !DILocation({{.*}}, atomGroup: 1, atomRank: 1)
More information about the cfe-commits
mailing list