575 lines · plain
1; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s2; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s3target datalayout = "p:64:64:64"4 5%async.task = type { i64 }6%async.actor = type { i64 }7%async.fp = type <{ i32, i32 }>8 9%async.ctxt = type { ptr, ptr }10 11; The async callee.12@my_other_async_function_fp = external global <{ i32, i32 }>13declare void @my_other_async_function(ptr %async.ctxt)14 15; The current async function (the caller).16; This struct describes an async function. The first field is the17; relative offset to the async function implementation, the second field is the18; size needed for the async context of the current async function.19 20@my_async_function_fp = constant <{ i32, i32 }>21 <{ i32 trunc ( ; Relative pointer to async function22 i64 sub (23 i64 ptrtoint (ptr @my_async_function to i64),24 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)25 )26 to i32),27 i32 128 ; Initial async context size without space for frame28}>29@my_async_function_pa_fp = constant <{ i32, i32 }>30 <{ i32 trunc (31 i64 sub (32 i64 ptrtoint (ptr @my_async_function_pa to i64),33 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64)34 )35 to i32),36 i32 837}>38 39; Function that implements the dispatch to the callee function.40define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {41 tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)42 ret void43}44 45declare void @some_user(i64)46declare void @some_may_write(ptr)47 48define ptr @__swift_async_resume_project_context(ptr %ctxt) {49entry:50 %resume_ctxt = load ptr, ptr %ctxt, align 851 ret ptr %resume_ctxt52}53 54define ptr @resume_context_projection(ptr %ctxt) {55entry:56 %resume_ctxt = load ptr, ptr %ctxt, align 857 ret ptr %resume_ctxt58}59 60 61define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 {62entry:63 %tmp = alloca { i64, i64 }, align 864 %vector = alloca <4 x double>, align 1665 %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 066 %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 167 68 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,69 ptr @my_async_function_fp)70 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)71 store i64 0, ptr %proj.1, align 872 store i64 1, ptr %proj.2, align 873 call void @some_may_write(ptr %proj.1)74 75 ; Begin lowering: apply %my_other_async_function(%args...)76 77 ; setup callee context78 %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)79 ; store arguments ...80 ; ... (omitted)81 82 ; store the return continuation83 %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 184 %resume.func_ptr = call ptr @llvm.coro.async.resume()85 store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr86 87 ; store caller context into callee context88 store ptr %async.ctxt, ptr %callee_context89 %vector_spill = load <4 x double>, ptr %vector, align 1690 %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,91 ptr %resume.func_ptr,92 ptr @__swift_async_resume_project_context,93 ptr @my_async_function.my_other_async_function_fp.apply,94 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !595 96 call void @llvm.coro.async.context.dealloc(ptr %callee_context)97 %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 198 %val = load i64, ptr %proj.199 call void @some_user(i64 %val)100 %val.2 = load i64, ptr %proj.2101 call void @some_user(i64 %val.2)102 store <4 x double> %vector_spill, ptr %vector, align 16103 tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)104 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)105 unreachable106}107 108define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {109 call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp)110 call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor)111 ret void112}113 114; Make sure we update the async function pointer115; CHECK: @my_async_function_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }116; CHECK: @my_async_function_pa_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }117; CHECK: @my_async_function2_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }118 119; CHECK-LABEL: define swiftcc void @my_async_function(ptr swiftasync initializes((152, 160)) %async.ctxt, ptr %task, ptr %actor)120; CHECK-O0-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor)121; CHECK-SAME: !dbg ![[SP1:[0-9]+]] {122; CHECK: coro.return:123; CHECK: [[FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 128124; CHECK: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 152125; CHECK: store ptr %actor, ptr [[ACTOR_SPILL_ADDR]]126; CHECK: [[ADDR1:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 144127; CHECK: store ptr %async.ctxt, ptr [[ADDR1]]128; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 136129; CHECK: store i64 0, ptr [[FRAMEPTR]]130; CHECK: store i64 1, ptr [[ALLOCA_PRJ2]]131; CHECK: tail call void @some_may_write(ptr nonnull [[FRAMEPTR]])132; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr %task, ptr nonnull @my_other_async_function_fp)133; CHECK: [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 160134; CHECK: store ptr [[CALLEE_CTXT]], ptr [[CALLEE_CTXT_SPILL]]135; CHECK: [[TYPED_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CTXT]], i64 8136; CHECK: store ptr @my_async_functionTQ0_, ptr [[TYPED_RETURN_TO_CALLER_ADDR]]137; CHECK: store ptr %async.ctxt, ptr [[CALLEE_CTXT]]138; Make sure the spill is underaligned to the max context alignment (16).139; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}}140; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1141; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16142; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)143; CHECK: ret void144; CHECK: }145 146; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr readonly swiftasync captures(none) %0, ptr %1, ptr readnone captures(none) %2)147; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2)148; CHECK-SAME: !dbg ![[SP2:[0-9]+]] {149; CHECK: entryresume.0:150; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0151; CHECK: [[FRAME_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 128152; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1153; CHECK-O0: load <4 x double>, ptr [[VECTOR_SPILL_ADDR]], align 16154; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 160155; CHECK: [[CALLEE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]156; CHECK: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 152157; CHECK: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]]158; CHECK: [[ADDR1:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 144159; CHECK: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ADDR1]]160; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 136161; CHECK: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CTXT_RELOAD]])162; CHECK: [[VAL1:%.*]] = load i64, ptr [[FRAME_PTR]]163; CHECK: tail call void @some_user(i64 [[VAL1]])164; CHECK: [[VAL2:%.*]] = load i64, ptr [[ALLOCA_PRJ2]]165; CHECK: tail call void @some_user(i64 [[VAL2]])166; CHECK: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]])167; CHECK: ret void168; CHECK: }169 170@my_async_function2_fp = constant <{ i32, i32 }>171 <{ i32 trunc ( ; Relative pointer to async function172 i64 sub (173 i64 ptrtoint (ptr @my_async_function2 to i64),174 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64)175 )176 to i32),177 i32 128 ; Initial async context size without space for frame178 }>179 180define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 {181entry:182 183 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, ptr @my_async_function2_fp)184 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)185 ; setup callee context186 %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)187 188 %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1189 %resume.func_ptr = call ptr @llvm.coro.async.resume()190 store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr191 store ptr %async.ctxt, ptr %callee_context192 %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 2,193 ptr %resume.func_ptr,194 ptr @resume_context_projection,195 ptr @my_async_function.my_other_async_function_fp.apply,196 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9197 198 %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 0199 200 %callee_context.return_to_caller.addr.1 = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1201 %resume.func_ptr.1 = call ptr @llvm.coro.async.resume()202 store ptr %resume.func_ptr.1, ptr %callee_context.return_to_caller.addr.1203 store ptr %async.ctxt, ptr %callee_context204 %res.2 = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,205 ptr %resume.func_ptr.1,206 ptr @resume_context_projection,207 ptr @my_async_function.my_other_async_function_fp.apply,208 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)209 210 call void @llvm.coro.async.context.dealloc(ptr %callee_context)211 %continuation_actor_arg = extractvalue {ptr, ptr, ptr} %res.2, 1212 213 tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %continuation_actor_arg)214 call void @llvm.coro.end(ptr %hdl, i1 0, token none)215 unreachable216}217 218; CHECK-LABEL: define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt)219; CHECK-SAME: #[[FRAMEPOINTER:[0-9]+]]220; CHECK-SAME: !dbg ![[SP3:[0-9]+]]221; CHECK: store ptr %async.ctxt,222; CHECK: store ptr %actor,223; CHECK: store ptr %task,224; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(225; CHECK: store ptr [[CALLEE_CTXT]],226; CHECK: store ptr @my_async_function2.resume.0,227; CHECK: store ptr %async.ctxt,228; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)229; CHECK: ret void230 231; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(ptr %0, ptr readnone captures(none) %1, ptr readonly captures(none) %2)232; CHECK-SAME: #[[FRAMEPOINTER]]233; CHECK-SAME: !dbg ![[SP4:[0-9]+]]234; CHECK: [[CALLEE_CTXT:%.*]] = load ptr, ptr %2235; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CTXT]], i64 152236; CHECK: store ptr @my_async_function2.resume.1,237; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]238; CHECK: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]]239; CHECK: ret void240 241; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(ptr readonly captures(none) %0, ptr %1, ptr readnone captures(none) %2)242; CHECK-SAME: #[[FRAMEPOINTER]]243; CHECK: tail call swiftcc void @asyncReturn({{.*}}%1)244; CHECK: ret void245 246define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {247 %prepare = call ptr @llvm.coro.prepare.async(ptr @my_async_function)248 call swiftcc void %prepare(ptr %ctxt, ptr %task, ptr %actor)249 ret void250}251 252; CHECK-LABEL: define swiftcc void @top_level_caller(ptr initializes((152, 160)) %ctxt, ptr %task, ptr %actor)253; CHECK: store ptr @my_async_functionTQ0_254; CHECK: store ptr %ctxt255; CHECK: tail call swiftcc void @asyncSuspend256; CHECK: ret void257 258@dont_crash_on_cf_fp = constant <{ i32, i32 }>259 <{ i32 trunc ( ; Relative pointer to async function260 i64 sub (261 i64 ptrtoint (ptr @my_async_function to i64),262 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)263 )264 to i32),265 i32 128 ; Initial async context size without space for frame266}>267 268 269define swiftcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {270 %isNull = icmp eq ptr %task, null271 br i1 %isNull, label %is_null, label %is_not_null272 273is_null:274 ret void275 276is_not_null:277 tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)278 ret void279}280 281define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {282entry:283 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,284 ptr @dont_crash_on_cf_fp)285 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)286 %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)287 %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1288 %resume.func_ptr = call ptr @llvm.coro.async.resume()289 store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr290 store ptr %async.ctxt, ptr %callee_context291 %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,292 ptr %resume.func_ptr,293 ptr @resume_context_projection,294 ptr @dont_crash_on_cf_dispatch,295 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)296 297 call void @llvm.coro.async.context.dealloc(ptr %callee_context)298 %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1299 tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)300 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)301 unreachable302}303 304@multiple_coro_end_async_fp = constant <{ i32, i32 }>305 <{ i32 trunc ( ; Relative pointer to async function306 i64 sub (307 i64 ptrtoint (ptr @multiple_coro_end_async to i64),308 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64)309 )310 to i32),311 i32 128 ; Initial async context size without space for frame312}>313 314define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) {315 musttail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor)316 ret void317}318 319define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {320entry:321 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,322 ptr @dont_crash_on_cf_fp)323 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)324 %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)325 %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1326 %resume.func_ptr = call ptr @llvm.coro.async.resume()327 store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr328 store ptr %async.ctxt, ptr %callee_context329 %res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,330 ptr %resume.func_ptr,331 ptr @resume_context_projection,332 ptr @dont_crash_on_cf_dispatch,333 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)334 335 call void @llvm.coro.async.context.dealloc(ptr %callee_context)336 %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1337 %eq = icmp eq ptr %continuation_task_arg, null338 br i1 %eq, label %is_equal, label %is_not_equal339 340is_equal:341 tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)342 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)343 unreachable344 345is_not_equal:346 call void (ptr, i1, ...) @llvm.coro.end.async(347 ptr %hdl, i1 0,348 ptr @must_tail_call_return,349 ptr %async.ctxt, ptr %continuation_task_arg, ptr null)350 unreachable351}352 353; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(354; CHECK: musttail call swiftcc void @asyncReturn(355; CHECK: ret void356 357@polymorphic_suspend_return_fp = constant <{ i32, i32 }>358 <{ i32 trunc ( ; Relative pointer to async function359 i64 sub (360 i64 ptrtoint (ptr @polymorphic_suspend_return to i64),361 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64)362 )363 to i32),364 i32 64 ; Initial async context size without space for frame365}>366 367define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {368entry:369 %tmp = alloca { i64, i64 }, align 8370 %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0371 %proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1372 373 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,374 ptr @polymorphic_suspend_return_fp)375 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)376 store i64 0, ptr %proj.1, align 8377 store i64 1, ptr %proj.2, align 8378 call void @some_may_write(ptr %proj.1)379 380 ; Begin lowering: apply %my_other_async_function(%args...)381 382 ; setup callee context383 %callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)384 ; store arguments ...385 ; ... (omitted)386 387 ; store the return continuation388 %callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1389 %resume.func_ptr = call ptr @llvm.coro.async.resume()390 store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr391 392 ; store caller context into callee context393 store ptr %async.ctxt, ptr %callee_context394 %res = call {ptr, ptr, ptr, ptr} (i32, ptr, ptr, ...)395 @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function396 ptr %resume.func_ptr,397 ptr @resume_context_projection,398 ptr @my_async_function.my_other_async_function_fp.apply,399 ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)400 401 call void @llvm.coro.async.context.dealloc(ptr %callee_context)402 %continuation_task_arg = extractvalue {ptr, ptr, ptr, ptr} %res, 3403 %val = load i64, ptr %proj.1404 call void @some_user(i64 %val)405 %val.2 = load i64, ptr %proj.2406 call void @some_user(i64 %val.2)407 408 tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor)409 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)410 unreachable411}412 413; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync initializes((152, 160)) %async.ctxt, ptr %task, ptr %actor)414; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3)415; CHECK: }416 417@no_coro_suspend_fp = constant <{ i32, i32 }>418 <{ i32 trunc ( ; Relative pointer to async function419 i64 sub (420 i64 ptrtoint (ptr @no_coro_suspend to i64),421 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64)422 )423 to i32),424 i32 128 ; Initial async context size without space for frame425}>426 427define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine {428entry:429 %some_alloca = alloca i64430 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,431 ptr @no_coro_suspend_fp)432 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)433 call void @some_may_write(ptr %some_alloca)434 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)435 unreachable436}437 438; CHECK-LABEL: define swiftcc void @no_coro_suspend439; CHECK: [[ALLOCA:%.*]] = alloca i64440; CHECK: call void @some_may_write(ptr {{.*}}[[ALLOCA]])441 442@no_coro_suspend_swifterror_fp = constant <{ i32, i32 }>443 <{ i32 trunc ( ; Relative pointer to async function444 i64 sub (445 i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64),446 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)447 )448 to i32),449 i32 128 ; Initial async context size without space for frame450}>451 452declare void @do_with_swifterror(ptr swifterror)453 454define swiftcc void @no_coro_suspend_swifterror(ptr %async.ctx) presplitcoroutine {455entry:456 %some_alloca = alloca swifterror ptr457 %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,458 ptr @no_coro_suspend_swifterror_fp)459 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)460 store ptr null, ptr %some_alloca, align 8461 call void @do_with_swifterror(ptr swifterror %some_alloca)462 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)463 unreachable464}465 466 ; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror467 ; CHECK: [[ALLOCA:%.*]] = alloca swifterror ptr468 ; CHECK: store ptr null, ptr [[ALLOCA]]469 ; CHECK: call void @do_with_swifterror(ptr {{.*}}swifterror{{.*}} [[ALLOCA]])470 471@undefined_coro_async_resume_fp = constant <{ i32, i32 }>472 <{ i32 trunc (473 i64 sub (474 i64 ptrtoint (ptr @undefined_coro_async_resume to i64),475 i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64)476 )477 to i32),478 i32 24479}>480 481declare void @crash()482declare void @use(ptr)483 484define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine {485entry:486 %id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, ptr @undefined_coro_async_resume_fp)487 %hdl = call ptr @llvm.coro.begin(token %id, ptr null)488 %undefined_resume_pointer = call ptr @llvm.coro.async.resume()489 call void @use(ptr %undefined_resume_pointer)490 call void @crash()491 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 false)492 unreachable493}494; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume495; CHECK-NOT: @llvm.coro.async.resume496; CHECK: call void @use(ptr null)497; CHECK: ret498 499@simpleFuncTu = global <{i32, i32}> <{500 i32 trunc (i64 sub (i64 ptrtoint (ptr @simpleFunc to i64),501 i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }>502 503define swifttailcc void @simpleFunc(ptr swiftasync %0) presplitcoroutine {504entry:505 %1 = alloca ptr, align 8506 %2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @simpleFuncTu)507 %3 = call ptr @llvm.coro.begin(token %2, ptr null)508 store ptr %0, ptr %1, align 8509 %4 = load ptr, ptr %1, align 8510 %5 = getelementptr inbounds <{ ptr, ptr }>, ptr %4, i32 0, i32 1511 %6 = load ptr, ptr %5, align 8512 %7 = load ptr, ptr %1, align 8513 call void (ptr, i1, ...) @llvm.coro.end.async(ptr %3, i1 false, ptr @simpleFunc.0, ptr %6, ptr %7)514 unreachable515}516 517; CHECK-LABEL: define swifttailcc void @simpleFunc(ptr swiftasync %0) {518; CHECK-NOT: define519; CHECK: [[RESUME:%.*]] = load ptr520; CHECK: musttail call swifttailcc void [[RESUME]]521 522define internal swifttailcc void @simpleFunc.0(ptr %0, ptr %1) alwaysinline {523entry:524 musttail call swifttailcc void %0(ptr swiftasync %1)525 ret void526}527 528declare { ptr, ptr, ptr, ptr } @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32, ptr, ptr, ...)529declare ptr @llvm.coro.prepare.async(ptr)530declare token @llvm.coro.id.async(i32, i32, i32, ptr)531declare ptr @llvm.coro.begin(token, ptr)532declare void @llvm.coro.end.async(ptr, i1, ...)533declare void @llvm.coro.end(ptr, i1, token)534declare {ptr, ptr, ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)535declare ptr @llvm.coro.async.context.alloc(ptr, ptr)536declare void @llvm.coro.async.context.dealloc(ptr)537declare swiftcc void @asyncReturn(ptr, ptr, ptr)538declare swiftcc void @asyncSuspend(ptr, ptr, ptr)539declare ptr @llvm.coro.async.resume()540declare void @llvm.coro.async.size.replace(ptr, ptr)541declare ptr @hide(ptr)542 543!llvm.dbg.cu = !{!2}544!llvm.module.flags = !{!0}545 546!0 = !{i32 2, !"Debug Info Version", i32 3}547; CHECK: ![[SP1]] = distinct !DISubprogram(name: "my_async_function",548; CHECK-SAME: linkageName: "my_async_function",549; CHECK-SAME: scopeLine: 1550!1 = distinct !DISubprogram(name: "my_async_function",551 linkageName: "my_async_function",552 scope: !2, file: !3, line: 1, type: !4,553 scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)554; CHECK: ![[SP2]] = distinct !DISubprogram(name: "my_async_function",555; CHECK-SAME: linkageName: "my_async_functionTQ0_",556; CHECK-SAME: scopeLine: 2557!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, emissionKind: FullDebug)558!3 = !DIFile(filename: "/tmp/1.swift", directory: "/")559!4 = !DISubroutineType(types: !{})560!5 = !DILocation(line: 2, column: 0, scope: !1)561 562; CHECK: ![[SP3]] = distinct !DISubprogram(name: "my_async_function2",563; CHECK-SAME: linkageName: "my_async_function2",564; CHECK-SAME: scopeLine: 1565!6 = distinct !DISubprogram(name: "my_async_function2",566 linkageName: "my_async_function2",567 scope: !2, file: !3, line: 1, type: !4,568 scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)569; CHECK: ![[SP4]] = distinct !DISubprogram(name: "my_async_function2",570; CHECK-SAME: linkageName: "my_async_function2.resume.0",571; CHECK-SAME: scopeLine: 1572!7 = !DILexicalBlockFile(scope: !6, file: !8, discriminator: 0)573!8 = !DIFile(filename: "/tmp/fake.cpp", directory: "/")574!9 = !DILocation(line: 2, column: 0, scope: !7)575