coro-await.cpp 12 KB

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