forked from OSchip/llvm-project
[coroutines] Add emission of initial and final suspends
https://reviews.llvm.org/D31608 llvm-svn: 303603
This commit is contained in:
parent
c46203eaf5
commit
5efc61866d
|
@ -388,7 +388,10 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
|
||||||
|
|
||||||
CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
|
CurCoro.Data->FinalJD = getJumpDestInCurrentScope(FinalBB);
|
||||||
|
|
||||||
// FIXME: Emit initial suspend and more before the body.
|
// FIXME: Emit param moves.
|
||||||
|
|
||||||
|
CurCoro.Data->CurrentAwaitKind = AwaitKind::Init;
|
||||||
|
EmitStmt(S.getInitSuspendStmt());
|
||||||
|
|
||||||
CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
|
CurCoro.Data->CurrentAwaitKind = AwaitKind::Normal;
|
||||||
|
|
||||||
|
@ -410,7 +413,8 @@ void CodeGenFunction::EmitCoroutineBody(const CoroutineBodyStmt &S) {
|
||||||
const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
|
const bool HasCoreturns = CurCoro.Data->CoreturnCount > 0;
|
||||||
if (CanFallthrough || HasCoreturns) {
|
if (CanFallthrough || HasCoreturns) {
|
||||||
EmitBlock(FinalBB);
|
EmitBlock(FinalBB);
|
||||||
// FIXME: Emit final suspend.
|
CurCoro.Data->CurrentAwaitKind = AwaitKind::Final;
|
||||||
|
EmitStmt(S.getFinalSuspendStmt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,17 @@ struct coroutine_handle : coroutine_handle<> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
struct suspend_always {
|
||||||
int stuff;
|
int stuff;
|
||||||
bool await_ready();
|
bool await_ready();
|
||||||
|
@ -32,8 +43,8 @@ template<>
|
||||||
struct std::experimental::coroutine_traits<void> {
|
struct std::experimental::coroutine_traits<void> {
|
||||||
struct promise_type {
|
struct promise_type {
|
||||||
void get_return_object();
|
void get_return_object();
|
||||||
suspend_always initial_suspend();
|
init_susp initial_suspend();
|
||||||
suspend_always final_suspend();
|
final_susp final_suspend();
|
||||||
void return_void();
|
void return_void();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -42,6 +53,13 @@ struct std::experimental::coroutine_traits<void> {
|
||||||
extern "C" void f0() {
|
extern "C" void f0() {
|
||||||
// CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
|
// 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{};
|
co_await suspend_always{};
|
||||||
// See if we need to suspend:
|
// See if we need to suspend:
|
||||||
// --------------------------
|
// --------------------------
|
||||||
|
@ -76,6 +94,13 @@ extern "C" void f0() {
|
||||||
// --------------------------
|
// --------------------------
|
||||||
// CHECK: [[READY_BB]]:
|
// CHECK: [[READY_BB]]:
|
||||||
// CHECK: call void @_ZN14suspend_always12await_resumeEv(%struct.suspend_always* %[[AWAITABLE]])
|
// 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 {
|
struct suspend_maybe {
|
||||||
|
@ -91,8 +116,8 @@ template<>
|
||||||
struct std::experimental::coroutine_traits<void,int> {
|
struct std::experimental::coroutine_traits<void,int> {
|
||||||
struct promise_type {
|
struct promise_type {
|
||||||
void get_return_object();
|
void get_return_object();
|
||||||
suspend_always initial_suspend();
|
init_susp initial_suspend();
|
||||||
suspend_always final_suspend();
|
final_susp final_suspend();
|
||||||
void return_void();
|
void return_void();
|
||||||
suspend_maybe yield_value(int);
|
suspend_maybe yield_value(int);
|
||||||
};
|
};
|
||||||
|
@ -228,3 +253,21 @@ extern "C" void TestOpAwait() {
|
||||||
// CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* %
|
// CHECK: call void @_ZN5MyAggawEv(%struct.MyAgg* %
|
||||||
// CHECK: call void @_ZN11AggrAwaiter12await_resumeEv(%struct.Aggr* sret %
|
// 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*
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,11 @@ void f() {
|
||||||
// CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_typeC1Ev(
|
// CHECK: invoke void @_ZNSt12experimental16coroutine_traitsIJvEE12promise_typeC1Ev(
|
||||||
// CHECK-NEXT: to label %{{.+}} unwind label %[[DeallocPad:.+]]
|
// CHECK-NEXT: to label %{{.+}} unwind label %[[DeallocPad:.+]]
|
||||||
|
|
||||||
|
// CHECK: [[DeallocPad]]:
|
||||||
|
// CHECK-NEXT: landingpad
|
||||||
|
// CHECK-NEXT: cleanup
|
||||||
|
// CHECK: br label %[[Dealloc:.+]]
|
||||||
|
|
||||||
Cleanup cleanup;
|
Cleanup cleanup;
|
||||||
may_throw();
|
may_throw();
|
||||||
|
|
||||||
|
@ -54,11 +59,6 @@ void f() {
|
||||||
// CHECK: invoke void @_Z9may_throwv(
|
// CHECK: invoke void @_Z9may_throwv(
|
||||||
// CHECK-NEXT: to label %{{.+}} unwind label %[[CatchPad:.+]]
|
// CHECK-NEXT: to label %{{.+}} unwind label %[[CatchPad:.+]]
|
||||||
|
|
||||||
// CHECK: [[DeallocPad]]:
|
|
||||||
// CHECK-NEXT: landingpad
|
|
||||||
// CHECK-NEXT: cleanup
|
|
||||||
// CHECK: br label %[[Dealloc:.+]]
|
|
||||||
|
|
||||||
// CHECK: [[CatchPad]]:
|
// CHECK: [[CatchPad]]:
|
||||||
// CHECK-NEXT: landingpad
|
// CHECK-NEXT: landingpad
|
||||||
// CHECK-NEXT: catch i8* null
|
// CHECK-NEXT: catch i8* null
|
||||||
|
|
Loading…
Reference in New Issue