GorNishanov updated this revision to Diff 93889.
GorNishanov added a comment.

Added a CHECK that for a final suspend we correctly set "IsFinalSuspend" 
argument of @llvm.coro.suspend


https://reviews.llvm.org/D31608

Files:
  lib/CodeGen/CGCoroutine.cpp
  test/CodeGenCoroutines/coro-await.cpp
  test/CodeGenCoroutines/coro-cleanup.cpp

Index: test/CodeGenCoroutines/coro-cleanup.cpp
===================================================================
--- test/CodeGenCoroutines/coro-cleanup.cpp
+++ test/CodeGenCoroutines/coro-cleanup.cpp
@@ -6,27 +6,27 @@
 
 template <class Promise = void> struct coroutine_handle {
   coroutine_handle() = default;
-  static coroutine_handle from_address(void *) { return {}; }
+  static coroutine_handle from_address(void *) noexcept;
 };
 template <> struct coroutine_handle<void> {
-  static coroutine_handle from_address(void *) { return {}; }
+  static coroutine_handle from_address(void *) noexcept;
   coroutine_handle() = default;
   template <class PromiseType>
   coroutine_handle(coroutine_handle<PromiseType>) {}
 };
 }
 
 struct suspend_always {
-  bool await_ready();
-  void await_suspend(std::experimental::coroutine_handle<>);
-  void await_resume();
+  bool await_ready() noexcept;
+  void await_suspend(std::experimental::coroutine_handle<>) noexcept;
+  void await_resume() noexcept;
 };
 
 template <> struct std::experimental::coroutine_traits<void> {
   struct promise_type {
     void get_return_object();
-    suspend_always initial_suspend();
-    suspend_always final_suspend();
+    suspend_always initial_suspend() noexcept;
+    suspend_always final_suspend() noexcept;
     void return_void();
     promise_type();
     ~promise_type();
@@ -46,19 +46,19 @@
   // CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_typeC1Ev(
   // CHECK-NEXT: to label %{{.+}} unwind label %[[DeallocPad:.+]]
 
+  // CHECK: [[DeallocPad]]:
+  // CHECK-NEXT: landingpad
+  // CHECK-NEXT:   cleanup
+  // CHECK: br label %[[Dealloc:.+]]
+
   Cleanup cleanup;
   may_throw();
 
   // if may_throw throws, check that we destroy the promise and free the memory.
 
   // CHECK: invoke void @_Z9may_throwv(
   // CHECK-NEXT: to label %{{.+}} unwind label %[[PromDtorPad:.+]]
 
-  // CHECK: [[DeallocPad]]:
-  // CHECK-NEXT: landingpad
-  // CHECK-NEXT:   cleanup
-  // CHECK: br label %[[Dealloc:.+]]
-
   // CHECK: [[PromDtorPad]]:
   // CHECK-NEXT: landingpad
   // CHECK-NEXT:   cleanup
Index: test/CodeGenCoroutines/coro-await.cpp
===================================================================
--- test/CodeGenCoroutines/coro-await.cpp
+++ test/CodeGenCoroutines/coro-await.cpp
@@ -21,6 +21,17 @@
 }
 }
 
+struct init_susp {
+  bool await_ready();
+  void await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
+struct final_susp {
+  bool await_ready();
+  void await_suspend(std::experimental::coroutine_handle<>);
+  void await_resume();
+};
+
 struct suspend_always {
   int stuff;
   bool await_ready();
@@ -32,16 +43,23 @@
 struct std::experimental::coroutine_traits<void> {
   struct promise_type {
     void get_return_object();
-    suspend_always initial_suspend();
-    suspend_always final_suspend();
+    init_susp initial_suspend();
+    final_susp final_suspend();
     void return_void();
   };
 };
 
 // CHECK-LABEL: f0(
 extern "C" void f0() {
   // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
 
+  // See if initial_suspend was issued:
+  // ----------------------------------
+  // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
+  // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(%struct.init_susp*
+  // CHECK: %[[INITSP_ID:.+]] = call token @llvm.coro.save(
+  // CHECK: call i8 @llvm.coro.suspend(token %[[INITSP_ID]], i1 false)
+
   co_await suspend_always{};
   // See if we need to suspend:
   // --------------------------
@@ -60,6 +78,7 @@
   // CHECK: %[[CH:.+]] = load i8*, i8** %{{.+}}
   // CHECK: call void @_ZN14suspend_always13await_suspendENSt12experimental16coroutine_handleIvEE(%struct.suspend_always* %[[AWAITABLE]], i8* %[[CH]])
   // -------------------------
+
   // Generate a suspend point:
   // -------------------------
   // CHECK: %[[OUTCOME:.+]] = call i8 @llvm.coro.suspend(token %[[SUSPEND_ID]], i1 false)
@@ -76,6 +95,13 @@
   // --------------------------
   // CHECK: [[READY_BB]]:
   // CHECK:  call void @_ZN14suspend_always12await_resumeEv(%struct.suspend_always* %[[AWAITABLE]])
+
+  // See if final_suspend was issued:
+  // ----------------------------------
+  // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
+  // CHECK-NEXT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
+  // CHECK: %[[FINALSP_ID:.+]] = call token @llvm.coro.save(
+  // CHECK: call i8 @llvm.coro.suspend(token %[[FINALSP_ID]], i1 true)
 }
 
 struct suspend_maybe {
@@ -91,8 +117,8 @@
 struct std::experimental::coroutine_traits<void,int> {
   struct promise_type {
     void get_return_object();
-    suspend_always initial_suspend();
-    suspend_always final_suspend();
+    init_susp initial_suspend();
+    final_susp final_suspend();
     void return_void();
     suspend_maybe yield_value(int);
   };
@@ -228,3 +254,21 @@
   // CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* %
   // CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret %
 }
+
+// CHECK-LABEL: EndlessLoop(
+extern "C" void EndlessLoop() {
+  // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+
+  // See if initial_suspend was issued:
+  // ----------------------------------
+  // CHECK: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type15initial_suspendEv(
+  // CHECK-NEXT: call zeroext i1 @_ZN9init_susp11await_readyEv(%struct.init_susp*
+
+  for (;;)
+    co_await suspend_always{};
+
+  // Verify that final_suspend was NOT issued:
+  // ----------------------------------
+  // CHECK-NOT: call void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_type13final_suspendEv(
+  // CHECK-NOT: call zeroext i1 @_ZN10final_susp11await_readyEv(%struct.final_susp*
+}
Index: lib/CodeGen/CGCoroutine.cpp
===================================================================
--- lib/CodeGen/CGCoroutine.cpp
+++ lib/CodeGen/CGCoroutine.cpp
@@ -338,8 +338,11 @@
     EmitStmt(S.getPromiseDeclStmt());
 
     CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
+    // FIXME: Emit param moves and gro initialization.
 
-    // FIXME: Emit initial suspend and more before the body.
+
+    CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
+    EmitStmt(S.getInitSuspendStmt());
 
     CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
     EmitStmt(S.getBody());
@@ -349,7 +352,8 @@
     const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
     if (CanFallthrough || HasCoreturns) {
       EmitBlock(FinalBB);
-      // FIXME: Emit final suspend.
+      CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
+      EmitStmt(S.getFinalSuspendStmt());
     }
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to