diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp --- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp +++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp @@ -223,7 +223,7 @@ auto *block = resumeOp.addEntryBlock(); OpBuilder blockBuilder = OpBuilder::atBlockEnd(block); - blockBuilder.create(loc, Type(), + blockBuilder.create(loc, TypeRange(), blockBuilder.getSymbolRefAttr(kCoroResume), resumeOp.getArgument(0)); @@ -343,7 +343,8 @@ ValueRange({coroId.getResult(0), coroHdl.getResult(0)})); // Free the memory. - builder.create(loc, Type(), builder.getSymbolRefAttr(kFree), + builder.create(loc, TypeRange(), + builder.getSymbolRefAttr(kFree), ValueRange(coroMem.getResult(0))); // Branch into the suspend block. builder.create(loc, suspendBlock); @@ -503,7 +504,7 @@ // Call async runtime API to execute a coroutine in the managed thread. SmallVector executeArgs = {coro.coroHandle, resumePtr.res()}; - builder.create(loc, Type(), kExecute, executeArgs); + builder.create(loc, TypeRange(), kExecute, executeArgs); // Split the entry block before the terminator. Block *resume = addSuspensionPoint(coro, coroSave.getResult(0), @@ -524,7 +525,7 @@ // to async runtime to emplace the result token. for (Operation &op : execute.body().getOps()) { if (isa(op)) { - builder.create(loc, kEmplaceToken, Type(), coro.asyncToken); + builder.create(loc, kEmplaceToken, TypeRange(), coro.asyncToken); continue; } builder.clone(op, valueMapping); @@ -671,7 +672,7 @@ // Inside regular function we convert await operation to the blocking // async API await function call. if (!isInCoroutine) - rewriter.create(loc, Type(), blockingAwaitFuncName, + rewriter.create(loc, TypeRange(), blockingAwaitFuncName, ValueRange(op->getOperand(0))); // Inside the coroutine we convert await operation into coroutine suspension @@ -696,7 +697,7 @@ // the async await argument becomes ready. SmallVector awaitAndExecuteArgs = { await.getOperand(), coro.coroHandle, resumePtr.res()}; - builder.create(loc, Type(), coroAwaitFuncName, + builder.create(loc, TypeRange(), coroAwaitFuncName, awaitAndExecuteArgs); // Split the entry block before the await operation. diff --git a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp --- a/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp +++ b/mlir/lib/Conversion/StandardToLLVM/StandardToLLVM.cpp @@ -2290,7 +2290,7 @@ auto callOp = cast(op); // Pack the result types into a struct. - Type packedResult; + Type packedResult = nullptr; unsigned numResults = callOp.getNumResults(); auto resultTypes = llvm::to_vector<4>(callOp.getResultTypes()); @@ -2302,8 +2302,9 @@ auto promoted = this->typeConverter.promoteOperands( op->getLoc(), /*opOperands=*/op->getOperands(), operands, rewriter); - auto newOp = rewriter.create(op->getLoc(), packedResult, - promoted, op->getAttrs()); + auto newOp = rewriter.create( + op->getLoc(), packedResult ? TypeRange(packedResult) : TypeRange(), + promoted, op->getAttrs()); SmallVector results; if (numResults < 2) { diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -167,6 +167,8 @@ : location(location), numSuccs(numSuccessors), numRegions(numRegions), hasOperandStorage(hasOperandStorage), hasSingleResult(false), name(name), attrs(attributes) { + assert(llvm::all_of(resultTypes, [](Type t) { return t; }) && + "unexpected null result type"); if (!resultTypes.empty()) { // If there is a single result it is stored in-place, otherwise use a tuple. hasSingleResult = resultTypes.size() == 1; diff --git a/mlir/lib/IR/TypeRange.cpp b/mlir/lib/IR/TypeRange.cpp --- a/mlir/lib/IR/TypeRange.cpp +++ b/mlir/lib/IR/TypeRange.cpp @@ -14,7 +14,10 @@ // TypeRange TypeRange::TypeRange(ArrayRef types) - : TypeRange(types.data(), types.size()) {} + : TypeRange(types.data(), types.size()) { + assert(llvm::all_of(types, [](Type t) { return t; }) && + "attempting to construct a TypeRange with null types"); +} TypeRange::TypeRange(OperandRange values) : TypeRange(values.begin().getBase(), values.size()) {} TypeRange::TypeRange(ResultRange values) diff --git a/mlir/test/Conversion/StandardToLLVM/standard-to-llvm.mlir b/mlir/test/Conversion/StandardToLLVM/standard-to-llvm.mlir --- a/mlir/test/Conversion/StandardToLLVM/standard-to-llvm.mlir +++ b/mlir/test/Conversion/StandardToLLVM/standard-to-llvm.mlir @@ -203,3 +203,13 @@ return } +// This should not trigger an assertion by creating an LLVM::CallOp with a +// nullptr result type. + +// CHECK-LABEL: @call_zero_result_func +func @call_zero_result_func() { + // CHECK: call @zero_result_func + call @zero_result_func() : () -> () + return +} +func private @zero_result_func()