Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -3653,11 +3653,13 @@ Assert( !F->isIntrinsic() || isa(I) || F->getIntrinsicID() == Intrinsic::donothing || + F->getIntrinsicID() == Intrinsic::coro_resume || + F->getIntrinsicID() == Intrinsic::coro_destroy || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 || F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, - "Cannot invoke an intrinsic other than donothing, patchpoint or " - "statepoint", + "Cannot invoke an intrinsic other than donothing, patchpoint, " + "statepoint, coro_resume or coro_destroy", &I); Assert(F->getParent() == M, "Referencing function in another module!", &I, M, F, F->getParent()); Index: lib/Transforms/Coroutines/CoroEarly.cpp =================================================================== --- lib/Transforms/Coroutines/CoroEarly.cpp +++ lib/Transforms/Coroutines/CoroEarly.cpp @@ -61,7 +61,30 @@ break; } Changed = true; + continue; } + + // The coro.resume and coro.destroy may be called via Invoke Instruction, + // and won't be lowered by the code above. + + auto Inv = dyn_cast(&I); + if (!Inv) + continue; + auto CalledFn = Inv->getCalledFunction(); + if (!CalledFn) + continue; + StringRef Name = CalledFn->getName(); + if (!Name.startswith("llvm.coro")) + continue; + if (Name == CORO_RESUME_STR) { + lowerResumeOrDestroy(Inv, CoroSubFnInst::ResumeIndex); + } else { + assert(Name == CORO_DESTROY_STR && "Cannot invoke coroutine intrinsic " + "other than coro.resume and " + "coro.destroy"); + lowerResumeOrDestroy(Inv, CoroSubFnInst::DestroyIndex); + } + Changed = true; } return Changed; } Index: test/Transforms/Coroutines/coro-early.ll =================================================================== --- test/Transforms/Coroutines/coro-early.ll +++ test/Transforms/Coroutines/coro-early.ll @@ -20,5 +20,22 @@ ; CHECK-NEXT: ret void } +; CHECK-LABEL: @eh +define void @eh(i8* %hdl) personality i8* null { +; CHECK-NEXT: entry +entry: +; CHECK-NEXT: %0 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0) +; CHECK-NEXT: %1 = bitcast i8* %0 to void (i8*)* +; CHECK-NEXT: invoke fastcc void %1(i8* %hdl) + invoke void @llvm.coro.resume(i8* %hdl) + to label %cont unwind label %ehcleanup +cont: + ret void + +ehcleanup: + %0 = cleanuppad within none [] + cleanupret from %0 unwind to caller +} + declare void @llvm.coro.resume(i8*) declare void @llvm.coro.destroy(i8*)