diff --git a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp --- a/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroCleanup.cpp @@ -70,6 +70,10 @@ case Intrinsic::coro_alloc: II->replaceAllUsesWith(ConstantInt::getTrue(Context)); break; + case Intrinsic::coro_async_resume: + II->replaceAllUsesWith( + ConstantPointerNull::get(cast(I.getType()))); + break; case Intrinsic::coro_id: case Intrinsic::coro_id_retcon: case Intrinsic::coro_id_retcon_once: @@ -114,7 +118,8 @@ return coro::declaresIntrinsics( M, {"llvm.coro.alloc", "llvm.coro.begin", "llvm.coro.subfn.addr", "llvm.coro.free", "llvm.coro.id", "llvm.coro.id.retcon", - "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace"}); + "llvm.coro.id.retcon.once", "llvm.coro.async.size.replace", + "llvm.coro.async.resume"}); } PreservedAnalyses CoroCleanupPass::run(Function &F, diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp --- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp +++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp @@ -126,6 +126,7 @@ "llvm.coro.alloc", "llvm.coro.async.context.alloc", "llvm.coro.async.context.dealloc", + "llvm.coro.async.resume", "llvm.coro.async.size.replace", "llvm.coro.async.store_resume", "llvm.coro.begin", diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll --- a/llvm/test/Transforms/Coroutines/coro-async.ll +++ b/llvm/test/Transforms/Coroutines/coro-async.ll @@ -540,6 +540,34 @@ ; CHECK: store i64* null, i64** [[ALLOCA]] ; CHECK: call void @do_with_swifterror(i64** {{.*}}swifterror{{.*}} [[ALLOCA]]) +@undefined_coro_async_resume_fp = constant <{ i32, i32 }> + <{ i32 trunc ( + i64 sub ( + i64 ptrtoint (void (i8*)* @undefined_coro_async_resume to i64), + i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @undefined_coro_async_resume_fp, i32 0, i32 1) to i64) + ) + to i32), + i32 24 +}> + +declare void @crash() +declare void @use(i8*) + +define swiftcc void @undefined_coro_async_resume(i8 *%async.ctx) { +entry: + %id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, i8* bitcast (<{i32, i32}>* @undefined_coro_async_resume_fp to i8*)) + %hdl = call i8* @llvm.coro.begin(token %id, i8* null) + %undefined_resume_pointer = call i8* @llvm.coro.async.resume() + call void @use(i8* %undefined_resume_pointer) + call void @crash() + %unused = call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 false) + unreachable +} +; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume +; CHECK-NOT: @llvm.coro.async.resume +; CHECK: call void @use(i8* null) +; CHECK: unreachable + declare { i8*, i8*, i8*, i8* } @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32, i8*, i8*, ...) declare i8* @llvm.coro.prepare.async(i8*) declare token @llvm.coro.id.async(i32, i32, i32, i8*)