1 // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fcoroutines-ts -std=c++14 \
2 // RUN:   -emit-llvm %s -o - -disable-llvm-passes -Wno-coroutine -Wno-unused | FileCheck %s
3 
4 namespace std {
5 namespace experimental {
6 template <typename... T>
7 struct coroutine_traits;
8 
9 template <typename Promise = void> struct coroutine_handle;
10 
11 template <>
12 struct coroutine_handle<void> {
13   void *ptr;
14   static coroutine_handle from_address(void *);
15   void *address();
16 };
17 
18 template <typename Promise>
19 struct coroutine_handle : coroutine_handle<> {
20   static coroutine_handle from_address(void *) noexcept;
21 };
22 
23 }
24 }
25 
26 struct init_susp {
27   bool await_ready();
28   void await_suspend(std::experimental::coroutine_handle<>);
29   void await_resume();
30 };
31 struct final_susp {
32   bool await_ready() noexcept;
33   void await_suspend(std::experimental::coroutine_handle<>) noexcept;
34   void await_resume() noexcept;
35 };
36 
37 struct suspend_always {
38   int stuff;
39   bool await_ready();
40   void await_suspend(std::experimental::coroutine_handle<>);
41   void await_resume();
42 };
43 
44 template<>
45 struct std::experimental::coroutine_traits<void> {
46   struct promise_type {
47     void get_return_object();
48     init_susp initial_suspend();
49     final_susp final_suspend() noexcept;
50     void return_void();
51   };
52 };
53 
54 // CHECK-LABEL: f0(
55 extern "C" void f0() {
56   // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
57 
58   // See if initial_suspend was issued:
59   // ----------------------------------
60   // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
61   // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(%struct.init_susp*
62   // CHECK: %[[INITSP_ID:.+]] = call token @llvm.coro.save(
63   // CHECK: call i8 @llvm.coro.suspend(token %[[INITSP_ID]], i1 false)
64 
65   co_await suspend_always{};
66   // See if we need to suspend:
67   // --------------------------
68   // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN14suspend_always11await_readyEv(%struct.suspend_always* {{[^,]*}} %[[AWAITABLE:.+]])
69   // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
70 
71   // If we are suspending:
72   // ---------------------
73   // CHECK: [[SUSPEND_BB]]:
74   // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
75   // ---------------------------
76   // Build the coroutine handle and pass it to await_suspend
77   // ---------------------------
78   // CHECK: call i8* @_ZNSt12experimental16coroutine_handleINS_16coroutine_traitsIJvEE12promise_typeEE12from_addressEPv(i8* %[[FRAME]])
79   //   ... many lines of code to coerce coroutine_handle into an i8* scalar
80   // CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
81   // CHECK: call void @_ZN14suspend_always13await_suspendENSt12experimental16coroutine_handleIvEE(%struct.suspend_always* {{[^,]*}} %[[AWAITABLE]], i8* %[[CH]])
82   // -------------------------
83   // Generate a suspend point:
84   // -------------------------
85   // CHECK: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
86   // CHECK: switch i8 %[[OUTCOME]], label %[[RET_BB:.+]] [
87   // CHECK:   i8 0, label %[[READY_BB]]
88   // CHECK:   i8 1, label %[[CLEANUP_BB:.+]]
89   // CHECK: ]
90 
91   // Cleanup code goes here:
92   // -----------------------
93   // CHECK: [[CLEANUP_BB]]:
94 
95   // When coroutine is resumed, call await_resume
96   // --------------------------
97   // CHECK: [[READY_BB]]:
98   // CHECK:  call void @_ZN14suspend_always12await_resumeEv(%struct.suspend_always* {{[^,]*}} %[[AWAITABLE]])
99 
100   // See if final_suspend was issued:
101   // ----------------------------------
102   // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
103   // CHECK-NEXT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
104   // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save(
105   // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)
106 }
107 
108 struct suspend_maybe {
109   float stuff;
110   ~suspend_maybe();
111   bool await_ready();
112   bool await_suspend(std::experimental::coroutine_handle<>);
113   void await_resume();
114 };
115 
116 
117 template<>
118 struct std::experimental::coroutine_traits<void,int> {
119   struct promise_type {
120     void get_return_object();
121     init_susp initial_suspend();
122     final_susp final_suspend() noexcept;
123     void return_void();
124     suspend_maybe yield_value(int);
125   };
126 };
127 
128 // CHECK-LABEL: f1(
129 extern "C" void f1(int) {
130   // CHECK: %[[PROMISE:.+]] = alloca %"struct.std::experimental::coroutine_traits<void, int>::promise_type"
131   // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
132   co_yield 42;
133   // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJviEE12promise_type11yield_valueEi(%struct.suspend_maybe* sret(%struct.suspend_maybe) align 4 %[[AWAITER:.+]], %"struct.std::experimental::coroutine_traits<void, int>::promise_type"* {{[^,]*}} %[[PROMISE]], i32 42)
134 
135   // See if we need to suspend:
136   // --------------------------
137   // CHECK: %[[READY:.+]] = call zeroext i1 @_ZN13suspend_maybe11await_readyEv(%struct.suspend_maybe* {{[^,]*}} %[[AWAITABLE]])
138   // CHECK: br i1 %[[READY]], label %[[READY_BB:.+]], label %[[SUSPEND_BB:.+]]
139 
140   // If we are suspending:
141   // ---------------------
142   // CHECK: [[SUSPEND_BB]]:
143   // CHECK: %[[SUSPEND_ID:.+]] = call token @llvm.coro.save(
144   // ---------------------------
145   // Build the coroutine handle and pass it to await_suspend
146   // ---------------------------
147   // CHECK: call i8* @_ZNSt12experimental16coroutine_handleINS_16coroutine_traitsIJviEE12promise_typeEE12from_addressEPv(i8* %[[FRAME]])
148   //   ... many lines of code to coerce coroutine_handle into an i8* scalar
149   // CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
150   // CHECK: %[[YES:.+]] = call zeroext i1 @_ZN13suspend_maybe13await_suspendENSt12experimental16coroutine_handleIvEE(%struct.suspend_maybe* {{[^,]*}} %[[AWAITABLE]], i8* %[[CH]])
151   // -------------------------------------------
152   // See if await_suspend decided not to suspend
153   // -------------------------------------------
154   // CHECK: br i1 %[[YES]], label %[[SUSPEND_PLEASE:.+]], label %[[READY_BB]]
155 
156   // CHECK: [[SUSPEND_PLEASE]]:
157   // CHECK:    call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
158 
159   // CHECK: [[READY_BB]]:
160   // CHECK:     call void @_ZN13suspend_maybe12await_resumeEv(%struct.suspend_maybe* {{[^,]*}} %[[AWAITABLE]])
161 }
162 
163 struct ComplexAwaiter {
164   template <typename F> void await_suspend(F);
165   bool await_ready();
166   _Complex float await_resume();
167 };
168 extern "C" void UseComplex(_Complex float);
169 
170 // CHECK-LABEL: @TestComplex(
171 extern "C" void TestComplex() {
172   UseComplex(co_await ComplexAwaiter{});
173   // CHECK: call <2 x float> @_ZN14ComplexAwaiter12await_resumeEv(%struct.ComplexAwaiter*
174   // CHECK: call void @UseComplex(<2 x float> %{{.+}})
175 
176   co_await ComplexAwaiter{};
177   // CHECK: call <2 x float> @_ZN14ComplexAwaiter12await_resumeEv(%struct.ComplexAwaiter*
178 
179   _Complex float Val = co_await ComplexAwaiter{};
180   // CHECK: call <2 x float> @_ZN14ComplexAwaiter12await_resumeEv(%struct.ComplexAwaiter*
181 }
182 
183 struct Aggr { int X, Y, Z; ~Aggr(); };
184 struct AggrAwaiter {
185   template <typename F> void await_suspend(F);
186   bool await_ready();
187   Aggr await_resume();
188 };
189 
190 extern "C" void Whatever();
191 extern "C" void UseAggr(Aggr&&);
192 
193 // FIXME: Once the cleanup code is in, add testing that destructors for Aggr
194 // are invoked properly on the cleanup branches.
195 
196 // CHECK-LABEL: @TestAggr(
197 extern "C" void TestAggr() {
198   UseAggr(co_await AggrAwaiter{});
199   Whatever();
200   // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %[[AwaitResume:.+]],
201   // CHECK: call void @UseAggr(%struct.Aggr* nonnull align 4 dereferenceable(12) %[[AwaitResume]])
202   // CHECK: call void @_ZN4AggrD1Ev(%struct.Aggr* {{[^,]*}} %[[AwaitResume]])
203   // CHECK: call void @Whatever()
204 
205   co_await AggrAwaiter{};
206   Whatever();
207   // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %[[AwaitResume2:.+]],
208   // CHECK: call void @_ZN4AggrD1Ev(%struct.Aggr* {{[^,]*}} %[[AwaitResume2]])
209   // CHECK: call void @Whatever()
210 
211   Aggr Val = co_await AggrAwaiter{};
212   Whatever();
213   // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %[[AwaitResume3:.+]],
214   // CHECK: call void @Whatever()
215   // CHECK: call void @_ZN4AggrD1Ev(%struct.Aggr* {{[^,]*}} %[[AwaitResume3]])
216 }
217 
218 struct ScalarAwaiter {
219   template <typename F> void await_suspend(F);
220   bool await_ready();
221   int await_resume();
222 };
223 
224 extern "C" void UseScalar(int);
225 
226 // CHECK-LABEL: @TestScalar(
227 extern "C" void TestScalar() {
228   UseScalar(co_await ScalarAwaiter{});
229   // CHECK: %[[Result:.+]] = call i32 @_ZN13ScalarAwaiter12await_resumeEv(%struct.ScalarAwaiter*
230   // CHECK: call void @UseScalar(i32 %[[Result]])
231 
232   int Val = co_await ScalarAwaiter{};
233   // CHECK: %[[Result2:.+]] = call i32 @_ZN13ScalarAwaiter12await_resumeEv(%struct.ScalarAwaiter*
234   // CHECK: store i32 %[[Result2]], i32* %[[TMP_EXPRCLEANUP:.+]],
235   // CHECK: %[[TMP:.+]] = load i32, i32* %[[TMP_EXPRCLEANUP]],
236   // CHECK: store i32 %[[TMP]], i32* %Val,
237 
238   co_await ScalarAwaiter{};
239   // CHECK: call i32 @_ZN13ScalarAwaiter12await_resumeEv(%struct.ScalarAwaiter*
240 }
241 
242 // Test operator co_await codegen.
243 enum class MyInt: int {};
244 ScalarAwaiter operator co_await(MyInt);
245 
246 struct MyAgg {
247   AggrAwaiter operator co_await();
248 };
249 
250 // CHECK-LABEL: @TestOpAwait(
251 extern "C" void TestOpAwait() {
252   co_await MyInt(42);
253   // CHECK: call void @_Zaw5MyInt(i32 42)
254   // CHECK: call i32 @_ZN13ScalarAwaiter12await_resumeEv(%struct.ScalarAwaiter* {{[^,]*}} %
255 
256   co_await MyAgg{};
257   // CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* {{[^,]*}} %
258   // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret(%struct.Aggr) align 4 %
259 }
260 
261 // CHECK-LABEL: EndlessLoop(
262 extern "C" void EndlessLoop() {
263   // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
264 
265   // See if initial_suspend was issued:
266   // ----------------------------------
267   // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
268   // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(%struct.init_susp*
269 
270   for (;;)
271     co_await suspend_always{};
272 
273   // Verify that final_suspend was NOT issued:
274   // ----------------------------------
275   // CHECK-NOT: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
276   // CHECK-NOT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
277 }
278 
279 // Verifies that we don't crash when awaiting on an lvalue.
280 // CHECK-LABEL: @_Z11AwaitLValuev(
281 void AwaitLValue() {
282   suspend_always lval;
283   co_await lval;
284 }
285 
286 struct RefTag { };
287 
288 struct AwaitResumeReturnsLValue {
289   bool await_ready();
290   void await_suspend(std::experimental::coroutine_handle<>);
291   RefTag& await_resume();
292 };
293 
294 
295 template<>
296 struct std::experimental::coroutine_traits<void,double> {
297   struct promise_type {
298     void get_return_object();
299     init_susp initial_suspend();
300     final_susp final_suspend() noexcept;
301     void return_void();
302     AwaitResumeReturnsLValue yield_value(int);
303   };
304 };
305 
306 // Verifies that we don't crash when returning an lvalue from an await_resume()
307 // expression.
308 // CHECK-LABEL:  define{{.*}} void @_Z18AwaitReturnsLValued(double %0)
309 void AwaitReturnsLValue(double) {
310   AwaitResumeReturnsLValue a;
311   // CHECK: %[[AVAR:.+]] = alloca %struct.AwaitResumeReturnsLValue,
312   // CHECK: %[[XVAR:.+]] = alloca %struct.RefTag*,
313 
314   // CHECK: %[[YVAR:.+]] = alloca %struct.RefTag*,
315   // CHECK-NEXT: %[[TMP1:.+]] = alloca %struct.AwaitResumeReturnsLValue,
316 
317   // CHECK: %[[TMP_EXPRCLEANUP1:.+]] = alloca %struct.RefTag*,
318   // CHECK: %[[ZVAR:.+]] = alloca %struct.RefTag*,
319   // CHECK-NEXT: %[[TMP2:.+]] = alloca %struct.AwaitResumeReturnsLValue,
320   // CHECK: %[[TMP_EXPRCLEANUP2:.+]] = alloca %struct.RefTag*,
321 
322   // CHECK: %[[RES1:.+]] = call nonnull align 1 dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* {{[^,]*}} %[[AVAR]])
323   // CHECK-NEXT: store %struct.RefTag* %[[RES1]], %struct.RefTag** %[[XVAR]],
324   RefTag& x = co_await a;
325 
326   // CHECK: %[[RES2:.+]] = call nonnull align 1 dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* {{[^,]*}} %[[TMP1]])
327   // CHECK-NEXT: store %struct.RefTag* %[[RES2]], %struct.RefTag** %[[TMP_EXPRCLEANUP1]],
328   // CHECK: %[[LOAD_TMP1:.+]] = load %struct.RefTag*, %struct.RefTag** %[[TMP_EXPRCLEANUP1]],
329   // CHECK: store %struct.RefTag* %[[LOAD_TMP1]], %struct.RefTag** %[[YVAR]],
330 
331   RefTag& y = co_await AwaitResumeReturnsLValue{};
332   // CHECK: %[[RES3:.+]] = call nonnull align 1 dereferenceable({{.*}}) %struct.RefTag* @_ZN24AwaitResumeReturnsLValue12await_resumeEv(%struct.AwaitResumeReturnsLValue* {{[^,]*}} %[[TMP2]])
333   // CHECK-NEXT: store %struct.RefTag* %[[RES3]], %struct.RefTag** %[[TMP_EXPRCLEANUP2]],
334   // CHECK: %[[LOAD_TMP2:.+]] = load %struct.RefTag*, %struct.RefTag** %[[TMP_EXPRCLEANUP2]],
335   // CHECK: store %struct.RefTag* %[[LOAD_TMP2]], %struct.RefTag** %[[ZVAR]],
336   RefTag& z = co_yield 42;
337 }
338 
339 struct TailCallAwait {
340   bool await_ready();
341   std::experimental::coroutine_handle<> await_suspend(std::experimental::coroutine_handle<>);
342   void await_resume();
343 };
344 
345 // CHECK-LABEL: @TestTailcall(
346 extern "C" void TestTailcall() {
347   co_await TailCallAwait{};
348 
349   // CHECK: %[[RESULT:.+]] = call i8* @_ZN13TailCallAwait13await_suspendENSt12experimental16coroutine_handleIvEE(%struct.TailCallAwait*
350   // CHECK: %[[COERCE:.+]] = getelementptr inbounds %"struct.std::experimental::coroutine_handle", %"struct.std::experimental::coroutine_handle"* %[[TMP:.+]], i32 0, i32 0
351   // CHECK: store i8* %[[RESULT]], i8** %[[COERCE]]
352   // CHECK: %[[ADDR:.+]] = call i8* @_ZNSt12experimental16coroutine_handleIvE7addressEv(%"struct.std::experimental::coroutine_handle"* {{[^,]*}} %[[TMP]])
353   // CHECK: call void @llvm.coro.resume(i8* %[[ADDR]])
354 }
355