Index: mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td =================================================================== --- mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td +++ mlir/include/mlir/Dialect/LLVMIR/LLVMIntrinsicOps.td @@ -186,6 +186,25 @@ let assemblyFormat = "$handle attr-dict"; } +// +// Variadic function intrinsics. +// + +def LLVM_VaStartOp : LLVM_ZeroResultIntrOp<"vastart">, + Arguments<(ins LLVM_i8Ptr:$arg_list)> { + let assemblyFormat = "$arg_list attr-dict"; +} + +def LLVM_VaCopyOp : LLVM_ZeroResultIntrOp<"vacopy">, + Arguments<(ins LLVM_i8Ptr:$dest_list, LLVM_i8Ptr:$src_list)> { + let assemblyFormat = "$src_list `to` $dest_list attr-dict"; +} + +def LLVM_VaEndOp : LLVM_ZeroResultIntrOp<"vaend">, + Arguments<(ins LLVM_i8Ptr:$arg_list)> { + let assemblyFormat = "$arg_list attr-dict"; +} + // // Exception handling intrinsics. // @@ -548,4 +567,4 @@ def LLVM_VPPtrToIntOp : LLVM_VPCastPtr<"ptrtoint">; def LLVM_VPIntToPtrOp : LLVM_VPCastI<"inttoptr">; -#endif // LLVM_INTRINSIC_OPS \ No newline at end of file +#endif // LLVM_INTRINSIC_OPS Index: mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp =================================================================== --- mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -2311,9 +2311,6 @@ return success(); } - if (isVarArg()) - return emitOpError("only external functions can be variadic"); - return success(); } Index: mlir/test/Dialect/LLVMIR/func.mlir =================================================================== --- mlir/test/Dialect/LLVMIR/func.mlir +++ mlir/test/Dialect/LLVMIR/func.mlir @@ -159,6 +159,11 @@ llvm.func weak fastcc @cconv3() { llvm.return } + + // CHECK-LABEL: llvm.func @variadic_def + llvm.func @variadic_def(...) { + llvm.return + } } // ----- @@ -232,15 +237,6 @@ // ----- -module { - // expected-error@+1 {{only external functions can be variadic}} - llvm.func @variadic_def(...) { - llvm.return - } -} - -// ----- - module { // expected-error@+1 {{cannot attach result attributes to functions with a void return}} llvm.func @variadic_def() -> (!llvm.void {llvm.noalias}) Index: mlir/test/Target/LLVMIR/Import/intrinsic.ll =================================================================== --- mlir/test/Target/LLVMIR/Import/intrinsic.ll +++ mlir/test/Target/LLVMIR/Import/intrinsic.ll @@ -385,6 +385,17 @@ ret void } +; CHECK-LABEL: llvm.func @va_intrinsics_test +define void @va_intrinsics_test(i8* %0, i8* %1) { +; CHECK: llvm.intr.vastart %{{.*}} + call void @llvm.va_start(i8* %0) +; CHECK: llvm.intr.vacopy %{{.*}} to %{{.*}} + call void @llvm.va_copy(i8* %1, i8* %0) +; CHECK: llvm.intr.vaend %{{.*}} + call void @llvm.va_end(i8* %0) + ret void +} + ; CHECK-LABEL: llvm.func @coro_id define void @coro_id(i32 %0, i8* %1) { ; CHECK: llvm.intr.coro.id %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}} : !llvm.token @@ -686,6 +697,9 @@ declare i32 @llvm.eh.typeid.for(i8*) declare i8* @llvm.stacksave() declare void @llvm.stackrestore(i8*) +declare void @llvm.va_start(i8*) +declare void @llvm.va_copy(i8*, i8*) +declare void @llvm.va_end(i8*) declare <8 x i32> @llvm.vp.add.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.sub.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32) declare <8 x i32> @llvm.vp.mul.v8i32(<8 x i32>, <8 x i32>, <8 x i1>, i32)