diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.h @@ -137,7 +137,10 @@ return getStructTy(&elt1.getDialect(), fields); } static LLVMType getVectorTy(LLVMType elementType, unsigned numElements); + + /// Void type utilities. static LLVMType getVoidTy(LLVMDialect *dialect); + bool isVoidTy(); // Creation and setting of LLVM's identified struct types static LLVMType createStructTy(LLVMDialect *dialect, 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 @@ -344,7 +344,7 @@ } def LLVM_LandingpadOp : LLVM_OneResultOp<"landingpad">, - Arguments<(ins UnitAttr:$cleanup, + Arguments<(ins UnitAttr:$cleanup, Variadic)> { let verifier = [{ return ::verify(*this); }]; let parser = [{ return parseLandingpadOp(parser, result); }]; @@ -354,9 +354,18 @@ def LLVM_CallOp : LLVM_Op<"call">, Arguments<(ins OptionalAttr:$callee, Variadic)>, - Results<(outs Variadic)>, - LLVM_TwoBuilders { + Results<(outs Variadic)> { + let builders = [OpBuilder< + "Builder *builder, OperationState &result, LLVMFuncOp func," + "ValueRange operands, ArrayRef attributes = {}", + [{ + LLVMType resultType = func.getType().getFunctionResultType(); + if (!resultType.isVoidTy()) + result.addTypes(resultType); + result.addAttribute("callee", builder->getSymbolRefAttr(func)); + result.addAttributes(attributes); + result.addOperands(operands); + }]>]; let verifier = [{ if (getNumResults() > 1) return emitOpError("must have 0 or 1 result"); 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 @@ -1313,7 +1313,7 @@ argTypes.push_back(fnType.getFunctionParamType(i)); LLVMType returnType = fnType.getFunctionResultType(); - if (!returnType.getUnderlyingType()->isVoidTy()) + if (!returnType.isVoidTy()) resTypes.push_back(returnType); impl::printFunctionSignature(p, op, argTypes, op.isVarArg(), resTypes); @@ -1348,14 +1348,12 @@ // Hook for OpTrait::FunctionLike, returns the number of function results. // Depends on the type attribute being correct as checked by verifyType unsigned LLVMFuncOp::getNumFuncResults() { - llvm::FunctionType *funcType = - cast(getType().getUnderlyingType()); // We model LLVM functions that return void as having zero results, // and all others as having one result. // If we modeled a void return as one result, then it would be possible to // attach an MLIR result attribute to it, and it isn't clear what semantics we // would assign to that. - if (funcType->getReturnType()->isVoidTy()) + if (getType().getFunctionResultType().isVoidTy()) return 0; return 1; } @@ -1900,10 +1898,15 @@ return llvm::VectorType::get(elementType.getUnderlyingType(), numElements); }); } + LLVMType LLVMType::getVoidTy(LLVMDialect *dialect) { return dialect->impl->voidTy; } +bool LLVMType::isVoidTy() { + return getUnderlyingType()->isVoidTy(); +} + //===----------------------------------------------------------------------===// // Utility functions. //===----------------------------------------------------------------------===//