Re: [PATCH] coroutines: Collect the function body rewrite code.
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.
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