Re: [PATCH] coroutines: Collect the function body rewrite code.

2020-06-29 Thread Nathan Sidwell

On 6/27/20 4:13 PM, Iain Sandoe wrote:

Hi,

This is a enabler patch that enables a reasonable approach to
fixing 5 reported PRs (it doesn’t fix anything in its own right).

It has been tested on x86_64-linux, darwin, powerpc64-linux
OK for master / 10.2?
thanks
Iain


OK, yes it was quite a slippery target to hit!



--

The standard describes a rewrite of the body of the user-authored
function (which wraps it in a try-catch block and provides the
initial and final suspend expressions).  The exact arrangement of
this was still in flux right up until the WG21 meeting in Prague and
as a consequence was a bit of a moving target.

The net result was a fragmented implementation of the parts of
this rewrite which is now impeding progress in fixing other issues.

This patch collates the rewrite action into a single function and
carries this out earlier.

gcc/cp/ChangeLog:

* coroutines.cc (expand_one_await_expression): Remove
code dealing with initial suspend.
(build_actor_fn): Remove code special-casing initial
and final suspend. Handle the final suspend and marking
of the coroutine as done.
(coro_rewrite_function_body): New.
(bind_expr_find_in_subtree): Remove.
(coro_body_contains_bind_expr_p): Remove.
(morph_fn_to_coro): Split the rewrite of the original
function into coro_rewrite_function_body and call it.
---
  gcc/cp/coroutines.cc | 534 +--
  1 file changed, 208 insertions(+), 326 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 54f9cb3b4e4..8e0f0e09b56 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1573,8 +1573,6 @@ expand_one_await_expression (tree *stmt, tree 
*await_expr, void *d)
tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
  
tree source = TREE_OPERAND (saved_co_await, 4);

-  bool is_initial =
-(source && TREE_INT_CST_LOW (source) == (int) INITIAL_SUSPEND_POINT);
bool is_final = (source
   && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
@@ -1724,16 +1722,6 @@ expand_one_await_expression (tree *stmt, tree 
*await_expr, void *d)
resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
append_to_statement_list (resume_label, _list);
  
-  if (is_initial)

-{
-  /* Note that we are about to execute the await_resume() for the initial
-await expression.  */
-  r = build2_loc (loc, MODIFY_EXPR, boolean_type_node, data->i_a_r_c,
- boolean_true_node);
-  r = coro_build_cvt_void_expr_stmt (r, loc);
-  append_to_statement_list (r, _list);
-}
-
/* This will produce the value (if one is provided) from the co_await
   expression.  */
tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume().  */
@@ -2102,19 +2090,16 @@ static void
  build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
tree orig, hash_map *param_uses,
hash_map *local_var_uses,
-   vec *param_dtor_list, tree initial_await,
-   tree final_await, unsigned body_count, tree frame_size)
+   vec *param_dtor_list,
+   tree fs_label, tree resume_fn_field,
+   unsigned body_count, tree frame_size)
  {
verify_stmt_tree (fnbody);
/* Some things we inherit from the original function.  */
-  tree coro_frame_ptr = build_pointer_type (coro_frame_type);
tree handle_type = get_coroutine_handle_type (orig);
tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
tree promise_type = get_coroutine_promise_type (orig);
tree promise_proxy = get_coroutine_promise_proxy (orig);
-  tree act_des_fn_type
-= build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
-  tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
  
/* One param, the coro frame pointer.  */

tree actor_fp = DECL_ARGUMENTS (actor);
@@ -2145,21 +2130,15 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
DECL_CONTEXT (continuation) = actor;
BIND_EXPR_VARS (actor_bind) = continuation;
  
-  /* Update the block associated with the outer scope of the orig fn.  */

+  /* Link in the block associated with the outer scope of the re-written
+ function body.  */
tree first = expr_first (fnbody);
-  if (first && TREE_CODE (first) == BIND_EXPR)
-{
-  /* We will discard this, since it's connected to the original scope
-nest.  */
-  tree block = BIND_EXPR_BLOCK (first);
-  if (block) /* For this to be missing is probably a bug.  */
-   {
- gcc_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
- gcc_assert (BLOCK_CHAIN (block) == NULL_TREE);
- BLOCK_SUPERCONTEXT (block) = top_block;
- BLOCK_SUBBLOCKS (top_block) = block;
-   }
-}
+  gcc_checking_assert 

[PATCH] coroutines: Collect the function body rewrite code.

2020-06-27 Thread Iain Sandoe
Hi,

This is a enabler patch that enables a reasonable approach to
fixing 5 reported PRs (it doesn’t fix anything in its own right).

It has been tested on x86_64-linux, darwin, powerpc64-linux
OK for master / 10.2?
thanks
Iain

--

The standard describes a rewrite of the body of the user-authored
function (which wraps it in a try-catch block and provides the
initial and final suspend expressions).  The exact arrangement of
this was still in flux right up until the WG21 meeting in Prague and
as a consequence was a bit of a moving target.

The net result was a fragmented implementation of the parts of
this rewrite which is now impeding progress in fixing other issues.

This patch collates the rewrite action into a single function and
carries this out earlier.

gcc/cp/ChangeLog:

* coroutines.cc (expand_one_await_expression): Remove
code dealing with initial suspend.
(build_actor_fn): Remove code special-casing initial
and final suspend. Handle the final suspend and marking
of the coroutine as done.
(coro_rewrite_function_body): New.
(bind_expr_find_in_subtree): Remove.
(coro_body_contains_bind_expr_p): Remove.
(morph_fn_to_coro): Split the rewrite of the original
function into coro_rewrite_function_body and call it.
---
 gcc/cp/coroutines.cc | 534 +--
 1 file changed, 208 insertions(+), 326 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 54f9cb3b4e4..8e0f0e09b56 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1573,8 +1573,6 @@ expand_one_await_expression (tree *stmt, tree 
*await_expr, void *d)
   tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
 
   tree source = TREE_OPERAND (saved_co_await, 4);
-  bool is_initial =
-(source && TREE_INT_CST_LOW (source) == (int) INITIAL_SUSPEND_POINT);
   bool is_final = (source
   && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
   bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
@@ -1724,16 +1722,6 @@ expand_one_await_expression (tree *stmt, tree 
*await_expr, void *d)
   resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
   append_to_statement_list (resume_label, _list);
 
-  if (is_initial)
-{
-  /* Note that we are about to execute the await_resume() for the initial
-await expression.  */
-  r = build2_loc (loc, MODIFY_EXPR, boolean_type_node, data->i_a_r_c,
- boolean_true_node);
-  r = coro_build_cvt_void_expr_stmt (r, loc);
-  append_to_statement_list (r, _list);
-}
-
   /* This will produce the value (if one is provided) from the co_await
  expression.  */
   tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume().  */
@@ -2102,19 +2090,16 @@ static void
 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
tree orig, hash_map *param_uses,
hash_map *local_var_uses,
-   vec *param_dtor_list, tree initial_await,
-   tree final_await, unsigned body_count, tree frame_size)
+   vec *param_dtor_list,
+   tree fs_label, tree resume_fn_field,
+   unsigned body_count, tree frame_size)
 {
   verify_stmt_tree (fnbody);
   /* Some things we inherit from the original function.  */
-  tree coro_frame_ptr = build_pointer_type (coro_frame_type);
   tree handle_type = get_coroutine_handle_type (orig);
   tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
   tree promise_type = get_coroutine_promise_type (orig);
   tree promise_proxy = get_coroutine_promise_proxy (orig);
-  tree act_des_fn_type
-= build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
-  tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
 
   /* One param, the coro frame pointer.  */
   tree actor_fp = DECL_ARGUMENTS (actor);
@@ -2145,21 +2130,15 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   DECL_CONTEXT (continuation) = actor;
   BIND_EXPR_VARS (actor_bind) = continuation;
 
-  /* Update the block associated with the outer scope of the orig fn.  */
+  /* Link in the block associated with the outer scope of the re-written
+ function body.  */
   tree first = expr_first (fnbody);
-  if (first && TREE_CODE (first) == BIND_EXPR)
-{
-  /* We will discard this, since it's connected to the original scope
-nest.  */
-  tree block = BIND_EXPR_BLOCK (first);
-  if (block) /* For this to be missing is probably a bug.  */
-   {
- gcc_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
- gcc_assert (BLOCK_CHAIN (block) == NULL_TREE);
- BLOCK_SUPERCONTEXT (block) = top_block;
- BLOCK_SUBBLOCKS (top_block) = block;
-   }
-}
+  gcc_checking_assert (first && TREE_CODE (first) == BIND_EXPR);
+  tree block = BIND_EXPR_BLOCK (first);
+  gcc_checking_assert