@@ -91,3 +91,60 @@ entry:
9191 %retf = tuple (%ret : $Builtin.Int64, %ret2_1 : $Builtin.Int64, %ret2_2 : $Builtin.Int64)
9292 return %retf : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
9393}
94+
95+ // CHECK-LABEL: coro_ret_indirect
96+ // CHECK-SAME: ptr{{.*}} [[CTX:%.*]], ptr{{.*}} [[INDIRECT_RET:%.*]], ptr{{.*}} [[ARG:%.*]], ptr{{.*}} [[TYPE:%.*]])
97+ sil @coro_ret_indirect : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T) {
98+ bb0(%outt : $*T, %t : $*T):
99+ // 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)
100+ // 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)
101+
102+ // CHECK: [[IS_UNWIND:%.*]] = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr [[ARG]])
103+ // CHECK: br i1 [[IS_UNWIND]], label %[[UNWIND_BB:.*]], label %[[RESUME_BB:.*]]
104+
105+ // CHECK:[[RESUME_BB]]:
106+ // CHECK: [[VW_PTR:%.*]] = getelementptr inbounds ptr, ptr [[TYPE]], i64 -1
107+ // CHECK: [[VW:%.*]] = load ptr, ptr [[VW_PTR]]
108+ // CHECK: [[ASSIGN_PTR:%.*]] = getelementptr inbounds ptr, ptr [[VW]], i32 3
109+ // CHECK: [[ASSIGN:%.*]] = load ptr, ptr [[ASSIGN_PTR]]
110+ // CHECK: call ptr [[ASSIGN]](ptr [[INDIRECT_RET]], ptr [[ARG]], ptr [[TYPE]]) #2
111+
112+ yield (%t : $*T), resume bb1, unwind bb2
113+
114+ bb1:
115+ copy_addr %t to %outt : $*T
116+ %r = tuple ()
117+ return %r : $()
118+
119+ bb2:
120+ unwind
121+ }
122+
123+ // CHECK-LABEL: @test_coro_ret_indirect
124+ // CHECK-SAME: (i64 [[ARG:%.*]])
125+ sil [ossa] @test_coro_ret_indirect : $(Builtin.Int64) -> () {
126+ bb0(%0 : $Builtin.Int64):
127+ // CHECK: [[ARG_COPY:%.*]] = alloca i64
128+ // CHECK: [[INDIRECT_RET:%.*]] = alloca i64
129+ // CHECK: [[FRAME:%.*]] = alloca [32 x i8]
130+ %coro = function_ref @coro_ret_indirect : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T)
131+ %temp = alloc_stack $Builtin.Int64
132+ store %0 to [trivial] %temp : $*Builtin.Int64
133+
134+ %out = alloc_stack $Builtin.Int64
135+
136+ // CHECK: store i64 [[ARG]], ptr [[ARG_COPY]]
137+ // CHECK: [[CTX:%.*]] = getelementptr inbounds [32 x i8], ptr [[FRAME]], i32 0, i32 0
138+ // CHECK: [[CORO:%.*]] = call ptr @llvm.coro.prepare.retcon(ptr @coro_ret_indirect)
139+ // CHECK: [[FRAME:%.*]] = call swiftcc { ptr, ptr } [[CORO]](ptr{{.*}} [[CTX]], ptr [[INDIRECT_RET]], ptr noalias [[ARG_COPY]], ptr getelementptr inbounds (%swift.full_existential_type, ptr @{{.*}}
140+
141+ (%f1, %token) = begin_apply %coro<Builtin.Int64>(%out, %temp) : $@yield_once @convention(thin) <T> (@in T) -> (@yields @in T, @out T)
142+
143+ %f2 = end_apply %token as $()
144+
145+ dealloc_stack %out : $*Builtin.Int64
146+ dealloc_stack %temp : $*Builtin.Int64
147+
148+ %r = tuple ()
149+ return %r : $()
150+ }
0 commit comments