diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h index 1dbef0d24ddd..df96fa73f9f3 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepareItaniumCXXABI.h @@ -20,5 +20,8 @@ class LoweringPrepareItaniumCXXABI : public cir::LoweringPrepareCXXABI { clang::ASTContext &astCtx, mlir::cir::DynamicCastOp op) override; mlir::Value lowerVAArg(cir::CIRBaseBuilderTy &builder, mlir::cir::VAArgOp op, - const cir::CIRDataLayout &datalayout) override; + const cir::CIRDataLayout &datalayout) override { + // Itanium C++ ABI has nothing to do with VAArg. + return {}; + } }; diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp index 9d79fb7ccb43..11d66f8e66db 100644 --- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp +++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/Targets/LoweringPrepareItaniumCXXABI.cpp @@ -163,11 +163,3 @@ LoweringPrepareItaniumCXXABI::lowerDynamicCast(CIRBaseBuilderTy &builder, }) .getResult(); } - -mlir::Value LoweringPrepareItaniumCXXABI::lowerVAArg( - CIRBaseBuilderTy &builder, mlir::cir::VAArgOp op, - const ::cir::CIRDataLayout &datalayout) { - // There is no generic cir lowering for var_arg, here we fail - // so to prevent attempt of calling lowerVAArg for ItaniumCXXABI - llvm_unreachable("NYI"); -} diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index b38c4608f875..d98fda81fd69 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1603,7 +1603,12 @@ class CIRVAArgLowering : public mlir::OpConversionPattern { mlir::LogicalResult matchAndRewrite(mlir::cir::VAArgOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - return op.emitError("cir.vaarg lowering is NYI"); + auto vaArgResTy = getTypeConverter()->convertType(op.getType()); + auto opaquePtr = mlir::LLVM::LLVMPointerType::get(getContext()); + auto va_list = rewriter.create( + op.getLoc(), opaquePtr, adaptor.getOperands().front()); + rewriter.replaceOpWithNewOp(op, vaArgResTy, va_list); + return mlir::success(); } }; diff --git a/clang/test/CIR/CodeGen/var-arg.c b/clang/test/CIR/CodeGen/var-arg.c index e689adefebe5..fc9a7fe99139 100644 --- a/clang/test/CIR/CodeGen/var-arg.c +++ b/clang/test/CIR/CodeGen/var-arg.c @@ -2,6 +2,8 @@ // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare %s -o %t.cir 2>&1 | FileCheck %s -check-prefix=AFTER // RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM-X86 #include int f1(int n, ...) { @@ -118,3 +120,9 @@ int f1(int n, ...) { // LLVM: store i32 [[RES]], ptr [[RETP]], align 4, // LLVM: [[RETV:%.*]] = load i32, ptr [[RETP]], align 4, // LLVM-NEXT: ret i32 [[RETV]], + +// LLVM-X86: %struct.__va_list_tag = type { i32, i32, ptr, ptr } +// LLVM-X86: define {{.*}} @f1 +// LLVM-X86: call void @llvm.va_start.p0( +// LLVM-X86: va_arg ptr %{{.*}}, i32 +// LLVM-X86: call void @llvm.va_end.p0( diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index fb3b8e77c492..860c1948e376 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -597,6 +597,26 @@ def LLVM_LandingpadOp : LLVM_Op<"landingpad"> { let hasVerifier = 1; } +//===----------------------------------------------------------------------===// +// VAArgOp +//===----------------------------------------------------------------------===// + +def LLVM_VaArgOp : LLVM_Op<"va_arg"> { + let arguments = (ins LLVM_AnyPointer:$arg); + let results = (outs LLVM_Type:$res); + + let builders = [LLVM_OneResultOpBuilder]; + + let llvmBuilder = " $res = builder.CreateVAArg($arg, $_resultType); "; + let assemblyFormat = "$arg attr-dict `:` `(` type($arg) `)` `->` type($res)"; + + string llvmInstName = "VAArg"; + string mlirBuilder = [{ + $res = $_builder.create( + $_location, $_resultType, $arg); + }]; +} + //===----------------------------------------------------------------------===// // CallOp //===----------------------------------------------------------------------===// diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir index 7116f3b64d7f..89db1b6ffe75 100644 --- a/mlir/test/Target/LLVMIR/llvmir.mlir +++ b/mlir/test/Target/LLVMIR/llvmir.mlir @@ -2244,8 +2244,8 @@ llvm.func @qux(f32) // CHECK: %struct.va_list = type { ptr } -// CHECK: define void @vararg_function(i32 %{{.*}}, ...) -llvm.func @vararg_function(%arg0: i32, ...) { +// CHECK: define i32 @vararg_function(i32 %{{.*}}, ...) +llvm.func @vararg_function(%arg0: i32, ...) -> i32 { %0 = llvm.mlir.constant(1 : i32) : i32 %1 = llvm.mlir.constant(1 : i32) : i32 // CHECK: %[[ALLOCA0:.+]] = alloca %struct.va_list, align 8 @@ -2256,12 +2256,14 @@ llvm.func @vararg_function(%arg0: i32, ...) { %4 = llvm.alloca %0 x !llvm.ptr {alignment = 8 : i64} : (i32) -> !llvm.ptr // CHECK: call void @llvm.va_copy.p0(ptr %[[ALLOCA1]], ptr %[[ALLOCA0]]) llvm.intr.vacopy %2 to %4 : !llvm.ptr, !llvm.ptr + // CHECK: %[[RET:.+]] = va_arg ptr %[[ALLOCA1]], i32 + %ret = llvm.va_arg %4 : (!llvm.ptr) -> i32 // CHECK: call void @llvm.va_end.p0(ptr %[[ALLOCA1]]) // CHECK: call void @llvm.va_end.p0(ptr %[[ALLOCA0]]) llvm.intr.vaend %4 : !llvm.ptr llvm.intr.vaend %2 : !llvm.ptr - // CHECK: ret void - llvm.return + // CHECK: ret i32 %[[RET]] + llvm.return %ret : i32 } // -----