From 9f22401a59f8eee46e7134d38a11c6d6161c7b5a Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 5 Apr 2023 16:59:04 +0200 Subject: [PATCH] [Coroutines] Convert test to opaque pointers (NFC) --- llvm/test/Transforms/Coroutines/coro-async.ll | 604 ++++++++++++-------------- 1 file changed, 266 insertions(+), 338 deletions(-) diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll index f356efa..4a49217e 100644 --- a/llvm/test/Transforms/Coroutines/coro-async.ll +++ b/llvm/test/Transforms/Coroutines/coro-async.ll @@ -1,16 +1,16 @@ -; RUN: opt -opaque-pointers=0 < %s -passes='default' -S | FileCheck --check-prefixes=CHECK %s -; RUN: opt -opaque-pointers=0 < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s +; RUN: opt < %s -passes='default' -S | FileCheck --check-prefixes=CHECK %s +; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s target datalayout = "p:64:64:64" %async.task = type { i64 } %async.actor = type { i64 } %async.fp = type <{ i32, i32 }> -%async.ctxt = type { i8*, void (i8*, %async.task*, %async.actor*)* } +%async.ctxt = type { ptr, ptr } ; The async callee. @my_other_async_function_fp = external global <{ i32, i32 }> -declare void @my_other_async_function(i8* %async.ctxt) +declare void @my_other_async_function(ptr %async.ctxt) ; The current async function (the caller). ; This struct describes an async function. The first field is the @@ -20,8 +20,8 @@ declare void @my_other_async_function(i8* %async.ctxt) @my_async_function_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (i8*, %async.task*, %async.actor*)* @my_async_function to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @my_async_function_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @my_async_function to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64) ) to i32), i32 128 ; Initial async context size without space for frame @@ -29,96 +29,85 @@ declare void @my_other_async_function(i8* %async.ctxt) @my_async_function_pa_fp = constant <{ i32, i32 }> <{ i32 trunc ( i64 sub ( - i64 ptrtoint (void (i8*, %async.task*, %async.actor*)* @my_async_function_pa to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @my_async_function_pa_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @my_async_function_pa to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64) ) to i32), i32 8 }> ; Function that implements the dispatch to the callee function. -define swiftcc void @my_async_function.my_other_async_function_fp.apply(i8* %fnPtr, i8* %async.ctxt, %async.task* %task, %async.actor* %actor) { - %callee = bitcast i8* %fnPtr to void(i8*, %async.task*, %async.actor*)* - tail call swiftcc void %callee(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) +define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) { + tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) ret void } declare void @some_user(i64) -declare void @some_may_write(i64*) +declare void @some_may_write(ptr) -define i8* @__swift_async_resume_project_context(i8* %ctxt) { +define ptr @__swift_async_resume_project_context(ptr %ctxt) { entry: - %resume_ctxt_addr = bitcast i8* %ctxt to i8** - %resume_ctxt = load i8*, i8** %resume_ctxt_addr, align 8 - ret i8* %resume_ctxt + %resume_ctxt = load ptr, ptr %ctxt, align 8 + ret ptr %resume_ctxt } -define i8* @resume_context_projection(i8* %ctxt) { +define ptr @resume_context_projection(ptr %ctxt) { entry: - %resume_ctxt_addr = bitcast i8* %ctxt to i8** - %resume_ctxt = load i8*, i8** %resume_ctxt_addr, align 8 - ret i8* %resume_ctxt + %resume_ctxt = load ptr, ptr %ctxt, align 8 + ret ptr %resume_ctxt } -define swiftcc void @my_async_function(i8* swiftasync %async.ctxt, %async.task* %task, %async.actor* %actor) presplitcoroutine !dbg !1 { +define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 { entry: %tmp = alloca { i64, i64 }, align 8 %vector = alloca <4 x double>, align 16 - %proj.1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %tmp, i64 0, i32 0 - %proj.2 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %tmp, i64 0, i32 1 + %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0 + %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, - i8* bitcast (<{i32, i32}>* @my_async_function_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) - store i64 0, i64* %proj.1, align 8 - store i64 1, i64* %proj.2, align 8 - call void @some_may_write(i64* %proj.1) + ptr @my_async_function_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + store i64 0, ptr %proj.1, align 8 + store i64 1, ptr %proj.2, align 8 + call void @some_may_write(ptr %proj.1) ; Begin lowering: apply %my_other_async_function(%args...) ; setup callee context - %arg0 = bitcast %async.task* %task to i8* - %arg1 = bitcast <{ i32, i32}>* @my_other_async_function_fp to i8* - %callee_context = call i8* @llvm.coro.async.context.alloc(i8* %arg0, i8* %arg1) - %callee_context.0 = bitcast i8* %callee_context to %async.ctxt* + %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp) ; store arguments ... ; ... (omitted) ; store the return continuation - %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 1 - %return_to_caller.addr = bitcast void(i8*, %async.task*, %async.actor*)** %callee_context.return_to_caller.addr to i8** - %resume.func_ptr = call i8* @llvm.coro.async.resume() - store i8* %resume.func_ptr, i8** %return_to_caller.addr + %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1 + %resume.func_ptr = call ptr @llvm.coro.async.resume() + store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr ; store caller context into callee context - %callee_context.caller_context.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 0 - store i8* %async.ctxt, i8** %callee_context.caller_context.addr - %resume_proj_fun = bitcast i8*(i8*)* @__swift_async_resume_project_context to i8* - %callee = bitcast void(i8*, %async.task*, %async.actor*)* @asyncSuspend to i8* - %vector_spill = load <4 x double>, <4 x double>* %vector, align 16 - %res = call {i8*, i8*, i8*} (i32, i8*, i8*, ...) @llvm.coro.suspend.async(i32 0, - i8* %resume.func_ptr, - i8* %resume_proj_fun, - void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply, - i8* %callee, i8* %callee_context, %async.task* %task, %async.actor *%actor), !dbg !5 - - call void @llvm.coro.async.context.dealloc(i8* %callee_context) - %continuation_task_arg = extractvalue {i8*, i8*, i8*} %res, 1 - %task.2 = bitcast i8* %continuation_task_arg to %async.task* - %val = load i64, i64* %proj.1 + store ptr %async.ctxt, ptr %callee_context + %vector_spill = load <4 x double>, ptr %vector, align 16 + %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0, + ptr %resume.func_ptr, + ptr @__swift_async_resume_project_context, + ptr @my_async_function.my_other_async_function_fp.apply, + ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !5 + + call void @llvm.coro.async.context.dealloc(ptr %callee_context) + %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1 + %val = load i64, ptr %proj.1 call void @some_user(i64 %val) - %val.2 = load i64, i64* %proj.2 + %val.2 = load i64, ptr %proj.2 call void @some_user(i64 %val.2) - store <4 x double> %vector_spill, <4 x double>* %vector, align 16 - tail call swiftcc void @asyncReturn(i8* %async.ctxt, %async.task* %task.2, %async.actor* %actor) - call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0) + store <4 x double> %vector_spill, ptr %vector, align 16 + tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } -define void @my_async_function_pa(i8* %ctxt, %async.task* %task, %async.actor* %actor) { - call void @llvm.coro.async.size.replace(i8* bitcast (<{i32, i32}>* @my_async_function_pa_fp to i8*), i8* bitcast (<{i32, i32}>* @my_async_function_fp to i8*)) - call swiftcc void @my_async_function(i8* %ctxt, %async.task* %task, %async.actor* %actor) +define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) { + call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp) + call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor) ret void } @@ -127,289 +116,237 @@ define void @my_async_function_pa(i8* %ctxt, %async.task* %task, %async.actor* % ; CHECK: @my_async_function_pa_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 } ; CHECK: @my_async_function2_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 } -; CHECK-LABEL: define swiftcc void @my_async_function(i8* swiftasync %async.ctxt, %async.task* %task, %async.actor* %actor) -; CHECK-O0-LABEL: define swiftcc void @my_async_function(i8* swiftasync %async.ctxt, %async.task* %task, %async.actor* %actor) +; CHECK-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) +; CHECK-O0-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) ; CHECK-SAME: !dbg ![[SP1:[0-9]+]] { ; CHECK: coro.return: -; CHECK: [[FRAMEPTR:%.*]] = getelementptr inbounds i8, i8* %async.ctxt, i64 128 -; CHECK: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds i8, i8* %async.ctxt, i64 152 -; CHECK: [[CAST1:%.*]] = bitcast i8* [[ACTOR_SPILL_ADDR]] to %async.actor** -; CHECK: store %async.actor* %actor, %async.actor** [[CAST1]] -; CHECK: [[ADDR1:%.*]] = getelementptr inbounds i8, i8* %async.ctxt, i64 144 -; CHECK: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = bitcast i8* [[ADDR1]] to i8** -; CHECK: store i8* %async.ctxt, i8** [[ASYNC_CTXT_SPILL_ADDR]] -; CHECK: [[ALLOCA_PRJ1:%.*]] = bitcast i8* [[FRAMEPTR]] to i64* -; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds i8, i8* %async.ctxt, i64 136 -; CHECK: [[ADDR2:%.*]] = bitcast i8* [[ALLOCA_PRJ2]] to i64* -; CHECK: store i64 0, i64* [[ALLOCA_PRJ1]] -; CHECK: store i64 1, i64* [[ADDR2]] -; CHECK: tail call void @some_may_write(i64* nonnull %proj.1) -; CHECK: [[TASK:%.*]] = bitcast %async.task* %task to i8* -; CHECK: [[CALLEE_CTXT:%.*]] = tail call i8* @llvm.coro.async.context.alloc(i8* [[TASK]], i8* nonnull bitcast (<{ i32, i32 }>* @my_other_async_function_fp to i8*)) -; CHECK: [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds i8, i8* %async.ctxt, i64 160 -; CHECK: [[CAST2:%.*]] = bitcast i8* [[CALLEE_CTXT_SPILL]] to i8** -; CHECK: store i8* [[CALLEE_CTXT]], i8** [[CAST2]] -; CHECK: [[TYPED_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CALLEE_CTXT]], i64 8 -; CHECK: [[RETURN_TO_CALLER_ADDR:%.*]] = bitcast i8* [[TYPED_RETURN_TO_CALLER_ADDR]] to i8** -; CHECK: store i8* bitcast (void (i8*, i8*, i8*)* @my_async_functionTQ0_ to i8*), i8** [[RETURN_TO_CALLER_ADDR]] -; CHECK: [[CALLER_CONTEXT_ADDR:%.*]] = bitcast i8* [[CALLEE_CTXT]] to i8** -; CHECK: store i8* %async.ctxt, i8** [[CALLER_CONTEXT_ADDR]] +; CHECK: [[FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 128 +; CHECK: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 152 +; CHECK: store ptr %actor, ptr [[ACTOR_SPILL_ADDR]] +; CHECK: [[ADDR1:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 144 +; CHECK: store ptr %async.ctxt, ptr [[ADDR1]] +; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 136 +; CHECK: store i64 0, ptr [[FRAMEPTR]] +; CHECK: store i64 1, ptr [[ALLOCA_PRJ2]] +; CHECK: tail call void @some_may_write(ptr nonnull [[FRAMEPTR]]) +; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr %task, ptr nonnull @my_other_async_function_fp) +; CHECK: [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 160 +; CHECK: store ptr [[CALLEE_CTXT]], ptr [[CALLEE_CTXT_SPILL]] +; CHECK: [[TYPED_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds %async.ctxt, ptr [[CALLEE_CTXT]], i64 0, i32 1 +; CHECK: store ptr @my_async_functionTQ0_, ptr [[TYPED_RETURN_TO_CALLER_ADDR]] +; CHECK: store ptr %async.ctxt, ptr [[CALLEE_CTXT]] ; Make sure the spill is underaligned to the max context alignment (16). -; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, <4 x double>* {{.*}} -; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, %my_async_function.Frame* {{.*}}, i32 0, i32 1 -; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], <4 x double>* [[VECTOR_SPILL_ADDR]], align 16 -; CHECK: tail call swiftcc void @asyncSuspend(i8* [[CALLEE_CTXT]], %async.task* %task, %async.actor* %actor) +; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}} +; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1 +; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16 +; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor) ; CHECK: ret void ; CHECK: } -; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(i8* nocapture readonly swiftasync %0, i8* %1, i8* nocapture readnone %2) -; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(i8* swiftasync %0, i8* %1, i8* %2) +; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr nocapture readonly swiftasync %0, ptr %1, ptr nocapture readnone %2) +; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2) ; CHECK-SAME: !dbg ![[SP2:[0-9]+]] { ; CHECK: entryresume.0: -; CHECK: [[CALLER_CONTEXT_ADDR:%.*]] = bitcast i8* %0 to i8** -; CHECK: [[CALLER_CONTEXT:%.*]] = load i8*, i8** [[CALLER_CONTEXT_ADDR]] -; CHECK: [[FRAME_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALLER_CONTEXT]], i64 128 -; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, %my_async_function.Frame* {{.*}}, i32 0, i32 1 -; CHECK-O0: load <4 x double>, <4 x double>* [[VECTOR_SPILL_ADDR]], align 16 -; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CALLER_CONTEXT]], i64 160 -; CHECK: [[CAST1:%.*]] = bitcast i8* [[CALLEE_CTXT_SPILL_ADDR]] to i8** -; CHECK: [[CALLEE_CTXT_RELOAD:%.*]] = load i8*, i8** [[CAST1]] -; CHECK: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CALLER_CONTEXT]], i64 152 -; CHECK: [[CAST2:%.*]] = bitcast i8* [[ACTOR_RELOAD_ADDR]] to %async.actor** -; CHECK: [[ACTOR_RELOAD:%.*]] = load %async.actor*, %async.actor** [[CAST2]] -; CHECK: [[ADDR1:%.*]] = getelementptr inbounds i8, i8* [[CALLER_CONTEXT]], i64 144 -; CHECK: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = bitcast i8* [[ADDR1]] to i8** -; CHECK: [[ASYNC_CTXT_RELOAD:%.*]] = load i8*, i8** [[ASYNC_CTXT_RELOAD_ADDR]] -; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds i8, i8* [[CALLER_CONTEXT]], i64 136 -; CHECK: [[ADDR2:%.*]] = bitcast i8* [[ALLOCA_PRJ2]] to i64* -; CHECK: [[ALLOCA_PRJ1:%.*]] = bitcast i8* [[FRAME_PTR]] to i64* -; CHECK: tail call void @llvm.coro.async.context.dealloc(i8* [[CALLEE_CTXT_RELOAD]]) -; CHECK: [[TASK_ARG:%.*]] = bitcast i8* %1 to %async.task* -; CHECK: [[VAL1:%.*]] = load i64, i64* [[ALLOCA_PRJ1]] +; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0 +; CHECK: [[FRAME_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 128 +; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1 +; CHECK-O0: load <4 x double>, ptr [[VECTOR_SPILL_ADDR]], align 16 +; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 160 +; CHECK: [[CALLEE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]] +; CHECK: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 152 +; CHECK: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]] +; CHECK: [[ADDR1:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 144 +; CHECK: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ADDR1]] +; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds i8, ptr [[CALLER_CONTEXT]], i64 136 +; CHECK: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CTXT_RELOAD]]) +; CHECK: [[VAL1:%.*]] = load i64, ptr [[FRAME_PTR]] ; CHECK: tail call void @some_user(i64 [[VAL1]]) -; CHECK: [[VAL2:%.*]] = load i64, i64* [[ADDR2]] +; CHECK: [[VAL2:%.*]] = load i64, ptr [[ALLOCA_PRJ2]] ; CHECK: tail call void @some_user(i64 [[VAL2]]) -; CHECK: tail call swiftcc void @asyncReturn(i8* [[ASYNC_CTXT_RELOAD]], %async.task* [[TASK_ARG]], %async.actor* [[ACTOR_RELOAD]]) +; CHECK: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]]) ; CHECK: ret void ; CHECK: } @my_async_function2_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (%async.task*, %async.actor*, i8*)* @my_async_function2 to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @my_async_function2_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @my_async_function2 to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64) ) to i32), i32 128 ; Initial async context size without space for frame }> -define swiftcc void @my_async_function2(%async.task* %task, %async.actor* %actor, i8* %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 { +define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 { entry: - %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, i8* bitcast (<{i32, i32}>* @my_async_function2_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) + %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, ptr @my_async_function2_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) ; setup callee context - %arg0 = bitcast %async.task* %task to i8* - %arg1 = bitcast <{ i32, i32}>* @my_other_async_function_fp to i8* - %callee_context = call i8* @llvm.coro.async.context.alloc(i8* %arg0, i8* %arg1) - - %callee_context.0 = bitcast i8* %callee_context to %async.ctxt* - %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 1 - %return_to_caller.addr = bitcast void(i8*, %async.task*, %async.actor*)** %callee_context.return_to_caller.addr to i8** - %resume.func_ptr = call i8* @llvm.coro.async.resume() - store i8* %resume.func_ptr, i8** %return_to_caller.addr - %callee_context.caller_context.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 0 - store i8* %async.ctxt, i8** %callee_context.caller_context.addr - %resume_proj_fun = bitcast i8*(i8*)* @resume_context_projection to i8* - %callee = bitcast void(i8*, %async.task*, %async.actor*)* @asyncSuspend to i8* - %task.casted = bitcast i8* %arg0 to %async.task* - %res = call {i8*, i8*, i8*} (i32, i8*, i8*, ...) @llvm.coro.suspend.async(i32 2, - i8* %resume.func_ptr, - i8* %resume_proj_fun, - void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply, - i8* %callee, i8* %callee_context, %async.task* %task.casted, %async.actor *%actor), !dbg !9 - - %continuation_task_arg = extractvalue {i8*, i8*, i8*} %res, 0 - %task.2 = bitcast i8* %continuation_task_arg to %async.task* - - %callee_context.0.1 = bitcast i8* %callee_context to %async.ctxt* - %callee_context.return_to_caller.addr.1 = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0.1, i32 0, i32 1 - %return_to_caller.addr.1 = bitcast void(i8*, %async.task*, %async.actor*)** %callee_context.return_to_caller.addr.1 to i8** - %resume.func_ptr.1 = call i8* @llvm.coro.async.resume() - store i8* %resume.func_ptr.1, i8** %return_to_caller.addr.1 - %callee_context.caller_context.addr.1 = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0.1, i32 0, i32 0 - store i8* %async.ctxt, i8** %callee_context.caller_context.addr.1 - %resume_proj_fun.2 = bitcast i8*(i8*)* @resume_context_projection to i8* - %callee.2 = bitcast void(i8*, %async.task*, %async.actor*)* @asyncSuspend to i8* - %res.2 = call {i8*, i8*, i8*} (i32, i8*, i8*, ...) @llvm.coro.suspend.async(i32 0, - i8* %resume.func_ptr.1, - i8* %resume_proj_fun.2, - void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply, - i8* %callee.2, i8* %callee_context, %async.task* %task.casted, %async.actor *%actor) - - call void @llvm.coro.async.context.dealloc(i8* %callee_context) - %continuation_actor_arg = extractvalue {i8*, i8*, i8*} %res.2, 1 - %actor.2 = bitcast i8* %continuation_actor_arg to %async.actor* - - tail call swiftcc void @asyncReturn(i8* %async.ctxt, %async.task* %task.2, %async.actor* %actor.2) - call i1 @llvm.coro.end(i8* %hdl, i1 0) + %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp) + + %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1 + %resume.func_ptr = call ptr @llvm.coro.async.resume() + store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr + store ptr %async.ctxt, ptr %callee_context + %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 2, + ptr %resume.func_ptr, + ptr @resume_context_projection, + ptr @my_async_function.my_other_async_function_fp.apply, + ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9 + + %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 0 + + %callee_context.return_to_caller.addr.1 = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1 + %resume.func_ptr.1 = call ptr @llvm.coro.async.resume() + store ptr %resume.func_ptr.1, ptr %callee_context.return_to_caller.addr.1 + store ptr %async.ctxt, ptr %callee_context + %res.2 = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0, + ptr %resume.func_ptr.1, + ptr @resume_context_projection, + ptr @my_async_function.my_other_async_function_fp.apply, + ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor) + + call void @llvm.coro.async.context.dealloc(ptr %callee_context) + %continuation_actor_arg = extractvalue {ptr, ptr, ptr} %res.2, 1 + + tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %continuation_actor_arg) + call i1 @llvm.coro.end(ptr %hdl, i1 0) unreachable } -; CHECK-LABEL: define swiftcc void @my_async_function2(%async.task* %task, %async.actor* %actor, i8* %async.ctxt) +; CHECK-LABEL: define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) ; CHECK-SAME: #[[FRAMEPOINTER:[0-9]+]] ; CHECK-SAME: !dbg ![[SP3:[0-9]+]] -; CHECK: store i8* %async.ctxt, -; CHECK: store %async.actor* %actor, -; CHECK: store %async.task* %task, -; CHECK: [[CALLEE_CTXT:%.*]] = tail call i8* @llvm.coro.async.context.alloc( -; CHECK: store i8* [[CALLEE_CTXT]], -; CHECK: store i8* bitcast (void (i8*, i8*, i8*)* @my_async_function2.resume.0 to i8*), -; CHECK: store i8* %async.ctxt, -; CHECK: tail call swiftcc void @asyncSuspend(i8* [[CALLEE_CTXT]], %async.task* %task, %async.actor* %actor) +; CHECK: store ptr %async.ctxt, +; CHECK: store ptr %actor, +; CHECK: store ptr %task, +; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc( +; CHECK: store ptr [[CALLEE_CTXT]], +; CHECK: store ptr @my_async_function2.resume.0, +; CHECK: store ptr %async.ctxt, +; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor) ; CHECK: ret void -; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(i8* %0, i8* nocapture readnone %1, i8* nocapture readonly %2) +; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(ptr %0, ptr nocapture readnone %1, ptr nocapture readonly %2) ; CHECK-SAME: #[[FRAMEPOINTER]] ; CHECK-SAME: !dbg ![[SP4:[0-9]+]] -; CHECK: [[CALLEE_CTXT_ADDR:%.*]] = bitcast i8* %2 to i8** -; CHECK: [[CALLEE_CTXT:%.*]] = load i8*, i8** [[CALLEE_CTXT_ADDR]] -; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, i8* [[CALLEE_CTXT]], i64 152 -; CHECK: [[CALLEE_CTXT_SPILL_ADDR2:%.*]] = bitcast i8* [[CALLEE_CTXT_SPILL_ADDR]] to i8** -; CHECK: store i8* bitcast (void (i8*, i8*, i8*)* @my_async_function2.resume.1 to i8*), -; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load i8*, i8** [[CALLEE_CTXT_SPILL_ADDR2]] -; CHECK: tail call swiftcc void @asyncSuspend(i8* [[CALLEE_CTXT_RELOAD]] +; CHECK: [[CALLEE_CTXT:%.*]] = load ptr, ptr %2 +; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLEE_CTXT]], i64 152 +; CHECK: store ptr @my_async_function2.resume.1, +; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]] +; CHECK: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]] ; CHECK: ret void -; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(i8* nocapture readonly %0, i8* %1, i8* nocapture readnone %2) +; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(ptr nocapture readonly %0, ptr %1, ptr nocapture readnone %2) ; CHECK-SAME: #[[FRAMEPOINTER]] -; CHECK: bitcast i8* %0 to i8** -; CHECK: [[ACTOR_ARG:%.*]] = bitcast i8* %1 -; CHECK: tail call swiftcc void @asyncReturn({{.*}}[[ACTOR_ARG]]) +; CHECK: tail call swiftcc void @asyncReturn({{.*}}%1) ; CHECK: ret void -define swiftcc void @top_level_caller(i8* %ctxt, i8* %task, i8* %actor) { - %prepare = call i8* @llvm.coro.prepare.async(i8* bitcast (void (i8*, %async.task*, %async.actor*)* @my_async_function to i8*)) - %f = bitcast i8* %prepare to void (i8*, i8*, i8*)* - call swiftcc void %f(i8* %ctxt, i8* %task, i8* %actor) +define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) { + %prepare = call ptr @llvm.coro.prepare.async(ptr @my_async_function) + call swiftcc void %prepare(ptr %ctxt, ptr %task, ptr %actor) ret void } -; CHECK-LABEL: define swiftcc void @top_level_caller(i8* %ctxt, i8* %task, i8* %actor) -; CHECK: store i8* bitcast (void (i8*, i8*, i8*)* @my_async_functionTQ0_ -; CHECK: store i8* %ctxt +; CHECK-LABEL: define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) +; CHECK: store ptr @my_async_functionTQ0_ +; CHECK: store ptr %ctxt ; CHECK: tail call swiftcc void @asyncSuspend ; CHECK: ret void @dont_crash_on_cf_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (i8*, %async.task*, %async.actor*)* @my_async_function to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @my_async_function_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @my_async_function to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64) ) to i32), i32 128 ; Initial async context size without space for frame }> -define swiftcc void @dont_crash_on_cf_dispatch(i8* %fnPtr, i8* %async.ctxt, %async.task* %task, %async.actor* %actor) { - %isNull = icmp eq %async.task* %task, null +define swiftcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) { + %isNull = icmp eq ptr %task, null br i1 %isNull, label %is_null, label %is_not_null is_null: ret void is_not_null: - %callee = bitcast i8* %fnPtr to void(i8*, %async.task*, %async.actor*)* - tail call swiftcc void %callee(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) + tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) ret void } -define swiftcc void @dont_crash_on_cf(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) presplitcoroutine { +define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { entry: %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, - i8* bitcast (<{i32, i32}>* @dont_crash_on_cf_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) - %arg0 = bitcast %async.task* %task to i8* - %arg1 = bitcast <{ i32, i32}>* @my_other_async_function_fp to i8* - %callee_context = call i8* @llvm.coro.async.context.alloc(i8* %arg0, i8* %arg1) - %callee_context.0 = bitcast i8* %callee_context to %async.ctxt* - %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 1 - %return_to_caller.addr = bitcast void(i8*, %async.task*, %async.actor*)** %callee_context.return_to_caller.addr to i8** - %resume.func_ptr = call i8* @llvm.coro.async.resume() - store i8* %resume.func_ptr, i8** %return_to_caller.addr - %callee_context.caller_context.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 0 - store i8* %async.ctxt, i8** %callee_context.caller_context.addr - %resume_proj_fun = bitcast i8*(i8*)* @resume_context_projection to i8* - %callee = bitcast void(i8*, %async.task*, %async.actor*)* @asyncSuspend to i8* - %res = call {i8*, i8*, i8*} (i32, i8*, i8*, ...) @llvm.coro.suspend.async(i32 0, - i8* %resume.func_ptr, - i8* %resume_proj_fun, - void (i8*, i8*, %async.task*, %async.actor*)* @dont_crash_on_cf_dispatch, - i8* %callee, i8* %callee_context, %async.task* %task, %async.actor *%actor) - - call void @llvm.coro.async.context.dealloc(i8* %callee_context) - %continuation_task_arg = extractvalue {i8*, i8*, i8*} %res, 1 - %task.2 = bitcast i8* %continuation_task_arg to %async.task* - tail call swiftcc void @asyncReturn(i8* %async.ctxt, %async.task* %task.2, %async.actor* %actor) - call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0) + ptr @dont_crash_on_cf_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp) + %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1 + %resume.func_ptr = call ptr @llvm.coro.async.resume() + store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr + store ptr %async.ctxt, ptr %callee_context + %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0, + ptr %resume.func_ptr, + ptr @resume_context_projection, + ptr @dont_crash_on_cf_dispatch, + ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor) + + call void @llvm.coro.async.context.dealloc(ptr %callee_context) + %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1 + tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } @multiple_coro_end_async_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (i8*, %async.task*, %async.actor*)* @multiple_coro_end_async to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @multiple_coro_end_async_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @multiple_coro_end_async to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64) ) to i32), i32 128 ; Initial async context size without space for frame }> -define swiftcc void @must_tail_call_return(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) { - musttail call swiftcc void @asyncReturn(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) +define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) { + musttail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor) ret void } -define swiftcc void @multiple_coro_end_async(i8* %async.ctxt, %async.task* %task, %async.actor* %actor) presplitcoroutine { +define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { entry: %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, - i8* bitcast (<{i32, i32}>* @dont_crash_on_cf_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) - %arg0 = bitcast %async.task* %task to i8* - %arg1 = bitcast <{ i32, i32}>* @my_other_async_function_fp to i8* - %callee_context = call i8* @llvm.coro.async.context.alloc(i8* %arg0, i8* %arg1) - %callee_context.0 = bitcast i8* %callee_context to %async.ctxt* - %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 1 - %return_to_caller.addr = bitcast void(i8*, %async.task*, %async.actor*)** %callee_context.return_to_caller.addr to i8** - %resume.func_ptr = call i8* @llvm.coro.async.resume() - store i8* %resume.func_ptr, i8** %return_to_caller.addr - %callee_context.caller_context.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 0 - store i8* %async.ctxt, i8** %callee_context.caller_context.addr - %resume_proj_fun = bitcast i8*(i8*)* @resume_context_projection to i8* - %callee = bitcast void(i8*, %async.task*, %async.actor*)* @asyncSuspend to i8* - %res = call {i8*, i8*, i8*} (i32, i8*, i8*, ...) @llvm.coro.suspend.async(i32 0, - i8* %resume.func_ptr, - i8* %resume_proj_fun, - void (i8*, i8*, %async.task*, %async.actor*)* @dont_crash_on_cf_dispatch, - i8* %callee, i8* %callee_context, %async.task* %task, %async.actor *%actor) - - call void @llvm.coro.async.context.dealloc(i8* %callee_context) - %continuation_task_arg = extractvalue {i8*, i8*, i8*} %res, 1 - %task.2 = bitcast i8* %continuation_task_arg to %async.task* - %eq = icmp eq i8 * %continuation_task_arg, null + ptr @dont_crash_on_cf_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp) + %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1 + %resume.func_ptr = call ptr @llvm.coro.async.resume() + store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr + store ptr %async.ctxt, ptr %callee_context + %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0, + ptr %resume.func_ptr, + ptr @resume_context_projection, + ptr @dont_crash_on_cf_dispatch, + ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor) + + call void @llvm.coro.async.context.dealloc(ptr %callee_context) + %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1 + %eq = icmp eq ptr %continuation_task_arg, null br i1 %eq, label %is_equal, label %is_not_equal is_equal: - tail call swiftcc void @asyncReturn(i8* %async.ctxt, %async.task* %task.2, %async.actor* %actor) - call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0) + tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable is_not_equal: - call i1 (i8*, i1, ...) @llvm.coro.end.async( - i8* %hdl, i1 0, - void (i8*, %async.task*, %async.actor*)* @must_tail_call_return, - i8* %async.ctxt, %async.task* %task.2, %async.actor* null) + call i1 (ptr, i1, ...) @llvm.coro.end.async( + ptr %hdl, i1 0, + ptr @must_tail_call_return, + ptr %async.ctxt, ptr %continuation_task_arg, ptr null) unreachable } @@ -420,168 +357,159 @@ is_not_equal: @polymorphic_suspend_return_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (i8*, %async.task*, %async.actor*)* @polymorphic_suspend_return to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @polymorphic_suspend_return_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @polymorphic_suspend_return to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64) ) to i32), i32 64 ; Initial async context size without space for frame }> -define swiftcc void @polymorphic_suspend_return(i8* swiftasync %async.ctxt, %async.task* %task, %async.actor* %actor) presplitcoroutine { +define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { entry: %tmp = alloca { i64, i64 }, align 8 - %proj.1 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %tmp, i64 0, i32 0 - %proj.2 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %tmp, i64 0, i32 1 + %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0 + %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, - i8* bitcast (<{i32, i32}>* @polymorphic_suspend_return_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) - store i64 0, i64* %proj.1, align 8 - store i64 1, i64* %proj.2, align 8 - call void @some_may_write(i64* %proj.1) + ptr @polymorphic_suspend_return_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + store i64 0, ptr %proj.1, align 8 + store i64 1, ptr %proj.2, align 8 + call void @some_may_write(ptr %proj.1) ; Begin lowering: apply %my_other_async_function(%args...) ; setup callee context - %arg0 = bitcast %async.task* %task to i8* - %arg1 = bitcast <{ i32, i32}>* @my_other_async_function_fp to i8* - %callee_context = call i8* @llvm.coro.async.context.alloc(i8* %arg0, i8* %arg1) - %callee_context.0 = bitcast i8* %callee_context to %async.ctxt* + %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp) ; store arguments ... ; ... (omitted) ; store the return continuation - %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 1 - %return_to_caller.addr = bitcast void(i8*, %async.task*, %async.actor*)** %callee_context.return_to_caller.addr to i8** - %resume.func_ptr = call i8* @llvm.coro.async.resume() - store i8* %resume.func_ptr, i8** %return_to_caller.addr + %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1 + %resume.func_ptr = call ptr @llvm.coro.async.resume() + store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr ; store caller context into callee context - %callee_context.caller_context.addr = getelementptr inbounds %async.ctxt, %async.ctxt* %callee_context.0, i32 0, i32 0 - store i8* %async.ctxt, i8** %callee_context.caller_context.addr - %resume_proj_fun = bitcast i8*(i8*)* @resume_context_projection to i8* - %callee = bitcast void(i8*, %async.task*, %async.actor*)* @asyncSuspend to i8* - %res = call {i8*, i8*, i8*, i8*} (i32, i8*, i8*, ...) + store ptr %async.ctxt, ptr %callee_context + %res = call {ptr, ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function - i8* %resume.func_ptr, - i8* %resume_proj_fun, - void (i8*, i8*, %async.task*, %async.actor*)* @my_async_function.my_other_async_function_fp.apply, - i8* %callee, i8* %callee_context, %async.task* %task, %async.actor *%actor) - - call void @llvm.coro.async.context.dealloc(i8* %callee_context) - %continuation_task_arg = extractvalue {i8*, i8*, i8*, i8*} %res, 3 - %task.2 = bitcast i8* %continuation_task_arg to %async.task* - %val = load i64, i64* %proj.1 + ptr %resume.func_ptr, + ptr @resume_context_projection, + ptr @my_async_function.my_other_async_function_fp.apply, + ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor) + + call void @llvm.coro.async.context.dealloc(ptr %callee_context) + %continuation_task_arg = extractvalue {ptr, ptr, ptr, ptr} %res, 3 + %val = load i64, ptr %proj.1 call void @some_user(i64 %val) - %val.2 = load i64, i64* %proj.2 + %val.2 = load i64, ptr %proj.2 call void @some_user(i64 %val.2) - tail call swiftcc void @asyncReturn(i8* %async.ctxt, %async.task* %task.2, %async.actor* %actor) - call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0) + tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } -; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(i8* swiftasync %async.ctxt, %async.task* %task, %async.actor* %actor) -; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(i8* {{.*}}swiftasync{{.*}} %0, i8* {{.*}}swiftself{{.*}} %1, i8* {{.*}}%2, i8* {{.*}}%3) -; CHECK: bitcast i8* %3 to %async.task* +; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) +; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3) ; CHECK: } @no_coro_suspend_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (i8*)* @no_coro_suspend to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @no_coro_suspend_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @no_coro_suspend to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64) ) to i32), i32 128 ; Initial async context size without space for frame }> -define swiftcc void @no_coro_suspend(i8* %async.ctx) presplitcoroutine { +define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine { entry: %some_alloca = alloca i64 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, - i8* bitcast (<{i32, i32}>* @no_coro_suspend_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) - call void @some_may_write(i64* %some_alloca) - call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0) + ptr @no_coro_suspend_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + call void @some_may_write(ptr %some_alloca) + call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } ; CHECK-LABEL: define swiftcc void @no_coro_suspend ; CHECK: [[ALLOCA:%.*]] = alloca i64 -; CHECK: call void @some_may_write(i64* {{.*}}[[ALLOCA]]) +; CHECK: call void @some_may_write(ptr {{.*}}[[ALLOCA]]) @no_coro_suspend_swifterror_fp = constant <{ i32, i32 }> <{ i32 trunc ( ; Relative pointer to async function i64 sub ( - i64 ptrtoint (void (i8*)* @no_coro_suspend_swifterror to i64), - i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64) + i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64) ) to i32), i32 128 ; Initial async context size without space for frame }> -declare void @do_with_swifterror(i64** swifterror) +declare void @do_with_swifterror(ptr swifterror) -define swiftcc void @no_coro_suspend_swifterror(i8* %async.ctx) presplitcoroutine { +define swiftcc void @no_coro_suspend_swifterror(ptr %async.ctx) presplitcoroutine { entry: - %some_alloca = alloca swifterror i64* + %some_alloca = alloca swifterror ptr %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, - i8* bitcast (<{i32, i32}>* @no_coro_suspend_swifterror_fp to i8*)) - %hdl = call i8* @llvm.coro.begin(token %id, i8* null) - store i64* null, i64** %some_alloca, align 8 - call void @do_with_swifterror(i64** swifterror %some_alloca) - call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0) + ptr @no_coro_suspend_swifterror_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + store ptr null, ptr %some_alloca, align 8 + call void @do_with_swifterror(ptr swifterror %some_alloca) + call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } ; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror - ; CHECK: [[ALLOCA:%.*]] = alloca swifterror i64* - ; CHECK: store i64* null, i64** [[ALLOCA]] - ; CHECK: call void @do_with_swifterror(i64** {{.*}}swifterror{{.*}} [[ALLOCA]]) + ; CHECK: [[ALLOCA:%.*]] = alloca swifterror ptr + ; CHECK: store ptr null, ptr [[ALLOCA]] + ; CHECK: call void @do_with_swifterror(ptr {{.*}}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) + i64 ptrtoint (ptr @undefined_coro_async_resume to i64), + i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64) ) to i32), i32 24 }> declare void @crash() -declare void @use(i8*) +declare void @use(ptr) -define swiftcc void @undefined_coro_async_resume(i8 *%async.ctx) presplitcoroutine { +define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine { 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) + %id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, ptr @undefined_coro_async_resume_fp) + %hdl = call ptr @llvm.coro.begin(token %id, ptr null) + %undefined_resume_pointer = call ptr @llvm.coro.async.resume() + call void @use(ptr %undefined_resume_pointer) call void @crash() - %unused = call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 false) + %unused = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %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: call void @use(ptr null) ; CHECK: ret -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*) -declare i8* @llvm.coro.begin(token, i8*) -declare i1 @llvm.coro.end.async(i8*, i1, ...) -declare i1 @llvm.coro.end(i8*, i1) -declare {i8*, i8*, i8*} @llvm.coro.suspend.async(i32, i8*, i8*, ...) -declare i8* @llvm.coro.async.context.alloc(i8*, i8*) -declare void @llvm.coro.async.context.dealloc(i8*) -declare swiftcc void @asyncReturn(i8*, %async.task*, %async.actor*) -declare swiftcc void @asyncSuspend(i8*, %async.task*, %async.actor*) -declare i8* @llvm.coro.async.resume() -declare void @llvm.coro.async.size.replace(i8*, i8*) -declare i8* @hide(i8*) +declare { ptr, ptr, ptr, ptr } @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32, ptr, ptr, ...) +declare ptr @llvm.coro.prepare.async(ptr) +declare token @llvm.coro.id.async(i32, i32, i32, ptr) +declare ptr @llvm.coro.begin(token, ptr) +declare i1 @llvm.coro.end.async(ptr, i1, ...) +declare i1 @llvm.coro.end(ptr, i1) +declare {ptr, ptr, ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...) +declare ptr @llvm.coro.async.context.alloc(ptr, ptr) +declare void @llvm.coro.async.context.dealloc(ptr) +declare swiftcc void @asyncReturn(ptr, ptr, ptr) +declare swiftcc void @asyncSuspend(ptr, ptr, ptr) +declare ptr @llvm.coro.async.resume() +declare void @llvm.coro.async.size.replace(ptr, ptr) +declare ptr @hide(ptr) !llvm.dbg.cu = !{!2} !llvm.module.flags = !{!0} -- 2.7.4