diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -1514,14 +1514,18 @@ ArrayRef getArgumentTypes() { return getFunctionType().getParams(); } /// Returns the result types of this function. - ArrayRef getResultTypes() { return getFunctionType().getReturnTypes(); } + ArrayRef getResultTypes() { + if (getFunctionType().getReturnType().isa()) + return {}; + return getFunctionType().getReturnTypes(); + } /// Returns the callable region, which is the function body. If the function /// is external, returns null. Region *getCallableRegion(); /// Returns the callable result type, which is the function return type. - ArrayRef getCallableResults() { return getFunctionType().getReturnTypes(); } + ArrayRef getCallableResults() { return getResultTypes(); } }]; diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -2044,7 +2044,16 @@ llvmInputs.push_back(t); } - // No output is denoted as "void" in LLVM type system. + // The void return type is an internal implementation detail that should not + // be expressed explicitly on the IR. This is symmetric to the printer, which + // does not print the implicit void return type. + if (!outputs.empty() && outputs.front().isa()) { + parser.emitError(loc, "failed to construct function type: void return type " + "should not be passed explicitly"); + return {}; + } + + // Set implicit void type to represent no return value. Type llvmOutput = outputs.empty() ? LLVMVoidType::get(b.getContext()) : outputs.front(); if (!isCompatibleType(llvmOutput)) { diff --git a/mlir/test/Dialect/LLVMIR/func.mlir b/mlir/test/Dialect/LLVMIR/func.mlir --- a/mlir/test/Dialect/LLVMIR/func.mlir +++ b/mlir/test/Dialect/LLVMIR/func.mlir @@ -256,8 +256,8 @@ // ----- module { - // expected-error@+1 {{cannot attach result attributes to functions with a void return}} - llvm.func @variadic_def() -> (!llvm.void {llvm.noundef}) + // expected-error@+1 {{void return type should not be passed explicitly}} + llvm.func @variadic_def() -> (!llvm.void) } // ----- diff --git a/mlir/test/Target/LLVMIR/llvmir-types.mlir b/mlir/test/Target/LLVMIR/llvmir-types.mlir --- a/mlir/test/Target/LLVMIR/llvmir-types.mlir +++ b/mlir/test/Target/LLVMIR/llvmir-types.mlir @@ -5,7 +5,7 @@ // // CHECK: declare void @return_void() -llvm.func @return_void() -> !llvm.void +llvm.func @return_void() // CHECK: declare half @return_half() llvm.func @return_half() -> f16 // CHECK: declare bfloat @return_bfloat() @@ -28,7 +28,7 @@ // // CHECK: declare void @f_void_i32(i32) -llvm.func @f_void_i32(i32) -> !llvm.void +llvm.func @f_void_i32(i32) // CHECK: declare i32 @f_i32_empty() llvm.func @f_i32_empty() -> i32 // CHECK: declare i32 @f_i32_half_bfloat_float_double(half, bfloat, float, double)