[clang] 7e29448 - [CIR] Upstream var arg copy builtin (#169415)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 2 06:28:17 PST 2025
Author: Hendrik Hübner
Date: 2025-12-02T15:28:12+01:00
New Revision: 7e29448b4e517631b228b11e855b8ecd1d357dff
URL: https://github.com/llvm/llvm-project/commit/7e29448b4e517631b228b11e855b8ecd1d357dff
DIFF: https://github.com/llvm/llvm-project/commit/7e29448b4e517631b228b11e855b8ecd1d357dff.diff
LOG: [CIR] Upstream var arg copy builtin (#169415)
This PR upstreams `__builtin_va_copy`, and extends the existing tests.
Added:
Modified:
clang/include/clang/CIR/Dialect/IR/CIROps.td
clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
clang/test/CIR/CodeGen/var_arg.c
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 9c1188e16c5a5..4b64fc56c57ad 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -4820,6 +4820,37 @@ 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
+ // %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>)
+ ```
+ }];
+
+ 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 8fd3ffeb4e261..e14b5f8aac337 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 04bc55256f62c..8e9780754f68f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -4061,6 +4061,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 04a3350d372ee..aab909eb67672 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,23 @@ 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]]
+
+void stdarg_copy() {
+ __builtin_va_list src, dest;
+ __builtin_va_copy(src, dest);
+}
+
+// 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: @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: @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 %{{.*}}
More information about the cfe-commits
mailing list