aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-propagate.c
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-03-26 21:00:25 +0000
committerIain Sandoe <iain@sandoe.co.uk>2020-03-26 21:01:13 +0000
commit6d85947d23ab6a9b9975b2e0590db9308c5c1b07 (patch)
treeba421ba3fb1f1de402d5695da8edd6f19f2bb16d /gcc/tree-ssa-propagate.c
parent2a1f0f64160e078e23795901ff98575805d6875b (diff)
downloadgcc-6d85947d23ab6a9b9975b2e0590db9308c5c1b07.zip
gcc-6d85947d23ab6a9b9975b2e0590db9308c5c1b07.tar.gz
gcc-6d85947d23ab6a9b9975b2e0590db9308c5c1b07.tar.bz2
coroutines: Implement n4849 recommended symmetric transfer.
Although the note in the text [expr.await] / 5.1.1 is not normative, it is asserted by users that an implementation that is unable to perform unlimited symmetric transfers is not terribly useful. This relates to the following circumstance: try { users-function-body: { .... { some suspend context continuation_handle = await_suspend (another handle); continuation_handle.resume (); 'return' (actually a suspension operation). } } } catch (...) {} The call to 'continuation_handle.resume ()' needs to be a tail- call in order that an arbitrary number of coroutines can be handled in this manner. There are two issues with this: 1. That the user's function body is wrapped in a try/catch block and one cannot tail-call from within those. 2. That GCC doesn't usually produce tail-calls when the optimisation level is < O2. After considerable discussion at WG21 meetings, it has been determined that the intent is that the operation behaves as if the resume call is executed in the context of the caller. So, we can remap the fragment above like this: { void_coroutine_handle continuation; try { users-function-body: { .... { some suspend context continuation = await_suspend (another handle); <scope exit without cleanup> symmetric_transfer; } } } catch (...) {} symmetric_transfer: continuation.resume(); [tail call] [must tail call] } Thus we take the call outside the try-catch block which solves issue (1) and mark it as a tail call and as "must tail call" for correctness which solves (2). As bonuses, since we no longer need to differentiate handle types returned from await_suspend() methods, nor do we need to keep them in the coroutine frame, since they are ephemeral, we save entries in the frame and reduce some code too. gcc/cp/ChangeLog: 2020-03-26 Iain Sandoe <iain@sandoe.co.uk> * coroutines.cc (coro_init_identifiers): Initialize an identifier for the cororoutine handle 'address' method name. (struct coro_aw_data): Add fields to cover the continuations. (co_await_expander): Determine the kind of await_suspend in use. If we have the case that returns a continuation handle, then save this and make the target for 'scope exit without cleanup' be the continuation resume label. (expand_co_awaits): Remove. (struct suspend_point_info): Remove fields that kept the returned await_suspend handle type. (transform_await_expr): Remove code tracking continuation handles. (build_actor_fn): Add the continuation handle as an actor-function scope var. Build the symmetric transfer continuation point. Call the tree walk for co_await expansion directly, rather than via a trivial shim function. (register_await_info): Remove fields tracking continuation handles. (get_await_suspend_return_type): Remove. (register_awaits): Remove code tracking continuation handles. (morph_fn_to_coro): Remove code tracking continuation handles. gcc/testsuite/ChangeLog: 2020-03-26 Iain Sandoe <iain@sandoe.co.uk> * g++.dg/coroutines/torture/co-ret-09-bool-await-susp.C: Amend to n4849 behaviour. * g++.dg/coroutines/torture/symmetric-transfer-00-basic.C: New test.
Diffstat (limited to 'gcc/tree-ssa-propagate.c')
0 files changed, 0 insertions, 0 deletions