https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/169415
From 905c12d4865978533b34ee2b20c77790d09e973e Mon Sep 17 00:00:00 2001 From: hhuebner <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
