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