[clang] [CIR] Upstream var arg copy builtin (PR #169415)
Hendrik Hübner via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 27 13:13:43 PST 2025
https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/169415
>From 905c12d4865978533b34ee2b20c77790d09e973e Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Mon, 24 Nov 2025 23:05:09 +0100
Subject: [PATCH 1/4] [CIR] Add VACopy builtin
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 26 +++++
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 7 +-
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 12 ++
clang/test/CIR/CodeGen/var_arg.c | 103 +++++++++++++++++-
4 files changed, 146 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index a19c4f951fff9..8ad203c43a001 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4704,6 +4704,32 @@ def CIR_VAEndOp : CIR_Op<"va_end"> {
}];
}
+def CIR_VACopyOp : CIR_Op<"va.copy"> {
+ let summary = "Copied a variable argument list";
+ let description = [{
+ The `cir.copy` operation models the C/C++ va_copy macro.
+ The variable argument list passed as the `$src_list` is copied to an
+ unitialized `va_list` in the destination operand. The next argument that
+ can be extracted from the copied list is the same as the next argument in
+ the source list. The copied list must be destroyed with `va_end`.
+
+ Example:
+
+ ```mlir
+
+ ```
+ }];
+
+ let arguments = (ins
+ CIR_PointerType:$dst_list,
+ CIR_PointerType:$src_list
+ );
+
+ let assemblyFormat = [{
+ $src_list `to` $dst_list attr-dict `:` type(operands)
+ }];
+}
+
def CIR_VAArgOp : CIR_Op<"va_arg"> {
let summary = "Fetches next variadic element as a given type";
let description = [{
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index d220fdf4dc8a7..95ddfdfc7358a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -266,7 +266,12 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
case Builtin::BI__builtin_va_end:
emitVAEnd(emitVAListRef(e->getArg(0)).getPointer());
return {};
-
+ case Builtin::BI__builtin_va_copy: {
+ mlir::Value dstPtr = emitVAListRef(e->getArg(0)).getPointer();
+ mlir::Value srcPtr = emitVAListRef(e->getArg(1)).getPointer();
+ cir::VACopyOp::create(builder, dstPtr.getLoc(), dstPtr, srcPtr);
+ return {};
+ }
case Builtin::BIcos:
case Builtin::BIcosf:
case Builtin::BIcosl:
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 6136d48204e0c..f3c1b92fafcd3 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4034,6 +4034,18 @@ mlir::LogicalResult CIRToLLVMVAEndOpLowering::matchAndRewrite(
return mlir::success();
}
+mlir::LogicalResult CIRToLLVMVACopyOpLowering::matchAndRewrite(
+ cir::VACopyOp op, OpAdaptor adaptor,
+ mlir::ConversionPatternRewriter &rewriter) const {
+ auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext());
+ auto dstList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
+ adaptor.getDstList());
+ auto srcList = mlir::LLVM::BitcastOp::create(rewriter, op.getLoc(), opaquePtr,
+ adaptor.getSrcList());
+ rewriter.replaceOpWithNewOp<mlir::LLVM::VaCopyOp>(op, dstList, srcList);
+ return mlir::success();
+}
+
mlir::LogicalResult CIRToLLVMVAArgOpLowering::matchAndRewrite(
cir::VAArgOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/test/CIR/CodeGen/var_arg.c b/clang/test/CIR/CodeGen/var_arg.c
index f5b92c61e11ad..82de39a3db58a 100644
--- a/clang/test/CIR/CodeGen/var_arg.c
+++ b/clang/test/CIR/CodeGen/var_arg.c
@@ -141,7 +141,7 @@ int stdarg_start(int count, ...) {
// OGCG: %[[COND:.+]] = icmp ule i32 %[[GPOFFSET]], 40
// OGCG: br i1 %[[COND]], label %vaarg.in_reg, label %vaarg.in_mem
//
-// OGCG: vaarg.in_reg:
+// OGCG: vaarg.in_reg:
// OGCG: %[[REGSAVE_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY1]], i32 0, i32 3
// OGCG: %[[REGSAVE:.+]] = load ptr, ptr %[[REGSAVE_PTR]]
// OGCG: %[[VAADDR1:.+]] = getelementptr i8, ptr %[[REGSAVE]], i32 %[[GPOFFSET]]
@@ -164,3 +164,104 @@ int stdarg_start(int count, ...) {
// OGCG: call void @llvm.va_end.p0(ptr %[[DECAY2]])
// OGCG: %[[VAL:.+]] = load i32, ptr %[[RES_ADDR]]
// OGCG: ret i32 %[[VAL]]
+
+int stdarg_copy(int count, ...) {
+ __builtin_va_list args;
+ __builtin_stdarg_start(args, 12345);
+ __builtin_va_list dup;
+ __builtin_va_copy(args, dup);
+ int res = __builtin_va_arg(dup, int);
+ __builtin_va_end(args);
+ __builtin_va_end(dup);
+ return res;
+}
+
+// CIR-LABEL: cir.func dso_local @stdarg_copy(
+// CIR: %[[COUNT_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["count", init]
+// CIR: %[[RET_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR: %[[VAAREA:.+]] = cir.alloca !cir.array<!rec___va_list_tag x 1>, !cir.ptr<!cir.array<!rec___va_list_tag x 1>>, ["args"]
+// CIR: %[[DUP_AREA:.+]] = cir.alloca !cir.array<!rec___va_list_tag x 1>, !cir.ptr<!cir.array<!rec___va_list_tag x 1>>, ["dup"]
+// CIR: %[[RES_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["res", init]
+// CIR: cir.store %arg0, %[[COUNT_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[VA_PTR0:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: %[[C12345:.+]] = cir.const #cir.int<12345> : !s32i
+// CIR: cir.va_start %[[VA_PTR0]] %[[C12345]] : !cir.ptr<!rec___va_list_tag>, !s32i
+// CIR: %[[VA_PTR_SRC:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: %[[VA_PTR_DEST:.+]] = cir.cast array_to_ptrdecay %[[DUP_AREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va.copy %[[VA_PTR_DEST]] to %[[VA_PTR_SRC]] : !cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>
+// CIR: %[[VA_PTR_COPY:.+]] = cir.cast array_to_ptrdecay %[[DUP_AREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: %[[VA_ARG:.+]] = cir.va_arg %[[VA_PTR_COPY]] : (!cir.ptr<!rec___va_list_tag>) -> !s32i
+// CIR: cir.store{{.*}} %[[VA_ARG]], %[[RES_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[VA_PTR2:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va_end %[[VA_PTR2]] : !cir.ptr<!rec___va_list_tag>
+// CIR: %[[VA_PTR3:.+]] = cir.cast array_to_ptrdecay %[[DUP_AREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va_end %[[VA_PTR3]] : !cir.ptr<!rec___va_list_tag>
+// CIR: %[[RESULT:.+]] = cir.load{{.*}} %[[RES_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store %[[RESULT]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[RETVAL:.+]] = cir.load{{.*}} %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.return %[[RETVAL]] : !s32i
+
+// LLVM-LABEL: define dso_local i32 @stdarg_copy(
+// LLVM: %[[COUNT_ADDR:.+]] = alloca i32{{.*}}
+// LLVM: %[[RET_ADDR:.+]] = alloca i32{{.*}}
+// LLVM: %[[VAAREA:.+]] = alloca [1 x %struct.__va_list_tag]{{.*}}
+// LLVM: %[[DUP_AREA:.+]] = alloca [1 x %struct.__va_list_tag]{{.*}}
+// LLVM: %[[RES_ADDR:.+]] = alloca i32{{.*}}
+// LLVM: %[[VA_PTR0:.+]] = getelementptr %struct.__va_list_tag, ptr %[[VAAREA]], i32 0
+// LLVM: call void @llvm.va_start.p0(ptr %[[VA_PTR0]])
+// LLVM: %[[VA_PTR1:.+]] = getelementptr %struct.__va_list_tag, ptr %[[VAAREA]], i32 0
+// LLVM: %[[VA_PTR_DUP:.+]] = getelementptr %struct.__va_list_tag, ptr %[[DUP_AREA]], i32 0
+// LLVM: call void @llvm.va_copy.p0(ptr %[[VA_PTR1]], ptr %[[VA_PTR_DUP]])
+// LLVM: %[[VA_PTR_DUP2:.+]] = getelementptr %struct.__va_list_tag, ptr %[[DUP_AREA]], i32 0
+// LLVM: %[[VA_ARG:.+]] = va_arg ptr %[[VA_PTR_DUP2]], i32
+// LLVM: store i32 %[[VA_ARG]], ptr %[[RES_ADDR]], {{.*}}
+// LLVM: %[[VA_PTR2:.+]] = getelementptr %struct.__va_list_tag, ptr %[[VAAREA]], i32 0
+// LLVM: call void @llvm.va_end.p0(ptr %[[VA_PTR2]])
+// LLVM: %[[VA_PTR3:.+]] = getelementptr %struct.__va_list_tag, ptr %[[DUP_AREA]], i32 0
+// LLVM: call void @llvm.va_end.p0(ptr %[[VA_PTR3]])
+// LLVM: %[[TMP_LOAD:.+]] = load i32, ptr %[[RES_ADDR]], {{.*}}
+// LLVM: store i32 %[[TMP_LOAD]], ptr %[[RET_ADDR]], {{.*}}
+// LLVM: %[[RETVAL:.+]] = load i32, ptr %[[RET_ADDR]], {{.*}}
+// LLVM: ret i32 %[[RETVAL]]
+
+// OGCG-LABEL: define dso_local i32 @stdarg_copy
+// OGCG: %[[COUNT_ADDR:.+]] = alloca i32
+// OGCG: %[[VAAREA:.+]] = alloca [1 x %struct.__va_list_tag]
+// OGCG: %[[DUP_AREA:.+]] = alloca [1 x %struct.__va_list_tag]
+// OGCG: %[[RES_ADDR:.+]] = alloca i32
+// OGCG: %[[DECAY:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[VAAREA]], i64 0, i64 0
+// OGCG: call void @llvm.va_start.p0(ptr %[[DECAY]])
+// OGCG: %[[DECAY1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[VAAREA]], i64 0, i64 0
+// OGCG: %[[DECAY_DUP:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[DUP_AREA]], i64 0, i64 0
+// OGCG: call void @llvm.va_copy.p0(ptr %[[DECAY1]], ptr %[[DECAY_DUP]])
+// OGCG: %[[DECAY_DUP2:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[DUP_AREA]], i64 0, i64 0
+// OGCG: %[[GPOFFSET_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY_DUP2]], i32 0, i32 0
+// OGCG: %[[GPOFFSET:.+]] = load i32, ptr %[[GPOFFSET_PTR]]
+// OGCG: %[[COND:.+]] = icmp ule i32 %[[GPOFFSET]], 40
+// OGCG: br i1 %[[COND]], label %vaarg.in_reg, label %vaarg.in_mem
+//
+// OGCG: vaarg.in_reg:
+// OGCG: %[[REGSAVE_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY_DUP2]], i32 0, i32 3
+// OGCG: %[[REGSAVE:.+]] = load ptr, ptr %[[REGSAVE_PTR]]
+// OGCG: %[[VAADDR1:.+]] = getelementptr i8, ptr %[[REGSAVE]], i32 %[[GPOFFSET]]
+// OGCG: %[[NEXT_GPOFFSET:.+]] = add i32 %[[GPOFFSET]], 8
+// OGCG: store i32 %[[NEXT_GPOFFSET]], ptr %[[GPOFFSET_PTR]]
+// OGCG: br label %vaarg.end
+//
+// OGCG: vaarg.in_mem:
+// OGCG: %[[OVERFLOW_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY_DUP2]], i32 0, i32 2
+// OGCG: %[[OVERFLOW:.+]] = load ptr, ptr %[[OVERFLOW_PTR]]
+// OGCG: %[[OVERFLOW_NEXT:.+]] = getelementptr i8, ptr %[[OVERFLOW]], i32 8
+// OGCG: store ptr %[[OVERFLOW_NEXT]], ptr %[[OVERFLOW_PTR]]
+// OGCG: br label %vaarg.end
+//
+// OGCG: vaarg.end:
+// OGCG: %[[PHI:.+]] = phi ptr [ %[[VAADDR1]], %vaarg.in_reg ], [ %[[OVERFLOW]], %vaarg.in_mem ]
+// OGCG: %[[LOADED:.+]] = load i32, ptr %[[PHI]]
+// OGCG: store i32 %[[LOADED]], ptr %[[RES_ADDR]]
+// OGCG: %[[DECAY2:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[VAAREA]], i64 0, i64 0
+// OGCG: call void @llvm.va_end.p0(ptr %[[DECAY2]])
+// OGCG: %[[DECAY_DUP3:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[DUP_AREA]], i64 0, i64 0
+// OGCG: call void @llvm.va_end.p0(ptr %[[DECAY_DUP3]])
+// OGCG: %[[VAL:.+]] = load i32, ptr %[[RES_ADDR]]
+// OGCG: ret i32 %[[VAL]]
>From 6ddc17027ed4d51e8a62b281520421b0b4dcf7b2 Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Mon, 24 Nov 2025 23:07:36 +0100
Subject: [PATCH 2/4] example
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 8ad203c43a001..78143ab44fa7e 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4716,6 +4716,14 @@ def CIR_VACopyOp : CIR_Op<"va.copy"> {
Example:
```mlir
+ ```mlir
+ // %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
+ %p = cir.cast array_to_ptrdecay %args
+ : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
+ -> !cir.ptr<!rec___va_list_tag>
+ cir.va.copy %p to %dst
+ : (!cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>)
+ ```
```
}];
>From 1c5351ec69de26ece6835ec135ad41a542fb0ca4 Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Thu, 27 Nov 2025 02:06:30 +0100
Subject: [PATCH 3/4] test
---
clang/test/CIR/CodeGen/var_arg.c | 111 +++++--------------------------
1 file changed, 15 insertions(+), 96 deletions(-)
diff --git a/clang/test/CIR/CodeGen/var_arg.c b/clang/test/CIR/CodeGen/var_arg.c
index 82de39a3db58a..6e59b9daba0f4 100644
--- a/clang/test/CIR/CodeGen/var_arg.c
+++ b/clang/test/CIR/CodeGen/var_arg.c
@@ -165,103 +165,22 @@ int stdarg_start(int count, ...) {
// OGCG: %[[VAL:.+]] = load i32, ptr %[[RES_ADDR]]
// OGCG: ret i32 %[[VAL]]
-int stdarg_copy(int count, ...) {
- __builtin_va_list args;
- __builtin_stdarg_start(args, 12345);
- __builtin_va_list dup;
- __builtin_va_copy(args, dup);
- int res = __builtin_va_arg(dup, int);
- __builtin_va_end(args);
- __builtin_va_end(dup);
- return res;
+void stdarg_copy() {
+ __builtin_va_list src, dest;
+ __builtin_va_copy(src, dest);
}
-// CIR-LABEL: cir.func dso_local @stdarg_copy(
-// CIR: %[[COUNT_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["count", init]
-// CIR: %[[RET_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
-// CIR: %[[VAAREA:.+]] = cir.alloca !cir.array<!rec___va_list_tag x 1>, !cir.ptr<!cir.array<!rec___va_list_tag x 1>>, ["args"]
-// CIR: %[[DUP_AREA:.+]] = cir.alloca !cir.array<!rec___va_list_tag x 1>, !cir.ptr<!cir.array<!rec___va_list_tag x 1>>, ["dup"]
-// CIR: %[[RES_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["res", init]
-// CIR: cir.store %arg0, %[[COUNT_ADDR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[VA_PTR0:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
-// CIR: %[[C12345:.+]] = cir.const #cir.int<12345> : !s32i
-// CIR: cir.va_start %[[VA_PTR0]] %[[C12345]] : !cir.ptr<!rec___va_list_tag>, !s32i
-// CIR: %[[VA_PTR_SRC:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
-// CIR: %[[VA_PTR_DEST:.+]] = cir.cast array_to_ptrdecay %[[DUP_AREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
-// CIR: cir.va.copy %[[VA_PTR_DEST]] to %[[VA_PTR_SRC]] : !cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>
-// CIR: %[[VA_PTR_COPY:.+]] = cir.cast array_to_ptrdecay %[[DUP_AREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
-// CIR: %[[VA_ARG:.+]] = cir.va_arg %[[VA_PTR_COPY]] : (!cir.ptr<!rec___va_list_tag>) -> !s32i
-// CIR: cir.store{{.*}} %[[VA_ARG]], %[[RES_ADDR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[VA_PTR2:.+]] = cir.cast array_to_ptrdecay %[[VAAREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
-// CIR: cir.va_end %[[VA_PTR2]] : !cir.ptr<!rec___va_list_tag>
-// CIR: %[[VA_PTR3:.+]] = cir.cast array_to_ptrdecay %[[DUP_AREA]] : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
-// CIR: cir.va_end %[[VA_PTR3]] : !cir.ptr<!rec___va_list_tag>
-// CIR: %[[RESULT:.+]] = cir.load{{.*}} %[[RES_ADDR]] : !cir.ptr<!s32i>, !s32i
-// CIR: cir.store %[[RESULT]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[RETVAL:.+]] = cir.load{{.*}} %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
-// CIR: cir.return %[[RETVAL]] : !s32i
+// CIR-LABEL: @stdarg_copy
+// CIR: %{{.*}} = cir.cast array_to_ptrdecay %{{.*}} : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: %{{.*}} = cir.cast array_to_ptrdecay %{{.*}} : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va.copy %{{.*}} to %{{.*}} : !cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>
-// LLVM-LABEL: define dso_local i32 @stdarg_copy(
-// LLVM: %[[COUNT_ADDR:.+]] = alloca i32{{.*}}
-// LLVM: %[[RET_ADDR:.+]] = alloca i32{{.*}}
-// LLVM: %[[VAAREA:.+]] = alloca [1 x %struct.__va_list_tag]{{.*}}
-// LLVM: %[[DUP_AREA:.+]] = alloca [1 x %struct.__va_list_tag]{{.*}}
-// LLVM: %[[RES_ADDR:.+]] = alloca i32{{.*}}
-// LLVM: %[[VA_PTR0:.+]] = getelementptr %struct.__va_list_tag, ptr %[[VAAREA]], i32 0
-// LLVM: call void @llvm.va_start.p0(ptr %[[VA_PTR0]])
-// LLVM: %[[VA_PTR1:.+]] = getelementptr %struct.__va_list_tag, ptr %[[VAAREA]], i32 0
-// LLVM: %[[VA_PTR_DUP:.+]] = getelementptr %struct.__va_list_tag, ptr %[[DUP_AREA]], i32 0
-// LLVM: call void @llvm.va_copy.p0(ptr %[[VA_PTR1]], ptr %[[VA_PTR_DUP]])
-// LLVM: %[[VA_PTR_DUP2:.+]] = getelementptr %struct.__va_list_tag, ptr %[[DUP_AREA]], i32 0
-// LLVM: %[[VA_ARG:.+]] = va_arg ptr %[[VA_PTR_DUP2]], i32
-// LLVM: store i32 %[[VA_ARG]], ptr %[[RES_ADDR]], {{.*}}
-// LLVM: %[[VA_PTR2:.+]] = getelementptr %struct.__va_list_tag, ptr %[[VAAREA]], i32 0
-// LLVM: call void @llvm.va_end.p0(ptr %[[VA_PTR2]])
-// LLVM: %[[VA_PTR3:.+]] = getelementptr %struct.__va_list_tag, ptr %[[DUP_AREA]], i32 0
-// LLVM: call void @llvm.va_end.p0(ptr %[[VA_PTR3]])
-// LLVM: %[[TMP_LOAD:.+]] = load i32, ptr %[[RES_ADDR]], {{.*}}
-// LLVM: store i32 %[[TMP_LOAD]], ptr %[[RET_ADDR]], {{.*}}
-// LLVM: %[[RETVAL:.+]] = load i32, ptr %[[RET_ADDR]], {{.*}}
-// LLVM: ret i32 %[[RETVAL]]
+// LLVM-LABEL: @stdarg_copy
+// LLVM: %{{.*}} = getelementptr %struct.__va_list_tag, ptr %{{.*}}
+// LLVM: %{{.*}} = getelementptr %struct.__va_list_tag, ptr %{{.*}}
+// LLVM: call void @llvm.va_copy.p0(ptr %{{.*}}, ptr %{{.*}}
-// OGCG-LABEL: define dso_local i32 @stdarg_copy
-// OGCG: %[[COUNT_ADDR:.+]] = alloca i32
-// OGCG: %[[VAAREA:.+]] = alloca [1 x %struct.__va_list_tag]
-// OGCG: %[[DUP_AREA:.+]] = alloca [1 x %struct.__va_list_tag]
-// OGCG: %[[RES_ADDR:.+]] = alloca i32
-// OGCG: %[[DECAY:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[VAAREA]], i64 0, i64 0
-// OGCG: call void @llvm.va_start.p0(ptr %[[DECAY]])
-// OGCG: %[[DECAY1:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[VAAREA]], i64 0, i64 0
-// OGCG: %[[DECAY_DUP:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[DUP_AREA]], i64 0, i64 0
-// OGCG: call void @llvm.va_copy.p0(ptr %[[DECAY1]], ptr %[[DECAY_DUP]])
-// OGCG: %[[DECAY_DUP2:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[DUP_AREA]], i64 0, i64 0
-// OGCG: %[[GPOFFSET_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY_DUP2]], i32 0, i32 0
-// OGCG: %[[GPOFFSET:.+]] = load i32, ptr %[[GPOFFSET_PTR]]
-// OGCG: %[[COND:.+]] = icmp ule i32 %[[GPOFFSET]], 40
-// OGCG: br i1 %[[COND]], label %vaarg.in_reg, label %vaarg.in_mem
-//
-// OGCG: vaarg.in_reg:
-// OGCG: %[[REGSAVE_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY_DUP2]], i32 0, i32 3
-// OGCG: %[[REGSAVE:.+]] = load ptr, ptr %[[REGSAVE_PTR]]
-// OGCG: %[[VAADDR1:.+]] = getelementptr i8, ptr %[[REGSAVE]], i32 %[[GPOFFSET]]
-// OGCG: %[[NEXT_GPOFFSET:.+]] = add i32 %[[GPOFFSET]], 8
-// OGCG: store i32 %[[NEXT_GPOFFSET]], ptr %[[GPOFFSET_PTR]]
-// OGCG: br label %vaarg.end
-//
-// OGCG: vaarg.in_mem:
-// OGCG: %[[OVERFLOW_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY_DUP2]], i32 0, i32 2
-// OGCG: %[[OVERFLOW:.+]] = load ptr, ptr %[[OVERFLOW_PTR]]
-// OGCG: %[[OVERFLOW_NEXT:.+]] = getelementptr i8, ptr %[[OVERFLOW]], i32 8
-// OGCG: store ptr %[[OVERFLOW_NEXT]], ptr %[[OVERFLOW_PTR]]
-// OGCG: br label %vaarg.end
-//
-// OGCG: vaarg.end:
-// OGCG: %[[PHI:.+]] = phi ptr [ %[[VAADDR1]], %vaarg.in_reg ], [ %[[OVERFLOW]], %vaarg.in_mem ]
-// OGCG: %[[LOADED:.+]] = load i32, ptr %[[PHI]]
-// OGCG: store i32 %[[LOADED]], ptr %[[RES_ADDR]]
-// OGCG: %[[DECAY2:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[VAAREA]], i64 0, i64 0
-// OGCG: call void @llvm.va_end.p0(ptr %[[DECAY2]])
-// OGCG: %[[DECAY_DUP3:.+]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %[[DUP_AREA]], i64 0, i64 0
-// OGCG: call void @llvm.va_end.p0(ptr %[[DECAY_DUP3]])
-// OGCG: %[[VAL:.+]] = load i32, ptr %[[RES_ADDR]]
-// OGCG: ret i32 %[[VAL]]
+// OGCG-LABEL: @stdarg_copy
+// OGCG: %{{.*}} = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %{{.*}}
+// OGCG: %{{.*}} = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %{{.*}}
+// OGCG: call void @llvm.va_copy.p0(ptr %{{.*}}, ptr %{{.*}}
>From 72bdfb076f5054ef405dd10b6dcee586a4b20005 Mon Sep 17 00:00:00 2001
From: hhuebner <hendrik.huebner18 at gmail.com>
Date: Thu, 27 Nov 2025 22:12:52 +0100
Subject: [PATCH 4/4] formatting
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 3 ---
1 file changed, 3 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 78143ab44fa7e..0a9450f666c34 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4715,7 +4715,6 @@ def CIR_VACopyOp : CIR_Op<"va.copy"> {
Example:
- ```mlir
```mlir
// %args : !cir.ptr<!cir.array<!rec___va_list_tag x 1>>
%p = cir.cast array_to_ptrdecay %args
@@ -4724,8 +4723,6 @@ def CIR_VACopyOp : CIR_Op<"va.copy"> {
cir.va.copy %p to %dst
: (!cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>)
```
-
- ```
}];
let arguments = (ins
More information about the cfe-commits
mailing list