1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
// RUN: %target-swift-frontend -emit-irgen %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-cpu --check-prefix=CHECK-%target-ptrsize -DINT=i%target-ptrsize
import Builtin
sil @marker : $(Builtin.Int64) -> ()
sil @coro_ret : $@yield_once @convention(thin) () -> (@yields Builtin.Int64, Builtin.Int64)
sil @coro_ret_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int64, Builtin.Int64, Builtin.Int64)
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} swiftcc ptr @test_simple
// CHECK-32-SAME: ptr noalias dereferenceable([[BUFFER_SIZE:16]]) %0)
// CHECK-64-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE:32]]) %0)
// CHECK-SAME: [[CORO_ATTRIBUTES:#[0-9]+]]
sil @test_simple : $@yield_once () -> (Builtin.Int64) {
entry:
// CHECK-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr %0, ptr @"$sBi64_IetAd_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free)
// CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr %0, ptr @"$sBi64_IetAd_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free)
// CHECK-NEXT: [[BEGIN:%.*]] = call ptr @llvm.coro.begin(token [[ID]], ptr null)
// CHECK-NEXT: call swiftcc void @marker(i64 1000)
%marker = function_ref @marker : $@convention(thin) (Builtin.Int64) -> ()
%1000 = integer_literal $Builtin.Int64, 1000
apply %marker(%1000) : $@convention(thin) (Builtin.Int64) -> ()
// CHECK-NEXT: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1()
// CHECK-NEXT: br i1 [[IS_UNWIND]], label [[UNWIND_BB:%.*]], label [[RESUME_BB:%.*]]
yield (), resume resume, unwind unwind
resume:
// CHECK: call swiftcc void @marker(i64 2000)
%2000 = integer_literal $Builtin.Int64, 2000
apply %marker(%2000) : $@convention(thin) (Builtin.Int64) -> ()
// CHECK: br label %coro.end
return %2000 : $Builtin.Int64
unwind:
// CHECK: call swiftcc void @marker(i64 3000)
%3000 = integer_literal $Builtin.Int64, 3000
apply %marker(%3000) : $@convention(thin) (Builtin.Int64) -> ()
// CHECK: br label %coro.end
unwind
// CHECK: coro.end:
// CHECK: [[RESULT:%.*]] = phi i64 [ 2000, [[RESUME_BB]] ], [ undef, [[UNWIND_BB]] ]
// CHECK: [[TOKEN:%.*]] = call token (...) @llvm.coro.end.results(i64 [[RESULT]])
// CHECK: call i1 @llvm.coro.end(ptr [[BEGIN]], i1 false, token [[TOKEN]])
// CHECK-NEXT: unreachable
}
// CHECK-LABEL: declare{{( dllimport)?}}{{( protected)?}} swiftcc i64 @"$sBi64_IetAd_TC{{(.ptrauth)?}}"
// CHECK-SAME: (ptr noalias dereferenceable([[BUFFER_SIZE]]), i1)
// CHECK-LABEL: test_coro_ret
sil @test_coro_ret : $() -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
entry:
%marker = function_ref @marker : $@convention(thin) (Builtin.Int64) -> ()
%coro1 = function_ref @coro_ret : $@yield_once @convention(thin) () -> (@yields Builtin.Int64, Builtin.Int64)
(%first, %token1) = begin_apply %coro1() : $@yield_once @convention(thin) () -> (@yields Builtin.Int64, Builtin.Int64)
// CHECK: [[T0:%.*]] = alloca {{\[}}[[BUFFER_SIZE1:.*]] x i8
// CHECK: [[T1:%.*]] = alloca {{\[}}[[BUFFER_SIZE2:.*]] x i8
// CHECK: [[BUFFER1:%.*]] = getelementptr inbounds {{\[}}[[BUFFER_SIZE1]] x i8], ptr [[T0]], i32 0, i32 0
// CHECK: [[CORO1:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @coro_ret)
// CHECK: [[FRAME1:%.*]] = call swiftcc { ptr, i64 } [[CORO1]](ptr noalias dereferenceable([[BUFFER_SIZE1]]) [[BUFFER1]]
// CHECK: [[CONT1:%.*]] = extractvalue { ptr, i64 } [[FRAME1]], 0
apply %marker(%first) : $@convention(thin) (Builtin.Int64) -> ()
%ret = end_apply %token1 as $Builtin.Int64
// CHECK: call swiftcc i64 [[CONT1]](ptr noalias dereferenceable([[BUFFER_SIZE1]]) [[BUFFER1]], i1 false)
apply %marker(%ret) : $@convention(thin) (Builtin.Int64) -> ()
%coro2 = function_ref @coro_ret_pair : $@yield_once @convention(thin) () -> (@yields Builtin.Int64, Builtin.Int64, Builtin.Int64)
(%second, %token2) = begin_apply %coro2() : $@yield_once @convention(thin) () -> (@yields Builtin.Int64, Builtin.Int64, Builtin.Int64)
// CHECK: [[BUFFER2:%.*]] = getelementptr inbounds {{\[}}[[BUFFER_SIZE2]] x i8], ptr [[T1]], i32 0, i32 0
// CHECK: [[CORO2:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @coro_ret_pair)
// CHECK: [[FRAME2:%.*]] = call swiftcc { ptr, i64 } [[CORO2]](ptr noalias dereferenceable([[BUFFER_SIZE2]]) [[BUFFER2]]
// CHECK: [[CONT2:%.*]] = extractvalue { ptr, i64 } [[FRAME2]], 0
%ret2 = end_apply %token2 as $(Builtin.Int64, Builtin.Int64)
// CHECK: call swiftcc { i64, i64 } [[CONT2]](ptr noalias dereferenceable([[BUFFER_SIZE2]]) [[BUFFER2]], i1 false)
%ret2_1 = tuple_extract %ret2 : $(Builtin.Int64, Builtin.Int64), 0
%ret2_2 = tuple_extract %ret2 : $(Builtin.Int64, Builtin.Int64), 1
apply %marker(%second) : $@convention(thin) (Builtin.Int64) -> ()
%retf = tuple (%ret : $Builtin.Int64, %ret2_1 : $Builtin.Int64, %ret2_2 : $Builtin.Int64)
return %retf : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
}
// CHECK-LABEL: coro_ret_indirect
// CHECK-SAME: ptr{{.*}} [[CTX:%.*]], ptr{{.*}} [[INDIRECT_RET:%.*]], ptr{{.*}} [[ARG:%.*]], ptr{{.*}} [[TYPE:%.*]])
sil @coro_ret_indirect : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T) {
bb0(%outt : $*T, %t : $*T):
// CHECK-32: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:4]], ptr [[CTX]], ptr @"$sxxxlIetAirYi_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free)
// CHECK-64: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 [[BUFFER_SIZE]], i32 [[BUFFER_ALIGN:8]], ptr [[CTX]], ptr @"$sxxxlIetAirYi_TC{{(.ptrauth)?}}", ptr @malloc, ptr @free)
// CHECK: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr [[ARG]])
// CHECK: br i1 [[IS_UNWIND]], label %[[UNWIND_BB:.*]], label %[[RESUME_BB:.*]]
// CHECK:[[RESUME_BB]]:
// CHECK: [[VW_PTR:%.*]] = getelementptr inbounds ptr, ptr [[TYPE]], [[INT]] -1
// CHECK: [[VW:%.*]] = load ptr, ptr [[VW_PTR]]
// CHECK-arm64e-NEXT: ptrtoint ptr [[VW_PTR]] to i64
// CHECK-arm64e-NEXT: call i64 @llvm.ptrauth.blend
// CHECK-arm64e: [[VW:%.*]] = inttoptr i64 {{%.*}} to ptr
// CHECK: [[ASSIGN_PTR:%.*]] = getelementptr inbounds ptr, ptr [[VW]], i32 3
// CHECK: [[ASSIGN:%.*]] = load ptr, ptr [[ASSIGN_PTR]]
// CHECK: call ptr [[ASSIGN]](ptr [[INDIRECT_RET]], ptr [[ARG]], ptr [[TYPE]]) #2
yield (%t : $*T), resume bb1, unwind bb2
bb1:
copy_addr %t to %outt : $*T
%r = tuple ()
return %r : $()
bb2:
unwind
}
// CHECK-LABEL: @test_coro_ret_indirect
// CHECK-SAME: (i64 [[ARG:%.*]])
sil [ossa] @test_coro_ret_indirect : $(Builtin.Int64) -> () {
bb0(%0 : $Builtin.Int64):
// CHECK: [[ARG_COPY:%.*]] = alloca i64
// CHECK: [[INDIRECT_RET:%.*]] = alloca i64
// CHECK: [[FRAME:%.*]] = alloca [[[BUFFER_SIZE]] x i8]
%coro = function_ref @coro_ret_indirect : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T)
%temp = alloc_stack $Builtin.Int64
store %0 to [trivial] %temp : $*Builtin.Int64
%out = alloc_stack $Builtin.Int64
// CHECK: store i64 [[ARG]], ptr [[ARG_COPY]]
// CHECK: [[CTX:%.*]] = getelementptr inbounds [[[BUFFER_SIZE]] x i8], ptr [[FRAME]], i32 0, i32 0
// CHECK: [[CORO:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @coro_ret_indirect)
// CHECK: [[FRAME:%.*]] = call swiftcc { ptr, ptr } [[CORO]](ptr{{.*}} [[CTX]], ptr [[INDIRECT_RET]], ptr noalias [[ARG_COPY]], ptr getelementptr inbounds (%swift.full_existential_type, ptr @{{.*}}
(%f1, %token) = begin_apply %coro<Builtin.Int64>(%out, %temp) : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T)
%f2 = end_apply %token as $()
dealloc_stack %out : $*Builtin.Int64
dealloc_stack %temp : $*Builtin.Int64
%r = tuple ()
return %r : $()
}
|