https://gcc.gnu.org/g:8a3acd8cf449636079acb3d1dfcbcabb074b75af

commit r16-1548-g8a3acd8cf449636079acb3d1dfcbcabb074b75af
Author: Iain Sandoe <i...@sandoe.co.uk>
Date:   Mon Jun 16 09:12:29 2025 +0300

    c++, coroutines: Remove use of coroutine handle in the frame.
    
    We have been keeping a copy of coroutine_handle<promise> in the state
    frame, as it was expected to be efficient to use this to initialize the
    argument to await_suspend.  This does not turn out to be the case and
    intializing the value is obstructive to CGW2563 fixes.  This removes
    the use.
    
    gcc/cp/ChangeLog:
    
            * coroutines.cc (struct coroutine_info): Update comments.
            (struct coro_aw_data): Remove self_handle and add in
            information to create the handle in lowering.
            (expand_one_await_expression): Build a temporary coroutine
            handle.
            (build_actor_fn): Remove reference to the frame copy of the
            coroutine handle.
            (cp_coroutine_transform::wrap_original_function_body): Remove
            reference to the frame copy of the coroutine handle.
    
    Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>

Diff:
---
 gcc/cp/coroutines.cc | 62 +++++++++++++++++++++++-----------------------------
 1 file changed, 27 insertions(+), 35 deletions(-)

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index f97bd9deae33..a0d155b2b8b9 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -206,11 +206,10 @@ struct GTY((for_user)) coroutine_info
   tree traits_type;   /* The cached traits type for this function.  */
   tree handle_type;   /* The cached coroutine handle for this function.  */
   tree self_h_proxy;  /* A handle instance that is used as the proxy for the
-                        one that will eventually be allocated in the coroutine
-                        frame.  */
+                        one that will eventually be built in lowering.  */
   tree promise_proxy; /* Likewise, a proxy promise instance.  */
-  tree from_address;  /* handle_type from_address function.  */
-  tree return_void;   /* The expression for p.return_void() if it exists.  */
+  tree from_address;  /* handle_type from_address() function.  */
+  tree return_void;   /* The expression for p.return_void(), if it exists.  */
   location_t first_coro_keyword; /* The location of the keyword that made this
                                    function into a coroutine.  */
 
@@ -1982,12 +1981,13 @@ struct coro_aw_data
   tree coro_fp;    /* Frame pointer var.  */
   tree resume_idx; /* This is the index var in the frame.  */
   tree i_a_r_c;    /* initial suspend await_resume() was called if true.  */
-  tree self_h;     /* This is a handle to the current coro (frame var).  */
   tree cleanup;    /* This is where to go once we complete local destroy.  */
   tree cororet;    /* This is where to go if we suspend.  */
   tree corocont;   /* This is where to go if we continue.  */
   tree dispatch;   /* This is where we go if we restart the dispatch.  */
   tree conthand;   /* This is the handle for a continuation.  */
+  tree handle_type; /* Handle type for this coroutine...  */
+  tree hfa_m;       /* ... and handle.from_address() for this.  */
   unsigned index;  /* This is our current resume index.  */
 };
 
@@ -2105,6 +2105,18 @@ expand_one_await_expression (tree *expr, tree 
*await_expr, void *d)
 
   tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend().  */
   tree susp_type = TREE_TYPE (suspend);
+  tree susp_call = suspend;
+  if (TREE_CODE (suspend) == TARGET_EXPR)
+    susp_call = TARGET_EXPR_INITIAL (suspend);
+  gcc_checking_assert (TREE_CODE (susp_call) == CALL_EXPR);
+  tree dummy_ch = build_dummy_object (data->handle_type);
+  r = fold_convert (build_pointer_type (void_type_node), data->coro_fp);
+  vec<tree, va_gc> *args = make_tree_vector_single (r);
+  tree hfa = cp_fold_rvalue (
+    build_new_method_call (dummy_ch, data->hfa_m, &args, NULL_TREE,
+                          LOOKUP_NORMAL, NULL, tf_warning_or_error));
+  release_tree_vector (args);
+  CALL_EXPR_ARG (susp_call, call_expr_nargs (susp_call) - 1) = hfa;
 
   bool is_cont = false;
   /* NOTE: final suspend can't resume; the "resume" label in that case
@@ -2586,22 +2598,6 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   /* Now we start building the rewritten function body.  */
   add_stmt (build_stmt (loc, LABEL_EXPR, actor_begin_label));
 
-  /* actor's coroutine 'self handle'.  */
-  tree ash = coro_build_frame_access_expr (actor_frame, coro_self_handle_id,
-                                          false, tf_warning_or_error);
-  /* So construct the self-handle from the frame address.  */
-  tree hfa_m = get_coroutine_from_address (orig);
-  /* Should have been set earlier by coro_promise_type_found_p.  */
-  gcc_assert (hfa_m);
-
-  tree r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), 
actor_fp);
-  vec<tree, va_gc> *args = make_tree_vector_single (r);
-  tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, 
LOOKUP_NORMAL,
-                                   NULL, tf_warning_or_error);
-  r = cp_build_init_expr (ash, hfa);
-  finish_expr_stmt (r);
-  release_tree_vector (args);
-
   /* Now we know the real promise, and enough about the frame layout to
      decide where to put things.  */
 
@@ -2616,7 +2612,7 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   add_stmt (fnbody);
 
   /* Now do the tail of the function; first cleanups.  */
-  r = build_stmt (loc, LABEL_EXPR, del_promise_label);
+  tree r = build_stmt (loc, LABEL_EXPR, del_promise_label);
   add_stmt (r);
 
   /* Destructors for the things we built explicitly.
@@ -2684,6 +2680,12 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
   gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
   add_stmt (r);
 
+  /* How to construct the handle for this coroutine from the frame address.  */
+  tree hfa_m = get_coroutine_from_address (orig);
+  /* Should have been set earlier by coro_promise_type_found_p.  */
+  gcc_assert (hfa_m);
+  tree handle_type = TREE_TYPE (get_coroutine_self_handle_proxy (orig));
+
   /* We've now rewritten the tree and added the initial and final
      co_awaits.  Now pass over the tree and expand the co_awaits.  */
   tree i_a_r_c = NULL_TREE;
@@ -2692,8 +2694,9 @@ build_actor_fn (location_t loc, tree coro_frame_type, 
tree actor, tree fnbody,
                                           false, tf_warning_or_error);
 
   coro_aw_data data = {actor, actor_fp, resume_idx_var, i_a_r_c,
-                      ash, del_promise_label, ret_label,
-                      continue_label, restart_dispatch_label, continuation, 2};
+                      del_promise_label, ret_label,
+                      continue_label, restart_dispatch_label, continuation,
+                      handle_type, hfa_m, 2};
   cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
 
   BIND_EXPR_BODY (actor_bind) = pop_stmt_list (actor_body);
@@ -4424,16 +4427,6 @@ cp_coroutine_transform::wrap_original_function_body ()
   var_list = promise;
   add_decl_expr (promise);
 
-  /* We need a handle to this coroutine, which is passed to every
-     await_suspend().  This was created on demand when parsing we now link it
-     into our scope.  */
-  var = get_coroutine_self_handle_proxy (orig_fn_decl);
-  DECL_CONTEXT (var) = orig_fn_decl;
-  DECL_SOURCE_LOCATION (var) = loc;
-  DECL_CHAIN (var) = var_list;
-  var_list = var;
-  add_decl_expr (var);
-
   /* If we have function parms, then these will be copied to the coroutine
      frame as per [dcl.fct.def.coroutine] / 13.
      Here, we create a local (proxy) variable for each parm, since the original
@@ -5285,7 +5278,6 @@ cp_coroutine_transform::~cp_coroutine_transform ()
   bool _Coro_frame_needs_free; free the coro frame mem if set.
   bool _Coro_i_a_r_c; [dcl.fct.def.coroutine] / 5.3
   short _Coro_resume_index;
-  handle_type _Coro_self_handle;
   parameter copies (were required).
   local variables saved (including awaitables)
   (maybe) trailing space.

Reply via email to