1 /* coroutine-specific state, expansions and tests.
3 Copyright (C) 2018-2020 Free Software Foundation, Inc.
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
28 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
33 #include "gcc-rich-location.h"
36 static bool coro_promise_type_found_p (tree
, location_t
);
38 /* GCC C++ coroutines implementation.
40 The user authors a function that becomes a coroutine (lazily) by
41 making use of any of the co_await, co_yield or co_return keywords.
43 Unlike a regular function, where the activation record is placed on the
44 stack, and is destroyed on function exit, a coroutine has some state that
45 persists between calls - the coroutine frame (analogous to a stack frame).
47 We transform the user's function into three pieces:
48 1. A so-called ramp function, that establishes the coroutine frame and
49 begins execution of the coroutine.
50 2. An actor function that contains the state machine corresponding to the
51 user's suspend/resume structure.
52 3. A stub function that calls the actor function in 'destroy' mode.
54 The actor function is executed:
55 * from "resume point 0" by the ramp.
56 * from resume point N ( > 0 ) for handle.resume() calls.
57 * from the destroy stub for destroy point N for handle.destroy() calls.
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
62 The C++ coroutine design makes use of some helper functions that are
63 authored in a so-called "promise" class provided by the user.
65 At parse time (or post substitution) the type of the coroutine promise
66 will be determined. At that point, we can look up the required promise
67 class methods and issue diagnostics if they are missing or incorrect. To
68 avoid repeating these actions at code-gen time, we make use of temporary
69 'proxy' variables for the coroutine handle and the promise - which will
70 eventually be instantiated in the coroutine frame.
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
79 /* The state that we collect during parsing (and template expansion) for
82 struct GTY((for_user
)) coroutine_info
84 tree function_decl
; /* The original function decl. */
85 tree promise_type
; /* The cached promise type for this function. */
86 tree handle_type
; /* The cached coroutine handle for this function. */
87 tree self_h_proxy
; /* A handle instance that is used as the proxy for the
88 one that will eventually be allocated in the coroutine
90 tree promise_proxy
; /* Likewise, a proxy promise instance. */
91 location_t first_coro_keyword
; /* The location of the keyword that made this
92 function into a coroutine. */
93 /* Flags to avoid repeated errors for per-function issues. */
94 bool coro_ret_type_error_emitted
;
95 bool coro_promise_error_emitted
;
98 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
100 typedef tree compare_type
; /* We only compare the function decl. */
101 static inline hashval_t
hash (coroutine_info
*);
102 static inline hashval_t
hash (const compare_type
&);
103 static inline bool equal (coroutine_info
*, coroutine_info
*);
104 static inline bool equal (coroutine_info
*, const compare_type
&);
107 /* This table holds all the collected coroutine state for coroutines in
108 the current translation unit. */
110 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
112 /* We will initialise state lazily. */
113 static bool coro_initialized
= false;
115 /* Return a hash value for the entry pointed to by INFO.
116 The compare type is a tree, but the only trees we are going use are
117 function decls. We use the DECL_UID as the hash value since that is
118 stable across PCH. */
121 coroutine_info_hasher::hash (coroutine_info
*info
)
123 return DECL_UID (info
->function_decl
);
126 /* Return a hash value for the compare value COMP. */
129 coroutine_info_hasher::hash (const compare_type
& comp
)
131 return DECL_UID (comp
);
134 /* Return true if the entries pointed to by LHS and RHS are for the
138 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
140 return lhs
->function_decl
== rhs
->function_decl
;
144 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
146 return lhs
->function_decl
== rhs
;
149 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
150 entry does not yet exist. */
153 get_or_insert_coroutine_info (tree fn_decl
)
155 gcc_checking_assert (coroutine_info_table
!= NULL
);
157 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
158 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
162 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
163 (*slot
)->function_decl
= fn_decl
;
169 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
172 get_coroutine_info (tree fn_decl
)
174 if (coroutine_info_table
== NULL
)
177 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
178 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
184 /* We will lazily create all the identifiers that are used by coroutines
185 on the first attempt to lookup the traits. */
187 /* Identifiers that are used by all coroutines. */
189 static GTY(()) tree coro_traits_identifier
;
190 static GTY(()) tree coro_handle_identifier
;
191 static GTY(()) tree coro_promise_type_identifier
;
193 /* Required promise method name identifiers. */
195 static GTY(()) tree coro_await_transform_identifier
;
196 static GTY(()) tree coro_initial_suspend_identifier
;
197 static GTY(()) tree coro_final_suspend_identifier
;
198 static GTY(()) tree coro_return_void_identifier
;
199 static GTY(()) tree coro_return_value_identifier
;
200 static GTY(()) tree coro_yield_value_identifier
;
201 static GTY(()) tree coro_resume_identifier
;
202 static GTY(()) tree coro_address_identifier
;
203 static GTY(()) tree coro_from_address_identifier
;
204 static GTY(()) tree coro_get_return_object_identifier
;
205 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
206 static GTY(()) tree coro_unhandled_exception_identifier
;
208 /* Awaitable methods. */
210 static GTY(()) tree coro_await_ready_identifier
;
211 static GTY(()) tree coro_await_suspend_identifier
;
212 static GTY(()) tree coro_await_resume_identifier
;
214 /* Create the identifiers used by the coroutines library interfaces. */
217 coro_init_identifiers ()
219 coro_traits_identifier
= get_identifier ("coroutine_traits");
220 coro_handle_identifier
= get_identifier ("coroutine_handle");
221 coro_promise_type_identifier
= get_identifier ("promise_type");
223 coro_await_transform_identifier
= get_identifier ("await_transform");
224 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
225 coro_final_suspend_identifier
= get_identifier ("final_suspend");
226 coro_return_void_identifier
= get_identifier ("return_void");
227 coro_return_value_identifier
= get_identifier ("return_value");
228 coro_yield_value_identifier
= get_identifier ("yield_value");
229 coro_resume_identifier
= get_identifier ("resume");
230 coro_address_identifier
= get_identifier ("address");
231 coro_from_address_identifier
= get_identifier ("from_address");
232 coro_get_return_object_identifier
= get_identifier ("get_return_object");
233 coro_gro_on_allocation_fail_identifier
=
234 get_identifier ("get_return_object_on_allocation_failure");
235 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
237 coro_await_ready_identifier
= get_identifier ("await_ready");
238 coro_await_suspend_identifier
= get_identifier ("await_suspend");
239 coro_await_resume_identifier
= get_identifier ("await_resume");
242 /* Trees we only need to set up once. */
244 static GTY(()) tree coro_traits_templ
;
245 static GTY(()) tree coro_handle_templ
;
246 static GTY(()) tree void_coro_handle_type
;
248 /* ================= Parse, Semantics and Type checking ================= */
250 /* This initial set of routines are helper for the parsing and template
253 At the completion of this, we will have completed trees for each of the
254 keywords, but making use of proxy variables for the self-handle and the
255 promise class instance. */
257 /* [coroutine.traits]
258 Lookup the coroutine_traits template decl. */
261 find_coro_traits_template_decl (location_t kw
)
263 /* If we are missing fundmental information, such as the traits, (or the
264 declaration found is not a type template), then don't emit an error for
265 every keyword in a TU, just do it once. */
266 static bool traits_error_emitted
= false;
268 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
270 /*complain=*/!traits_error_emitted
);
271 if (traits_decl
== error_mark_node
272 || !DECL_TYPE_TEMPLATE_P (traits_decl
))
274 if (!traits_error_emitted
)
276 gcc_rich_location
richloc (kw
);
277 error_at (&richloc
, "coroutines require a traits template; cannot"
278 " find %<%E::%E%>", std_node
, coro_traits_identifier
);
279 inform (&richloc
, "perhaps %<#include <coroutine>%> is missing");
280 traits_error_emitted
= true;
288 /* Instantiate Coroutine traits for the function signature. */
291 instantiate_coro_traits (tree fndecl
, location_t kw
)
293 /* [coroutine.traits.primary]
294 So now build up a type list for the template <typename _R, typename...>.
295 The types are the function's arg types and _R is the function return
298 tree functyp
= TREE_TYPE (fndecl
);
299 tree arg
= DECL_ARGUMENTS (fndecl
);
300 bool lambda_p
= LAMBDA_FUNCTION_P (fndecl
);
301 tree arg_node
= TYPE_ARG_TYPES (functyp
);
302 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
305 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
307 /* See PR94807, as to why we must exclude lambda here. */
308 if (is_this_parameter (arg
) && !lambda_p
)
310 /* We pass a reference to *this to the param preview. */
311 tree ct
= TREE_TYPE (TREE_TYPE (arg
));
312 TREE_VEC_ELT (argtypes
, p
++) = cp_build_reference_type (ct
, false);
315 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
317 arg_node
= TREE_CHAIN (arg_node
);
318 arg
= DECL_CHAIN (arg
);
321 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
322 SET_ARGUMENT_PACK_ARGS (argtypepack
, argtypes
);
324 tree targ
= make_tree_vec (2);
325 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
326 TREE_VEC_ELT (targ
, 1) = argtypepack
;
329 = lookup_template_class (coro_traits_templ
, targ
,
330 /*in_decl=*/NULL_TREE
, /*context=*/NULL_TREE
,
331 /*entering scope=*/false, tf_warning_or_error
);
333 if (traits_class
== error_mark_node
)
335 error_at (kw
, "cannot instantiate %<coroutine traits%>");
342 /* [coroutine.handle] */
345 find_coro_handle_template_decl (location_t kw
)
347 /* As for the coroutine traits, this error is per TU, so only emit
349 static bool coro_handle_error_emitted
= false;
350 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
351 0, !coro_handle_error_emitted
);
352 if (handle_decl
== error_mark_node
353 || !DECL_CLASS_TEMPLATE_P (handle_decl
))
355 if (!coro_handle_error_emitted
)
356 error_at (kw
, "coroutines require a handle class template;"
357 " cannot find %<%E::%E%>", std_node
, coro_handle_identifier
);
358 coro_handle_error_emitted
= true;
365 /* Instantiate the handle template for a given promise type. */
368 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
370 /* So now build up a type list for the template, one entry, the promise. */
371 tree targ
= make_tree_vec (1);
372 TREE_VEC_ELT (targ
, 0) = promise_type
;
374 = lookup_template_class (coro_handle_identifier
, targ
,
375 /* in_decl=*/NULL_TREE
,
376 /* context=*/std_node
,
377 /* entering scope=*/false, tf_warning_or_error
);
379 if (handle_type
== error_mark_node
)
381 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
382 " promise type %qT", promise_type
);
389 /* Look for the promise_type in the instantiated traits. */
392 find_promise_type (tree traits_class
)
395 = lookup_member (traits_class
, coro_promise_type_identifier
,
396 /* protect=*/1, /*want_type=*/true, tf_warning_or_error
);
400 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
402 /* NULL_TREE on fail. */
407 coro_promise_type_found_p (tree fndecl
, location_t loc
)
409 gcc_assert (fndecl
!= NULL_TREE
);
411 if (!coro_initialized
)
413 /* Trees we only need to create once.
414 Set up the identifiers we will use. */
415 coro_init_identifiers ();
417 /* Coroutine traits template. */
418 coro_traits_templ
= find_coro_traits_template_decl (loc
);
419 if (coro_traits_templ
== NULL_TREE
)
422 /* coroutine_handle<> template. */
423 coro_handle_templ
= find_coro_handle_template_decl (loc
);
424 if (coro_handle_templ
== NULL_TREE
)
427 /* We can also instantiate the void coroutine_handle<> */
428 void_coro_handle_type
=
429 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
430 if (void_coro_handle_type
== NULL_TREE
)
433 /* A table to hold the state, per coroutine decl. */
434 gcc_checking_assert (coroutine_info_table
== NULL
);
435 coroutine_info_table
=
436 hash_table
<coroutine_info_hasher
>::create_ggc (11);
438 if (coroutine_info_table
== NULL
)
441 coro_initialized
= true;
444 /* Save the coroutine data on the side to avoid the overhead on every
445 function decl tree. */
447 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
448 /* Without this, we cannot really proceed. */
449 gcc_checking_assert (coro_info
);
451 /* If we don't already have a current promise type, try to look it up. */
452 if (coro_info
->promise_type
== NULL_TREE
)
454 /* Get the coroutine traits template class instance for the function
455 signature we have - coroutine_traits <R, ...> */
457 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
459 /* Find the promise type for that. */
460 coro_info
->promise_type
= find_promise_type (templ_class
);
462 /* If we don't find it, punt on the rest. */
463 if (coro_info
->promise_type
== NULL_TREE
)
465 if (!coro_info
->coro_promise_error_emitted
)
466 error_at (loc
, "unable to find the promise type for"
468 coro_info
->coro_promise_error_emitted
= true;
472 /* Try to find the handle type for the promise. */
474 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
475 if (handle_type
== NULL_TREE
)
478 /* Complete this, we're going to use it. */
479 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
481 /* Diagnostic would be emitted by complete_type_or_else. */
482 if (!coro_info
->handle_type
)
485 /* Build a proxy for a handle to "self" as the param to
486 await_suspend() calls. */
487 coro_info
->self_h_proxy
488 = build_lang_decl (VAR_DECL
, get_identifier ("self_h.proxy"),
489 coro_info
->handle_type
);
491 /* Build a proxy for the promise so that we can perform lookups. */
492 coro_info
->promise_proxy
493 = build_lang_decl (VAR_DECL
, get_identifier ("promise.proxy"),
494 coro_info
->promise_type
);
496 /* Note where we first saw a coroutine keyword. */
497 coro_info
->first_coro_keyword
= loc
;
503 /* These functions assumes that the caller has verified that the state for
504 the decl has been initialized, we try to minimize work here. */
507 get_coroutine_promise_type (tree decl
)
509 if (coroutine_info
*info
= get_coroutine_info (decl
))
510 return info
->promise_type
;
516 get_coroutine_handle_type (tree decl
)
518 if (coroutine_info
*info
= get_coroutine_info (decl
))
519 return info
->handle_type
;
525 get_coroutine_self_handle_proxy (tree decl
)
527 if (coroutine_info
*info
= get_coroutine_info (decl
))
528 return info
->self_h_proxy
;
534 get_coroutine_promise_proxy (tree decl
)
536 if (coroutine_info
*info
= get_coroutine_info (decl
))
537 return info
->promise_proxy
;
543 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
546 tree promise
= get_coroutine_promise_type (fndecl
);
548 = lookup_member (promise
, member_id
,
549 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
550 if (musthave
&& pm_memb
== NULL_TREE
)
552 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
553 return error_mark_node
;
558 /* Lookup an Awaitable member, which should be await_ready, await_suspend
562 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
565 = lookup_member (await_type
, member_id
,
566 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
567 if (aw_memb
== NULL_TREE
)
569 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
570 return error_mark_node
;
575 /* Here we check the constraints that are common to all keywords (since the
576 presence of a coroutine keyword makes the function into a coroutine). */
579 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
582 if (fndecl
== NULL_TREE
)
584 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
588 /* This is arranged in order of prohibitions in the std. */
589 if (DECL_MAIN_P (fndecl
))
591 /* [basic.start.main] 3. The function main shall not be a coroutine. */
592 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
597 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
599 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
600 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
602 cp_function_chain
->invalid_constexpr
= true;
606 if (FNDECL_USED_AUTO (fndecl
))
608 /* [dcl.spec.auto] 15. A function declared with a return type that uses
609 a placeholder type shall not be a coroutine. */
611 "%qs cannot be used in a function with a deduced return type",
616 if (varargs_function_p (fndecl
))
618 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
619 coroutine shall not terminate with an ellipsis that is not part
620 of a parameter-declaration. */
622 "%qs cannot be used in a varargs function", kw_name
);
626 if (DECL_CONSTRUCTOR_P (fndecl
))
628 /* [class.ctor] 7. a constructor shall not be a coroutine. */
629 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
633 if (DECL_DESTRUCTOR_P (fndecl
))
635 /* [class.dtor] 21. a destructor shall not be a coroutine. */
636 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
643 /* Here we check the constraints that are not per keyword. */
646 coro_function_valid_p (tree fndecl
)
648 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
650 /* For cases where fundamental information cannot be found, e.g. the
651 coroutine traits are missing, we need to punt early. */
652 if (!coro_promise_type_found_p (fndecl
, f_loc
))
655 /* Since we think the function is a coroutine, that implies we parsed
656 a keyword that triggered this. Keywords check promise validity for
657 their context and thus the promise type should be known at this point. */
658 if (get_coroutine_handle_type (fndecl
) == NULL_TREE
659 || get_coroutine_promise_type (fndecl
) == NULL_TREE
)
662 if (current_function_returns_value
|| current_function_returns_null
)
664 /* TODO: record or extract positions of returns (and the first coro
665 keyword) so that we can add notes to the diagnostic about where
666 the bad keyword is and what made the function into a coro. */
667 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
668 " did you mean %<co_return%>?");
675 enum suspend_point_kind
{
676 CO_AWAIT_SUSPEND_POINT
= 0,
677 CO_YIELD_SUSPEND_POINT
,
678 INITIAL_SUSPEND_POINT
,
682 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
683 It is also used to build the initial and final suspend points.
685 'a', 'o' and 'e' are used as per the description in the section noted.
687 A, the original yield/await expr, is found at source location LOC.
689 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
690 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
693 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
695 /* Try and overload of operator co_await, .... */
697 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
699 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
700 NULL_TREE
, NULL
, tf_warning_or_error
);
701 /* If no viable functions are found, o is a. */
702 if (!o
|| o
== error_mark_node
)
706 o
= a
; /* This is most likely about to fail anyway. */
708 tree o_type
= TREE_TYPE (o
);
709 if (o_type
&& !VOID_TYPE_P (o_type
))
710 o_type
= complete_type_or_else (o_type
, o
);
713 return error_mark_node
;
715 if (TREE_CODE (o_type
) != RECORD_TYPE
)
717 error_at (loc
, "awaitable type %qT is not a structure",
719 return error_mark_node
;
722 /* Check for required awaitable members and their types. */
724 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
725 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
726 return error_mark_node
;
728 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
729 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
730 return error_mark_node
;
732 /* The type of the co_await is the return type of the awaitable's
733 await_resume, so we need to look that up. */
735 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
736 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
737 return error_mark_node
;
739 /* To complete the lookups, we need an instance of 'e' which is built from
740 'o' according to [expr.await] 3.4. However, we don't want to materialize
741 'e' here (it might need to be placed in the coroutine frame) so we will
742 make a temp placeholder instead. If 'o' is a parameter or a local var,
743 then we do not need an additional var (parms and local vars are already
744 copied into the frame and will have lifetimes according to their original
746 tree e_proxy
= STRIP_NOPS (o
);
747 if (INDIRECT_REF_P (e_proxy
))
748 e_proxy
= TREE_OPERAND (e_proxy
, 0);
749 if (TREE_CODE (e_proxy
) == PARM_DECL
750 || (VAR_P (e_proxy
) && (!DECL_ARTIFICIAL (e_proxy
)
751 || DECL_HAS_VALUE_EXPR_P (e_proxy
))))
755 e_proxy
= build_lang_decl (VAR_DECL
, NULL_TREE
, o_type
);
756 DECL_ARTIFICIAL (e_proxy
) = true;
759 /* I suppose we could check that this is contextually convertible to bool. */
760 tree awrd_func
= NULL_TREE
;
762 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
763 &awrd_func
, tf_warning_or_error
);
765 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
766 return error_mark_node
;
768 /* The suspend method may return one of three types:
769 1. void (no special action needed).
770 2. bool (if true, we don't need to suspend).
771 3. a coroutine handle, we execute the handle.resume() call. */
772 tree awsp_func
= NULL_TREE
;
773 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
774 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
776 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
777 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
779 release_tree_vector (args
);
780 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
781 return error_mark_node
;
784 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
785 if (same_type_p (susp_return_type
, void_type_node
))
787 else if (same_type_p (susp_return_type
, boolean_type_node
))
789 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
790 && CLASS_TYPE_P (susp_return_type
))
792 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
793 if (tt
== coro_handle_templ
)
799 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
800 " a coroutine handle");
801 return error_mark_node
;
804 /* Finally, the type of e.await_resume() is the co_await's type. */
805 tree awrs_func
= NULL_TREE
;
807 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
808 &awrs_func
, tf_warning_or_error
);
810 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
811 return error_mark_node
;
813 /* We now have three call expressions, in terms of the promise, handle and
814 'e' proxies. Save them in the await expression for later expansion. */
816 tree awaiter_calls
= make_tree_vec (3);
817 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
818 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
819 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
821 tree await_expr
= build5_loc (loc
, CO_AWAIT_EXPR
,
822 TREE_TYPE (TREE_TYPE (awrs_func
)),
823 a
, e_proxy
, o
, awaiter_calls
,
824 build_int_cst (integer_type_node
,
825 (int) suspend_kind
));
826 return convert_from_reference (await_expr
);
830 finish_co_await_expr (location_t kw
, tree expr
)
832 if (!expr
|| error_operand_p (expr
))
833 return error_mark_node
;
835 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
837 return error_mark_node
;
839 /* The current function has now become a coroutine, if it wasn't already. */
840 DECL_COROUTINE_P (current_function_decl
) = 1;
842 if (processing_template_decl
)
844 current_function_returns_value
= 1;
846 if (check_for_bare_parameter_packs (expr
))
847 return error_mark_node
;
849 /* If we don't know the promise type, we can't proceed. */
850 tree functype
= TREE_TYPE (current_function_decl
);
851 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
852 return build5_loc (kw
, CO_AWAIT_EXPR
, unknown_type_node
, expr
,
853 NULL_TREE
, NULL_TREE
, NULL_TREE
, integer_zero_node
);
856 /* We must be able to look up the "await_transform" method in the scope of
857 the promise type, and obtain its return type. */
858 if (!coro_promise_type_found_p (current_function_decl
, kw
))
859 return error_mark_node
;
862 The incoming cast expression might be transformed by a promise
863 'await_transform()'. */
865 = lookup_promise_method (current_function_decl
,
866 coro_await_transform_identifier
, kw
,
868 if (at_meth
== error_mark_node
)
869 return error_mark_node
;
874 /* try to build a = p.await_transform (e). */
875 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
876 a
= build_new_method_call (get_coroutine_promise_proxy (
877 current_function_decl
),
878 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
879 NULL
, tf_warning_or_error
);
881 /* As I read the section.
882 We saw an await_transform method, so it's mandatory that we replace
883 expr with p.await_transform (expr), therefore if the method call fails
884 (presumably, we don't have suitable arguments) then this part of the
886 if (a
== error_mark_node
)
887 return error_mark_node
;
890 /* Now we want to build co_await a. */
891 tree op
= build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
892 if (op
!= error_mark_node
)
894 TREE_SIDE_EFFECTS (op
) = 1;
895 SET_EXPR_LOCATION (op
, kw
);
901 /* Take the EXPR given and attempt to build:
902 co_await p.yield_value (expr);
903 per [expr.yield] para 1. */
906 finish_co_yield_expr (location_t kw
, tree expr
)
908 if (!expr
|| error_operand_p (expr
))
909 return error_mark_node
;
911 /* Check the general requirements and simple syntax errors. */
912 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
914 return error_mark_node
;
916 /* The current function has now become a coroutine, if it wasn't already. */
917 DECL_COROUTINE_P (current_function_decl
) = 1;
919 if (processing_template_decl
)
921 current_function_returns_value
= 1;
923 if (check_for_bare_parameter_packs (expr
))
924 return error_mark_node
;
926 tree functype
= TREE_TYPE (current_function_decl
);
927 /* If we don't know the promise type, we can't proceed. */
928 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
929 return build2_loc (kw
, CO_YIELD_EXPR
, unknown_type_node
, expr
,
933 if (!coro_promise_type_found_p (current_function_decl
, kw
))
934 /* We must be able to look up the "yield_value" method in the scope of
935 the promise type, and obtain its return type. */
936 return error_mark_node
;
938 /* The incoming expr is "e" per [expr.yield] para 1, lookup and build a
939 call for p.yield_value(e). */
940 tree y_meth
= lookup_promise_method (current_function_decl
,
941 coro_yield_value_identifier
, kw
,
943 if (!y_meth
|| y_meth
== error_mark_node
)
944 return error_mark_node
;
947 Let e be the operand of the yield-expression and p be an lvalue naming
948 the promise object of the enclosing coroutine, then the yield-expression
949 is equivalent to the expression co_await p.yield_value(e).
950 build p.yield_value(e): */
951 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
952 tree yield_call
= build_new_method_call
953 (get_coroutine_promise_proxy (current_function_decl
), y_meth
, &args
,
954 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
956 /* Now build co_await p.yield_value (e).
957 Noting that for co_yield, there is no evaluation of any potential
958 promise transform_await(), so we call build_co_await directly. */
960 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
961 if (op
!= error_mark_node
)
963 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
964 TREE_SIDE_EFFECTS (op
) = 1;
970 /* Check and build a co_return statememt.
971 First that it's valid to have a co_return keyword here.
972 If it is, then check and build the p.return_{void(),value(expr)}.
973 These are built against a proxy for the promise, which will be filled
974 in with the actual frame version when the function is transformed. */
977 finish_co_return_stmt (location_t kw
, tree expr
)
980 STRIP_ANY_LOCATION_WRAPPER (expr
);
982 if (error_operand_p (expr
))
983 return error_mark_node
;
985 /* If it fails the following test, the function is not permitted to be a
986 coroutine, so the co_return statement is erroneous. */
987 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
989 return error_mark_node
;
991 /* The current function has now become a coroutine, if it wasn't
993 DECL_COROUTINE_P (current_function_decl
) = 1;
995 /* This function will appear to have no return statement, even if it
996 is declared to return non-void (most likely). This is correct - we
997 synthesize the return for the ramp in the compiler. So suppress any
998 extraneous warnings during substitution. */
999 TREE_NO_WARNING (current_function_decl
) = true;
1001 if (processing_template_decl
1002 && check_for_bare_parameter_packs (expr
))
1003 return error_mark_node
;
1005 /* If we don't know the promise type, we can't proceed, build the
1006 co_return with the expression unchanged. */
1007 tree functype
= TREE_TYPE (current_function_decl
);
1008 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1010 /* co_return expressions are always void type, regardless of the
1012 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
,
1014 expr
= maybe_cleanup_point_expr_void (expr
);
1015 return add_stmt (expr
);
1018 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1019 return error_mark_node
;
1021 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1022 whether the promise type has a suitable return_void/return_value. */
1023 TREE_NO_WARNING (current_function_decl
) = true;
1025 if (!processing_template_decl
&& warn_sequence_point
)
1026 verify_sequence_points (expr
);
1030 /* If we had an id-expression obfuscated by force_paren_expr, we need
1031 to undo it so we can try to treat it as an rvalue below. */
1032 expr
= maybe_undo_parenthesized_ref (expr
);
1034 if (processing_template_decl
)
1035 expr
= build_non_dependent_expr (expr
);
1037 if (error_operand_p (expr
))
1038 return error_mark_node
;
1041 /* If the promise object doesn't have the correct return call then
1042 there's a mis-match between the co_return <expr> and this. */
1043 tree co_ret_call
= error_mark_node
;
1044 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
1047 = lookup_promise_method (current_function_decl
,
1048 coro_return_void_identifier
, kw
,
1050 if (crv_meth
== error_mark_node
)
1051 return error_mark_node
;
1053 co_ret_call
= build_new_method_call (
1054 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, NULL
,
1055 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1060 = lookup_promise_method (current_function_decl
,
1061 coro_return_value_identifier
, kw
,
1063 if (crv_meth
== error_mark_node
)
1064 return error_mark_node
;
1066 /* [class.copy.elision] / 3.
1067 An implicitly movable entity is a variable of automatic storage
1068 duration that is either a non-volatile object or an rvalue reference
1069 to a non-volatile object type. For such objects in the context of
1070 the co_return, the overload resolution should be carried out first
1071 treating the object as an rvalue, if that fails, then we fall back
1072 to regular overload resolution. */
1074 if (treat_lvalue_as_rvalue_p (expr
, /*parm_ok*/true)
1075 && CLASS_TYPE_P (TREE_TYPE (expr
))
1076 && !TYPE_VOLATILE (TREE_TYPE (expr
)))
1078 vec
<tree
, va_gc
> *args
= make_tree_vector_single (move (expr
));
1079 /* It's OK if this fails... */
1080 co_ret_call
= build_new_method_call
1081 (get_coroutine_promise_proxy (current_function_decl
), crv_meth
,
1082 &args
, NULL_TREE
, LOOKUP_NORMAL
|LOOKUP_PREFER_RVALUE
,
1086 if (co_ret_call
== error_mark_node
)
1088 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1089 /* ... but this must succeed if we didn't get the move variant. */
1090 co_ret_call
= build_new_method_call
1091 (get_coroutine_promise_proxy (current_function_decl
), crv_meth
,
1092 &args
, NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1096 /* Makes no sense for a co-routine really. */
1097 if (TREE_THIS_VOLATILE (current_function_decl
))
1099 "function declared %<noreturn%> has a"
1100 " %<co_return%> statement");
1102 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
1103 expr
= maybe_cleanup_point_expr_void (expr
);
1104 return add_stmt (expr
);
1107 /* We need to validate the arguments to __builtin_coro_promise, since the
1108 second two must be constant, and the builtins machinery doesn't seem to
1109 deal with that properly. */
1112 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
1114 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1116 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1117 switch (DECL_FUNCTION_CODE (fn
))
1122 case BUILT_IN_CORO_PROMISE
:
1124 /* Argument 0 is already checked by the normal built-in machinery
1125 Argument 1 must be a constant of size type. It probably makes
1126 little sense if it's not a power of 2, but that isn't specified
1128 tree arg
= CALL_EXPR_ARG (call
, 1);
1129 location_t loc
= EXPR_LOCATION (arg
);
1131 /* We expect alignof expressions in templates. */
1132 if (TREE_CODE (arg
) == NON_DEPENDENT_EXPR
1133 && TREE_CODE (TREE_OPERAND (arg
, 0)) == ALIGNOF_EXPR
)
1135 else if (!TREE_CONSTANT (arg
))
1137 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1138 " must be a constant");
1139 return error_mark_node
;
1141 /* Argument 2 is the direction - to / from handle address to promise
1143 arg
= CALL_EXPR_ARG (call
, 2);
1144 loc
= EXPR_LOCATION (arg
);
1145 if (!TREE_CONSTANT (arg
))
1147 error_at (loc
, "the direction argument to"
1148 " %<__builtin_coro_promise%> must be a constant");
1149 return error_mark_node
;
1157 /* ================= Morph and Expand. =================
1159 The entry point here is morph_fn_to_coro () which is called from
1160 finish_function () when we have completed any template expansion.
1162 This is preceded by helper functions that implement the phases below.
1164 The process proceeds in four phases.
1167 The user's function body is wrapped in the initial and final suspend
1168 points and we begin building the coroutine frame.
1169 We build empty decls for the actor and destroyer functions at this
1171 When exceptions are enabled, the user's function body will also be
1172 wrapped in a try-catch block with the catch invoking the promise
1173 class 'unhandled_exception' method.
1176 The user's function body is analyzed to determine the suspend points,
1177 if any, and to capture local variables that might persist across such
1178 suspensions. In most cases, it is not necessary to capture compiler
1179 temporaries, since the tree-lowering nests the suspensions correctly.
1180 However, in the case of a captured reference, there is a lifetime
1181 extension to the end of the full expression - which can mean across a
1182 suspend point in which case it must be promoted to a frame variable.
1184 At the conclusion of analysis, we have a conservative frame layout and
1185 maps of the local variables to their frame entry points.
1187 C Build the ramp function.
1188 Carry out the allocation for the coroutine frame (NOTE; the actual size
1189 computation is deferred until late in the middle end to allow for future
1190 optimizations that will be allowed to elide unused frame entries).
1191 We build the return object.
1193 D Build and expand the actor and destroyer function bodies.
1194 The destroyer is a trivial shim that sets a bit to indicate that the
1195 destroy dispatcher should be used and then calls into the actor.
1197 The actor function is the implementation of the user's state machine.
1198 The current suspend point is noted in an index.
1199 Each suspend point is encoded as a pair of internal functions, one in
1200 the relevant dispatcher, and one representing the suspend point.
1202 During this process, the user's local variables and the proxies for the
1203 self-handle and the promise class instance are re-written to their
1204 coroutine frame equivalents.
1206 The complete bodies for the ramp, actor and destroy function are passed
1207 back to finish_function for folding and gimplification. */
1209 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1212 coro_build_expr_stmt (tree expr
, location_t loc
)
1214 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1218 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1220 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1221 return coro_build_expr_stmt (t
, loc
);
1224 /* Helpers for label creation:
1225 1. Create a named label in the specified context. */
1228 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1230 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1232 DECL_CONTEXT (lab
) = ctx
;
1233 DECL_ARTIFICIAL (lab
) = true;
1234 DECL_IGNORED_P (lab
) = true;
1235 TREE_USED (lab
) = true;
1239 /* 2. Create a named label in the specified context. */
1242 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1244 tree lab_id
= get_identifier (name
);
1245 tree lab
= define_label (loc
, lab_id
);
1246 DECL_CONTEXT (lab
) = ctx
;
1247 DECL_ARTIFICIAL (lab
) = true;
1248 TREE_USED (lab
) = true;
1252 struct proxy_replace
1258 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1260 proxy_replace
*data
= (proxy_replace
*) d
;
1262 if (*here
== data
->from
)
1272 /* Support for expansion of co_return statements. */
1274 struct coro_ret_data
1281 /* If this is a coreturn statement (or one wrapped in a cleanup) then
1282 return the list of statements to replace it. */
1285 coro_maybe_expand_co_return (tree co_ret_expr
, coro_ret_data
*data
)
1287 /* Look inside <(void) (expr)> cleanup */
1288 if (TREE_CODE (co_ret_expr
) == CLEANUP_POINT_EXPR
)
1289 co_ret_expr
= TREE_OPERAND (co_ret_expr
, 0);
1291 if (TREE_CODE (co_ret_expr
) != CO_RETURN_EXPR
)
1294 location_t loc
= EXPR_LOCATION (co_ret_expr
);
1295 tree expr
= TREE_OPERAND (co_ret_expr
, 0);
1296 tree call
= TREE_OPERAND (co_ret_expr
, 1);
1297 tree stmt_list
= NULL
;
1298 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
1300 /* [stmt.return.coroutine], 2.2
1301 If expr is present and void, it is placed immediately before
1302 the call for return_void; */
1303 expr
= maybe_cleanup_point_expr_void (expr
);
1304 append_to_statement_list (expr
, &stmt_list
);
1307 /* Now replace the promise proxy with its real value. */
1308 proxy_replace p_data
;
1309 p_data
.from
= data
->promise_proxy
;
1310 p_data
.to
= data
->real_promise
;
1311 cp_walk_tree (&call
, replace_proxy
, &p_data
, NULL
);
1313 /* The types of p.return_void and p.return_value are not explicitly stated
1314 at least in n4835, it is expected that they will return void. */
1315 call
= maybe_cleanup_point_expr_void (call
);
1316 append_to_statement_list (call
, &stmt_list
);
1317 tree r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->fs_label
);
1318 append_to_statement_list (r
, &stmt_list
);
1322 /* Callback that rewrites co_return as per [stmt.return.coroutine]
1324 { p.return_void (); goto final_suspend; }
1325 - for co_return [void expr];
1326 { expr; p.return_void(); goto final_suspend;}
1327 - for co_return [non void expr];
1328 { p.return_value(expr); goto final_suspend; } */
1331 co_return_expander (tree
*stmt
, int *do_subtree
, void *d
)
1333 coro_ret_data
*data
= (coro_ret_data
*) d
;
1335 /* To avoid nesting statement lists, walk them and insert as needed. */
1336 if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1338 tree_stmt_iterator i
;
1339 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1341 tree
*new_stmt
= tsi_stmt_ptr (i
);
1342 tree replace
= coro_maybe_expand_co_return (*new_stmt
, data
);
1343 /* If we got something, it will be list and we want to splice
1345 if (replace
!= NULL_TREE
)
1347 /* Splice it in ... */
1348 tsi_link_before (&i
, replace
, TSI_SAME_STMT
);
1349 /* ... and delete what we expanded. */
1351 /* Maybe, even likely, we replaced the last in the list. */
1355 else /* Continue the walk. */
1356 cp_walk_tree (new_stmt
, co_return_expander
, d
, NULL
);
1358 *do_subtree
= 0; /* Done subtrees. */
1362 /* We might have a single co_return statement, in which case, we do
1363 have to replace it with a list. */
1364 tree replace
= coro_maybe_expand_co_return (*stmt
, data
);
1365 if (replace
!= NULL_TREE
)
1368 *do_subtree
= 0; /* Done here. */
1374 /* Walk the original function body, rewriting co_returns. */
1377 expand_co_returns (tree
*fnbody
, tree promise_proxy
, tree promise
,
1380 coro_ret_data data
= {promise_proxy
, promise
, fs_label
};
1381 cp_walk_tree (fnbody
, co_return_expander
, &data
, NULL
);
1385 /* Support for expansion of co_await statements. */
1389 tree actor_fn
; /* Decl for context. */
1390 tree coro_fp
; /* Frame pointer var. */
1391 tree resume_idx
; /* This is the index var in the frame. */
1392 tree i_a_r_c
; /* initial suspend await_resume() was called if true. */
1393 tree self_h
; /* This is a handle to the current coro (frame var). */
1394 tree cleanup
; /* This is where to go once we complete local destroy. */
1395 tree cororet
; /* This is where to go if we suspend. */
1396 tree corocont
; /* This is where to go if we continue. */
1397 tree conthand
; /* This is the handle for a continuation. */
1398 unsigned index
; /* This is our current resume index. */
1401 /* Lighweight search for the first await expression in tree-walk order.
1403 The first await expression found in STMT.
1404 NULL_TREE if there are none.
1405 So can be used to determine if the statement needs to be processed for
1409 co_await_find_in_subtree (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
1411 tree
**p
= (tree
**) d
;
1412 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1420 /* Starting with a statment:
1422 stmt => some tree containing one or more await expressions.
1424 We replace the statement with:
1426 initialise awaitable
1432 revised statement with one await expression rewritten to its
1433 await_resume() return value.
1436 We then recurse into the initializer and the revised statement
1437 repeating this replacement until there are no more await expressions
1441 expand_one_await_expression (tree
*stmt
, tree
*await_expr
, void *d
)
1443 coro_aw_data
*data
= (coro_aw_data
*) d
;
1445 tree saved_statement
= *stmt
;
1446 tree saved_co_await
= *await_expr
;
1448 tree actor
= data
->actor_fn
;
1449 location_t loc
= EXPR_LOCATION (*stmt
);
1450 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1451 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1452 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1454 tree source
= TREE_OPERAND (saved_co_await
, 4);
1456 (source
&& TREE_INT_CST_LOW (source
) == (int) INITIAL_SUSPEND_POINT
);
1457 bool is_final
= (source
1458 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1459 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1460 int resume_point
= data
->index
;
1461 size_t bufsize
= sizeof ("destroy.") + 10;
1462 char *buf
= (char *) alloca (bufsize
);
1463 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1464 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1465 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1466 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1467 tree empty_list
= build_empty_stmt (loc
);
1469 tree dtor
= NULL_TREE
;
1470 tree await_type
= TREE_TYPE (var
);
1472 dtor
= build_special_member_call (var
, complete_dtor_identifier
, NULL
,
1473 await_type
, LOOKUP_NORMAL
,
1474 tf_warning_or_error
);
1476 tree stmt_list
= NULL
;
1477 tree t_expr
= STRIP_NOPS (expr
);
1479 tree
*await_init
= NULL
;
1484 /* Initialize the var from the provided 'o' expression. */
1485 r
= build2 (INIT_EXPR
, await_type
, var
, expr
);
1486 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1487 append_to_statement_list_force (r
, &stmt_list
);
1488 /* We have an initializer, which might itself contain await exprs. */
1489 await_init
= tsi_stmt_ptr (tsi_last (stmt_list
));
1492 /* Use the await_ready() call to test if we need to suspend. */
1493 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1494 ready_cond
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, ready_cond
);
1496 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1498 tree body_list
= NULL
;
1499 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1500 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1502 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1503 append_to_statement_list (r
, &body_list
);
1505 /* Find out what we have to do with the awaiter's suspend method.
1507 (5.1) If the result of await-ready is false, the coroutine is considered
1509 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1510 await-suspend.resume() is evaluated.
1511 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1512 and the coroutine is resumed if the result is false.
1513 (5.1.3) Otherwise, await-suspend is evaluated. */
1515 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1516 tree susp_type
= TREE_TYPE (suspend
);
1518 bool is_cont
= false;
1519 /* NOTE: final suspend can't resume; the "resume" label in that case
1520 corresponds to implicit destruction. */
1521 if (VOID_TYPE_P (susp_type
))
1523 /* We just call await_suspend() and hit the yield. */
1524 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1525 append_to_statement_list (suspend
, &body_list
);
1527 else if (TREE_CODE (susp_type
) == BOOLEAN_TYPE
)
1529 /* Boolean return, continue if the call returns false. */
1530 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1532 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1533 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1534 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1536 append_to_statement_list (r
, &body_list
);
1540 r
= build1_loc (loc
, CONVERT_EXPR
, void_coro_handle_type
, suspend
);
1541 r
= build2_loc (loc
, INIT_EXPR
, void_coro_handle_type
, data
->conthand
, r
);
1542 r
= build1 (CONVERT_EXPR
, void_type_node
, r
);
1543 append_to_statement_list (r
, &body_list
);
1547 tree d_l
= build_address (destroy_label
);
1548 tree r_l
= build_address (resume_label
);
1549 tree susp
= build_address (data
->cororet
);
1550 tree cont
= build_address (data
->corocont
);
1551 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1553 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1555 tree sw
= begin_switch_stmt ();
1556 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1557 DECL_ARTIFICIAL (cond
) = 1;
1558 DECL_IGNORED_P (cond
) = 1;
1559 layout_decl (cond
, 0);
1561 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1562 susp_idx
, final_susp
, r_l
, d_l
,
1564 r
= build2 (INIT_EXPR
, integer_type_node
, cond
, r
);
1565 finish_switch_cond (r
, sw
);
1566 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1567 create_anon_label_with_ctx (loc
, actor
));
1568 add_stmt (r
); /* case 0: */
1569 /* Implement the suspend, a scope exit without clean ups. */
1570 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1,
1571 is_cont
? cont
: susp
);
1572 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1573 add_stmt (r
); /* goto ret; */
1574 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1575 create_anon_label_with_ctx (loc
, actor
));
1576 add_stmt (r
); /* case 1: */
1577 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1578 add_stmt (r
); /* goto resume; */
1579 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1580 create_anon_label_with_ctx (loc
, actor
));
1581 add_stmt (r
); /* default:; */
1582 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1583 add_stmt (r
); /* goto destroy; */
1585 /* part of finish switch. */
1586 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1588 tree scope
= SWITCH_STMT_SCOPE (sw
);
1589 SWITCH_STMT_SCOPE (sw
) = NULL
;
1590 r
= do_poplevel (scope
);
1591 append_to_statement_list (r
, &body_list
);
1593 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1594 append_to_statement_list (destroy_label
, &body_list
);
1596 append_to_statement_list (dtor
, &body_list
);
1597 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1598 append_to_statement_list (r
, &body_list
);
1600 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1603 append_to_statement_list (r
, &stmt_list
);
1606 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1607 append_to_statement_list (resume_label
, &stmt_list
);
1611 /* Note that we are about to execute the await_resume() for the initial
1612 await expression. */
1613 r
= build2_loc (loc
, MODIFY_EXPR
, boolean_type_node
, data
->i_a_r_c
,
1615 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1616 append_to_statement_list (r
, &stmt_list
);
1619 /* This will produce the value (if one is provided) from the co_await
1621 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1622 if (REFERENCE_REF_P (resume_call
))
1623 /* Sink to await_resume call_expr. */
1624 resume_call
= TREE_OPERAND (resume_call
, 0);
1626 *await_expr
= resume_call
; /* Replace the co_await expr with its result. */
1627 append_to_statement_list_force (saved_statement
, &stmt_list
);
1628 /* Get a pointer to the revised statment. */
1629 tree
*revised
= tsi_stmt_ptr (tsi_last (stmt_list
));
1631 append_to_statement_list (dtor
, &stmt_list
);
1634 /* Replace the original statement with the expansion. */
1637 /* Now, if the awaitable had an initializer, expand any awaits that might
1638 be embedded in it. */
1641 cp_walk_tree (await_init
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1642 expand_one_await_expression (await_init
, aw_expr_ptr
, d
);
1644 /* Expand any more await expressions in the the original statement. */
1645 if (cp_walk_tree (revised
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1646 expand_one_await_expression (revised
, aw_expr_ptr
, d
);
1651 /* Check to see if a statement contains at least one await expression, if
1652 so, then process that. */
1655 process_one_statement (tree
*stmt
, void *d
)
1658 if (cp_walk_tree (stmt
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1659 expand_one_await_expression (stmt
, aw_expr_ptr
, d
);
1664 await_statement_expander (tree
*stmt
, int *do_subtree
, void *d
)
1666 tree res
= NULL_TREE
;
1668 /* Process a statement at a time. */
1669 if (STATEMENT_CLASS_P (*stmt
) || TREE_CODE (*stmt
) == BIND_EXPR
)
1670 return NULL_TREE
; /* Just process the sub-trees. */
1671 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1673 tree_stmt_iterator i
;
1674 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1676 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_expander
,
1681 *do_subtree
= 0; /* Done subtrees. */
1683 else if (EXPR_P (*stmt
))
1685 process_one_statement (stmt
, d
);
1686 *do_subtree
= 0; /* Done subtrees. */
1689 /* Continue statement walk, where required. */
1693 /* Suspend point hash_map. */
1695 struct suspend_point_info
1697 /* coro frame field type. */
1698 tree awaitable_type
;
1699 /* coro frame field name. */
1700 tree await_field_id
;
1703 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1705 struct await_xform_data
1707 tree actor_fn
; /* Decl for context. */
1715 /* When we built the await expressions, we didn't know the coro frame
1716 layout, therefore no idea where to find the promise or where to put
1717 the awaitables. Now we know these things, fill them in. */
1720 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1722 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1723 location_t loc
= EXPR_LOCATION (await_expr
);
1726 error_at (loc
, "no suspend point info for %qD", await_expr
);
1727 return error_mark_node
;
1730 /* So, on entry, we have:
1731 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1732 We no longer need a [it had diagnostic value, maybe?]
1733 We need to replace the promise proxy in all elements
1734 We need to replace the e_proxy in the awr_call. */
1736 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1738 /* If we have a frame var for the awaitable, get a reference to it. */
1740 if (si
->await_field_id
)
1743 = lookup_member (coro_frame_type
, si
->await_field_id
,
1744 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
1745 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
,
1747 tf_warning_or_error
);
1749 /* Replace references to the instance proxy with the frame entry now
1751 data
.from
= TREE_OPERAND (await_expr
, 1);
1753 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1755 /* .. and replace. */
1756 TREE_OPERAND (await_expr
, 1) = as
;
1759 /* Now do the self_handle. */
1760 data
.from
= xform
->self_h_proxy
;
1761 data
.to
= xform
->real_self_h
;
1762 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1764 /* Now do the promise. */
1765 data
.from
= xform
->promise_proxy
;
1766 data
.to
= xform
->real_promise
;
1767 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1772 /* A wrapper for the transform_await_expr function so that it can be a
1773 callback from cp_walk_tree. */
1776 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1778 /* Set actor function as new DECL_CONTEXT of label_decl. */
1779 struct await_xform_data
*xform
= (struct await_xform_data
*) d
;
1780 if (TREE_CODE (*stmt
) == LABEL_DECL
1781 && DECL_CONTEXT (*stmt
) != xform
->actor_fn
)
1782 DECL_CONTEXT (*stmt
) = xform
->actor_fn
;
1784 /* We should have already lowered co_yields to their co_await. */
1785 gcc_checking_assert (TREE_CODE (*stmt
) != CO_YIELD_EXPR
);
1786 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
)
1789 tree await_expr
= *stmt
;
1790 *stmt
= transform_await_expr (await_expr
, xform
);
1791 if (*stmt
== error_mark_node
)
1796 /* This caches information that we determine about function params,
1797 their uses and copies in the coroutine frame. */
1801 tree field_id
; /* The name of the copy in the coroutine frame. */
1802 vec
<tree
*> *body_uses
; /* Worklist of uses, void if there are none. */
1803 tree frame_type
; /* The type used to represent this parm in the frame. */
1804 tree orig_type
; /* The original type of the parm (not as passed). */
1805 bool by_ref
; /* Was passed by reference. */
1806 bool pt_ref
; /* Was a pointer to object. */
1807 bool trivial_dtor
; /* The frame type has a trivial DTOR. */
1808 bool this_ptr
; /* Is 'this' */
1809 bool lambda_cobj
; /* Lambda capture object */
1812 struct local_var_info
1817 bool is_lambda_capture
;
1819 bool has_value_expr_p
;
1823 /* For figuring out what local variable usage we have. */
1824 struct local_vars_transform
1828 tree coro_frame_type
;
1830 hash_map
<tree
, local_var_info
> *local_var_uses
;
1834 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
1836 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
1838 /* For each var in this bind expr (that has a frame id, which means it was
1839 accessed), build a frame reference for each and then walk the bind expr
1840 statements, substituting the frame ref for the original var. */
1842 if (TREE_CODE (*stmt
) == BIND_EXPR
)
1845 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1846 lvar
= DECL_CHAIN (lvar
))
1849 local_var_info
&local_var
1850 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
1851 gcc_checking_assert (existed
);
1853 /* Re-write the variable's context to be in the actor func. */
1854 DECL_CONTEXT (lvar
) = lvd
->context
;
1856 /* For capture proxies, this could include the decl value expr. */
1857 if (local_var
.is_lambda_capture
|| local_var
.has_value_expr_p
)
1859 tree ve
= DECL_VALUE_EXPR (lvar
);
1860 cp_walk_tree (&ve
, transform_local_var_uses
, d
, NULL
);
1861 continue; /* No frame entry for this. */
1864 /* TODO: implement selective generation of fields when vars are
1866 if (local_var
.field_id
== NULL_TREE
)
1867 continue; /* Wasn't used. */
1870 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
1871 /*protect=*/1, /*want_type=*/0,
1872 tf_warning_or_error
);
1873 tree fld_idx
= build3_loc (lvd
->loc
, COMPONENT_REF
, TREE_TYPE (lvar
),
1874 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
1875 local_var
.field_idx
= fld_idx
;
1877 /* FIXME: we should be able to do this in the loop above, but (at least
1878 for range for) there are cases where the DECL_INITIAL contains
1880 So, now we've built the revised var in the frame, substitute uses of
1881 it in initializers and the bind expr body. */
1882 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1883 lvar
= DECL_CHAIN (lvar
))
1885 /* we need to walk some of the decl trees, which might contain
1886 references to vars replaced at a higher level. */
1887 cp_walk_tree (&DECL_INITIAL (lvar
), transform_local_var_uses
, d
,
1889 cp_walk_tree (&DECL_SIZE (lvar
), transform_local_var_uses
, d
, NULL
);
1890 cp_walk_tree (&DECL_SIZE_UNIT (lvar
), transform_local_var_uses
, d
,
1893 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
1895 /* Now we have processed and removed references to the original vars,
1896 we can drop those from the bind - leaving capture proxies alone. */
1897 for (tree
*pvar
= &BIND_EXPR_VARS (*stmt
); *pvar
!= NULL
;)
1900 local_var_info
&local_var
1901 = lvd
->local_var_uses
->get_or_insert (*pvar
, &existed
);
1902 gcc_checking_assert (existed
);
1904 /* Leave lambda closure captures alone, we replace the *this
1905 pointer with the frame version and let the normal process
1907 Likewise, variables with their value found elsewhere.
1908 Skip past unused ones too. */
1909 if (local_var
.is_lambda_capture
1910 || local_var
.has_value_expr_p
1911 || local_var
.field_id
== NULL_TREE
)
1913 pvar
= &DECL_CHAIN (*pvar
);
1917 /* Discard this one, we replaced it. */
1918 *pvar
= DECL_CHAIN (*pvar
);
1921 *do_subtree
= 0; /* We've done the body already. */
1925 tree var_decl
= *stmt
;
1926 /* Look inside cleanups, we don't want to wrap a statement list in a
1928 bool needs_cleanup
= true;
1929 if (TREE_CODE (var_decl
) == CLEANUP_POINT_EXPR
)
1930 var_decl
= TREE_OPERAND (var_decl
, 0);
1932 needs_cleanup
= false;
1934 /* Look inside the decl_expr for the actual var. */
1935 bool decl_expr_p
= TREE_CODE (var_decl
) == DECL_EXPR
;
1936 if (decl_expr_p
&& TREE_CODE (DECL_EXPR_DECL (var_decl
)) == VAR_DECL
)
1937 var_decl
= DECL_EXPR_DECL (var_decl
);
1938 else if (TREE_CODE (var_decl
) != VAR_DECL
)
1941 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1942 for the promise and coroutine handle(s), to global vars or to compiler
1943 temporaries. Skip past these, we will handle them later. */
1944 local_var_info
*local_var_i
= lvd
->local_var_uses
->get (var_decl
);
1946 if (local_var_i
== NULL
)
1949 if (local_var_i
->is_lambda_capture
1950 || local_var_i
->is_static
1951 || local_var_i
->has_value_expr_p
)
1954 /* This is our revised 'local' i.e. a frame slot. */
1955 tree revised
= local_var_i
->field_idx
;
1956 gcc_checking_assert (DECL_CONTEXT (var_decl
) == lvd
->context
);
1958 if (decl_expr_p
&& DECL_INITIAL (var_decl
))
1960 location_t loc
= DECL_SOURCE_LOCATION (var_decl
);
1962 = cp_build_modify_expr (loc
, revised
, INIT_EXPR
,
1963 DECL_INITIAL (var_decl
), tf_warning_or_error
);
1965 r
= coro_build_cvt_void_expr_stmt (r
, EXPR_LOCATION (*stmt
));
1972 *do_subtree
= 0; /* We've accounted for the nested use. */
1976 /* The actor transform. */
1979 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
1980 tree orig
, hash_map
<tree
, param_info
> *param_uses
,
1981 hash_map
<tree
, local_var_info
> *local_var_uses
,
1982 vec
<tree
, va_gc
> *param_dtor_list
, tree initial_await
,
1983 tree final_await
, unsigned body_count
, tree frame_size
)
1985 verify_stmt_tree (fnbody
);
1986 /* Some things we inherit from the original function. */
1987 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
1988 tree handle_type
= get_coroutine_handle_type (orig
);
1989 tree self_h_proxy
= get_coroutine_self_handle_proxy (orig
);
1990 tree promise_type
= get_coroutine_promise_type (orig
);
1991 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
1992 tree act_des_fn_type
1993 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
1994 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
1996 /* One param, the coro frame pointer. */
1997 tree actor_fp
= DECL_ARGUMENTS (actor
);
1999 /* A void return. */
2000 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2001 DECL_ARTIFICIAL (resdecl
) = 1;
2002 DECL_IGNORED_P (resdecl
) = 1;
2003 DECL_RESULT (actor
) = resdecl
;
2004 DECL_COROUTINE_P (actor
) = 1;
2006 /* We have a definition here. */
2007 TREE_STATIC (actor
) = 1;
2009 tree actor_outer
= push_stmt_list ();
2010 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2011 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
2013 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2014 tree top_block
= make_node (BLOCK
);
2015 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
2017 tree continuation
= build_lang_decl (VAR_DECL
,
2018 get_identifier ("actor.continue"),
2019 void_coro_handle_type
);
2020 DECL_ARTIFICIAL (continuation
) = 1;
2021 DECL_IGNORED_P (continuation
) = 1;
2022 DECL_CONTEXT (continuation
) = actor
;
2023 BIND_EXPR_VARS (actor_bind
) = continuation
;
2025 /* Update the block associated with the outer scope of the orig fn. */
2026 tree first
= expr_first (fnbody
);
2027 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
2029 /* We will discard this, since it's connected to the original scope
2031 tree block
= BIND_EXPR_BLOCK (first
);
2032 if (block
) /* For this to be missing is probably a bug. */
2034 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
2035 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
2036 BLOCK_SUPERCONTEXT (block
) = top_block
;
2037 BLOCK_SUBBLOCKS (top_block
) = block
;
2041 add_stmt (actor_bind
);
2042 tree actor_body
= push_stmt_list ();
2044 /* The entry point for the actor code from the ramp. */
2045 tree actor_begin_label
2046 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
2047 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
2049 /* Declare the continuation handle. */
2050 add_decl_expr (continuation
);
2052 /* Re-write param references in the body, no code should be generated
2054 if (DECL_ARGUMENTS (orig
))
2057 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
2060 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
2061 if (!parm
.body_uses
)
2062 continue; /* Wasn't used in the orignal function body. */
2064 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
2065 /*protect=*/1, /*want_type=*/0,
2066 tf_warning_or_error
);
2067 tree fld_idx
= build3_loc (loc
, COMPONENT_REF
, parm
.frame_type
,
2068 actor_frame
, fld_ref
, NULL_TREE
);
2070 /* We keep these in the frame as a regular pointer, so convert that
2071 back to the type expected. */
2073 fld_idx
= build1_loc (loc
, CONVERT_EXPR
, TREE_TYPE (arg
), fld_idx
);
2077 FOR_EACH_VEC_ELT (*parm
.body_uses
, i
, puse
)
2082 /* Re-write local vars, similarly. */
2083 local_vars_transform xform_vars_data
2084 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
2085 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
2087 tree resume_idx_name
= get_identifier ("__resume_at");
2088 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2089 tf_warning_or_error
);
2090 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
2091 rat_field
, NULL_TREE
);
2094 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
2097 = create_named_label_with_ctx (loc
, "actor.continue.ret", actor
);
2099 tree lsb_if
= begin_if_stmt ();
2100 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
2101 build_int_cst (short_unsigned_type_node
, 1));
2102 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
2103 build_int_cst (short_unsigned_type_node
, 0));
2104 finish_if_stmt_cond (chkb0
, lsb_if
);
2106 tree destroy_dispatcher
= begin_switch_stmt ();
2107 finish_switch_cond (rat
, destroy_dispatcher
);
2108 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2109 create_anon_label_with_ctx (loc
, actor
));
2111 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2112 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2115 short unsigned lab_num
= 3;
2116 for (unsigned destr_pt
= 0; destr_pt
< body_count
+ 2; destr_pt
++)
2118 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2119 b
= build_case_label (l_num
, NULL_TREE
,
2120 create_anon_label_with_ctx (loc
, actor
));
2122 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2124 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2126 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
2131 /* Insert the prototype dispatcher. */
2132 finish_switch_stmt (destroy_dispatcher
);
2134 finish_then_clause (lsb_if
);
2136 tree dispatcher
= begin_switch_stmt ();
2137 finish_switch_cond (rat
, dispatcher
);
2138 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
2139 create_anon_label_with_ctx (loc
, actor
));
2141 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
2144 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2145 create_anon_label_with_ctx (loc
, actor
));
2147 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2148 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2152 /* The final resume should be made to hit the default (trap, UB) entry. */
2153 for (unsigned resu_pt
= 0; resu_pt
< body_count
+ 1; resu_pt
++)
2155 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2156 b
= build_case_label (l_num
, NULL_TREE
,
2157 create_anon_label_with_ctx (loc
, actor
));
2159 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2161 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2163 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
2168 /* Insert the prototype dispatcher. */
2169 finish_switch_stmt (dispatcher
);
2171 finish_if_stmt (lsb_if
);
2173 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
2176 /* actor's version of the promise. */
2177 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
2178 tf_warning_or_error
);
2179 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
, false,
2180 tf_warning_or_error
);
2182 /* actor's coroutine 'self handle'. */
2183 tree ash_m
= lookup_member (coro_frame_type
, get_identifier ("__self_h"), 1,
2184 0, tf_warning_or_error
);
2185 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
2186 false, tf_warning_or_error
);
2187 /* So construct the self-handle from the frame address. */
2188 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
2189 0, tf_warning_or_error
);
2191 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2192 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2193 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2194 NULL
, tf_warning_or_error
);
2195 r
= build2 (INIT_EXPR
, handle_type
, ash
, hfa
);
2196 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2198 release_tree_vector (args
);
2200 /* Now we know the real promise, and enough about the frame layout to
2201 decide where to put things. */
2203 await_xform_data xform
2204 = {actor
, actor_frame
, promise_proxy
, ap
, self_h_proxy
, ash
};
2206 /* Get a reference to the initial suspend var in the frame. */
2207 transform_await_expr (initial_await
, &xform
);
2208 tree initial_await_stmt
= coro_build_expr_stmt (initial_await
, loc
);
2210 /* co_return branches to the final_suspend label, so declare that now. */
2211 tree fs_label
= create_named_label_with_ctx (loc
, "final.suspend", actor
);
2213 /* Expand co_returns in the saved function body */
2214 fnbody
= expand_co_returns (&fnbody
, promise_proxy
, ap
, fs_label
);
2216 /* Specific behaviour to treat exceptions thrown by the await_resume ()
2217 of the initial suspend expression. In order to implement this, we
2218 need to treat the initial_suspend expression as if it were part of the
2219 user-authored function body. This only applies if exceptions are
2221 if (flag_exceptions
)
2223 tree outer
= fnbody
;
2224 if (TREE_CODE (outer
) == BIND_EXPR
)
2225 outer
= BIND_EXPR_BODY (outer
);
2226 gcc_checking_assert (TREE_CODE (outer
) == TRY_BLOCK
);
2227 tree sl
= TRY_STMTS (outer
);
2228 if (TREE_CODE (sl
) == STATEMENT_LIST
)
2230 tree_stmt_iterator si
= tsi_start (sl
);
2231 tsi_link_before (&si
, initial_await_stmt
, TSI_NEW_STMT
);
2235 tree new_try
= NULL_TREE
;
2236 append_to_statement_list (initial_await_stmt
, &new_try
);
2237 append_to_statement_list (sl
, &new_try
);
2238 TRY_STMTS (outer
) = new_try
;
2242 add_stmt (initial_await_stmt
);
2244 /* Transform the await expressions in the function body. Only do each
2246 hash_set
<tree
> pset
;
2247 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2249 /* Add in our function body with the co_returns rewritten to final form. */
2252 /* Final suspend starts here. */
2253 r
= build_stmt (loc
, LABEL_EXPR
, fs_label
);
2256 /* Set the actor pointer to null, so that 'done' will work.
2257 Resume from here is UB anyway - although a 'ready' await will
2258 branch to the final resume, and fall through to the destroy. */
2260 = lookup_member (coro_frame_type
, get_identifier ("__resume"),
2261 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2262 tree res_x
= build_class_member_access_expr (actor_frame
, resume_m
, NULL_TREE
,
2263 false, tf_warning_or_error
);
2264 r
= build1 (CONVERT_EXPR
, act_des_fn_ptr
, integer_zero_node
);
2265 r
= build2 (INIT_EXPR
, act_des_fn_ptr
, res_x
, r
);
2266 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2269 /* Get a reference to the final suspend var in the frame. */
2270 transform_await_expr (final_await
, &xform
);
2271 r
= coro_build_expr_stmt (final_await
, loc
);
2274 /* now do the tail of the function. */
2275 tree del_promise_label
2276 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2277 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2280 /* Destructors for the things we built explicitly. */
2281 r
= build_special_member_call (ap
, complete_dtor_identifier
, NULL
,
2282 promise_type
, LOOKUP_NORMAL
,
2283 tf_warning_or_error
);
2286 tree del_frame_label
2287 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2288 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2291 /* Here deallocate the frame (if we allocated it), which we will have at
2294 = lookup_member (coro_frame_type
, get_identifier ("__frame_needs_free"), 1,
2295 0, tf_warning_or_error
);
2296 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2297 false, tf_warning_or_error
);
2299 tree need_free_if
= begin_if_stmt ();
2300 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2301 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2302 finish_if_stmt_cond (cmp
, need_free_if
);
2303 if (param_dtor_list
!= NULL
)
2307 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2310 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2311 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2312 false, tf_warning_or_error
);
2313 tree t
= TREE_TYPE (a
);
2316 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2317 LOOKUP_NORMAL
, tf_warning_or_error
);
2322 /* [dcl.fct.def.coroutine] / 12
2323 The deallocation function’s name is looked up in the scope of the promise
2324 type. If this lookup fails, the deallocation function’s name is looked up
2325 in the global scope. If deallocation function lookup finds both a usual
2326 deallocation function with only a pointer parameter and a usual
2327 deallocation function with both a pointer parameter and a size parameter,
2328 then the selected deallocation function shall be the one with two
2329 parameters. Otherwise, the selected deallocation function shall be the
2330 function with one parameter. If no usual deallocation function is found
2331 the program is ill-formed. The selected deallocation function shall be
2332 called with the address of the block of storage to be reclaimed as its
2333 first argument. If a deallocation function with a parameter of type
2334 std::size_t is used, the size of the block is passed as the corresponding
2337 tree del_coro_fr
= NULL_TREE
;
2338 tree frame_arg
= build1 (CONVERT_EXPR
, ptr_type_node
, actor_fp
);
2340 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2341 tree fns
= lookup_promise_method (orig
, delname
, loc
, /*musthave=*/false);
2342 if (fns
&& BASELINK_P (fns
))
2344 /* Look for sized version first, since this takes precedence. */
2345 vec
<tree
, va_gc
> *args
= make_tree_vector ();
2346 vec_safe_push (args
, frame_arg
);
2347 vec_safe_push (args
, frame_size
);
2348 tree dummy_promise
= build_dummy_object (promise_type
);
2350 /* It's OK to fail for this one... */
2351 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2352 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2355 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2357 release_tree_vector (args
);
2358 args
= make_tree_vector_single (frame_arg
);
2359 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2360 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2364 /* But one of them must succeed, or the program is ill-formed. */
2365 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2367 error_at (loc
, "%qE is provided by %qT but is not usable with"
2368 " the function signature %qD", delname
, promise_type
, orig
);
2369 del_coro_fr
= error_mark_node
;
2374 del_coro_fr
= build_op_delete_call (DELETE_EXPR
, frame_arg
, frame_size
,
2375 /*global_p=*/true, /*placement=*/NULL
,
2377 tf_warning_or_error
);
2378 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2379 del_coro_fr
= error_mark_node
;
2382 del_coro_fr
= coro_build_cvt_void_expr_stmt (del_coro_fr
, loc
);
2383 add_stmt (del_coro_fr
);
2384 finish_then_clause (need_free_if
);
2385 tree scope
= IF_SCOPE (need_free_if
);
2386 IF_SCOPE (need_free_if
) = NULL
;
2387 r
= do_poplevel (scope
);
2391 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2392 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2393 r
= maybe_cleanup_point_expr_void (r
);
2396 /* This is the suspend return point. */
2397 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2400 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2401 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2402 r
= maybe_cleanup_point_expr_void (r
);
2405 /* This is the 'continuation' return point. For such a case we have a coro
2406 handle (from the await_suspend() call) and we want handle.resume() to
2407 execute as a tailcall allowing arbitrary chaining of coroutines. */
2408 r
= build_stmt (loc
, LABEL_EXPR
, continue_label
);
2411 /* We want to force a tail-call even for O0/1, so this expands the resume
2412 call into its underlying implementation. */
2413 tree addr
= lookup_member (void_coro_handle_type
, coro_address_identifier
,
2414 1, 0, tf_warning_or_error
);
2415 addr
= build_new_method_call (continuation
, addr
, NULL
, NULL_TREE
,
2416 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
2417 tree resume
= build_call_expr_loc
2418 (loc
, builtin_decl_explicit (BUILT_IN_CORO_RESUME
), 1, addr
);
2420 /* In order to support an arbitrary number of coroutine continuations,
2421 we must tail call them. However, some targets do not support indirect
2422 tail calls to arbitrary callees. See PR94359. */
2423 CALL_EXPR_TAILCALL (resume
) = true;
2424 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
2427 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2428 gcc_checking_assert (maybe_cleanup_point_expr_void (r
) == r
);
2431 /* We will need to know which resume point number should be encoded. */
2433 = lookup_member (coro_frame_type
, resume_idx_name
,
2434 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2435 tree resume_pt_number
2436 = build_class_member_access_expr (actor_frame
, res_idx_m
, NULL_TREE
, false,
2437 tf_warning_or_error
);
2439 /* Boolean value to flag that the initial suspend expression's
2440 await_resume () has been called, and therefore we are in the user's
2441 function body for the purposes of handing exceptions. */
2443 = lookup_member (coro_frame_type
, get_identifier ("__i_a_r_c"),
2444 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2446 = build_class_member_access_expr (actor_frame
, i_a_r_c_m
, NULL_TREE
,
2447 false, tf_warning_or_error
);
2449 /* We've now rewritten the tree and added the initial and final
2450 co_awaits. Now pass over the tree and expand the co_awaits. */
2452 coro_aw_data data
= {actor
, actor_fp
, resume_pt_number
, i_a_r_c
,
2453 ash
, del_promise_label
, ret_label
,
2454 continue_label
, continuation
, 2};
2455 cp_walk_tree (&actor_body
, await_statement_expander
, &data
, NULL
);
2457 BIND_EXPR_BODY (actor_bind
) = pop_stmt_list (actor_body
);
2458 TREE_SIDE_EFFECTS (actor_bind
) = true;
2460 finish_compound_stmt (stmt
);
2461 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2462 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2465 /* The prototype 'destroy' function :
2466 frame->__resume_at |= 1;
2470 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2473 /* One param, the coro frame pointer. */
2474 tree destr_fp
= DECL_ARGUMENTS (destroy
);
2476 /* A void return. */
2477 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2478 DECL_ARTIFICIAL (resdecl
) = 1;
2479 DECL_IGNORED_P (resdecl
) = 1;
2480 DECL_RESULT (destroy
) = resdecl
;
2482 /* We have a definition here. */
2483 TREE_STATIC (destroy
) = 1;
2484 DECL_COROUTINE_P (destroy
) = 1;
2486 tree destr_outer
= push_stmt_list ();
2487 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2488 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2490 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2492 tree resume_idx_name
= get_identifier ("__resume_at");
2493 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2494 tf_warning_or_error
);
2495 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, destr_frame
,
2496 rat_field
, NULL_TREE
);
2498 /* _resume_at |= 1 */
2499 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2500 build_int_cst (short_unsigned_type_node
, 1));
2501 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2502 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2505 /* So .. call the actor .. */
2506 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2507 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2511 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2512 r
= maybe_cleanup_point_expr_void (r
);
2515 finish_compound_stmt (dstr_stmt
);
2516 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2519 /* Helper that returns an identifier for an appended extension to the
2520 current un-mangled function name. */
2523 get_fn_local_identifier (tree orig
, const char *append
)
2525 /* Figure out the bits we need to generate names for the outlined things
2526 For consistency, this needs to behave the same way as
2527 ASM_FORMAT_PRIVATE_NAME does. */
2528 tree nm
= DECL_NAME (orig
);
2529 const char *sep
, *pfx
= "";
2530 #ifndef NO_DOT_IN_LABEL
2533 #ifndef NO_DOLLAR_IN_LABEL
2542 if (DECL_ASSEMBLER_NAME (orig
))
2543 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2545 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2546 && DECL_TI_ARGS (orig
))
2548 tree tpl_args
= DECL_TI_ARGS (orig
);
2549 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2550 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2552 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2553 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2555 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2558 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2560 return get_identifier (an
);
2564 build_init_or_final_await (location_t loc
, bool is_final
)
2566 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2567 : coro_initial_suspend_identifier
;
2568 tree setup_meth
= lookup_promise_method (current_function_decl
, suspend_alt
,
2569 loc
, /*musthave=*/true);
2570 if (!setup_meth
|| setup_meth
== error_mark_node
)
2571 return error_mark_node
;
2573 tree s_fn
= NULL_TREE
;
2574 tree setup_call
= build_new_method_call (
2575 get_coroutine_promise_proxy (current_function_decl
), setup_meth
, NULL
,
2576 NULL_TREE
, LOOKUP_NORMAL
, &s_fn
, tf_warning_or_error
);
2578 if (!s_fn
|| setup_call
== error_mark_node
)
2579 return error_mark_node
;
2581 /* So build the co_await for this */
2582 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2583 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2584 : INITIAL_SUSPEND_POINT
));
2587 /* Callback to record the essential data for each await point found in the
2591 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
)
2594 suspend_point_info
&s
2595 = suspend_points
->get_or_insert (await_expr
, &seen
);
2598 error_at (EXPR_LOCATION (await_expr
), "duplicate info for %qE",
2602 s
.awaitable_type
= aw_type
;
2603 s
.await_field_id
= aw_nam
;
2607 /* Small helper for the repetitive task of adding a new field to the coro
2611 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
2614 tree id
= get_identifier (name
);
2615 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
2616 DECL_CHAIN (decl
) = *field_list
;
2621 /* This data set is used when analyzing statements for await expressions. */
2622 struct susp_frame_data
2624 /* Function-wide. */
2625 tree
*field_list
; /* The current coroutine frame field list. */
2626 tree handle_type
; /* The self-handle type for this coroutine. */
2627 vec
<tree
, va_gc
> *block_stack
; /* Track block scopes. */
2628 vec
<tree
, va_gc
> *bind_stack
; /* Track current bind expr. */
2629 unsigned await_number
; /* Which await in the function. */
2630 unsigned cond_number
; /* Which replaced condition in the fn. */
2631 /* Temporary values for one statement or expression being analyzed. */
2632 hash_set
<tree
> captured_temps
; /* The suspend captured these temps. */
2633 vec
<tree
, va_gc
> *to_replace
; /* The VAR decls to replace. */
2634 hash_set
<tree
> *truth_aoif_to_expand
; /* The set of TRUTH exprs to expand. */
2635 unsigned saw_awaits
; /* Count of awaits in this statement */
2636 bool captures_temporary
; /* This expr captures temps by ref. */
2637 bool needs_truth_if_exp
; /* We must expand a truth_if expression. */
2640 /* Walk the sub-tree looking for call expressions that both capture
2641 references and have compiler-temporaries as parms. */
2644 captures_temporary (tree
*stmt
, int *do_subtree
, void *d
)
2646 /* We should have already lowered co_yields to their co_await. */
2647 gcc_checking_assert (TREE_CODE (*stmt
) != CO_YIELD_EXPR
);
2649 /* Stop recursing if we see an await expression, the subtrees
2650 of that will be handled when it is processed. */
2651 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
2657 /* We're only interested in calls. */
2658 if (TREE_CODE (*stmt
) != CALL_EXPR
)
2661 /* Does this call capture references?
2662 Strip the ADDRESS_EXPR to get the fn decl and inspect it. */
2663 tree fn
= TREE_OPERAND (CALL_EXPR_FN (*stmt
), 0);
2664 bool is_meth
= TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
;
2665 tree arg
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2666 unsigned offset
= 3;
2667 for (unsigned anum
= 0; arg
!= NULL
; arg
= TREE_CHAIN (arg
), anum
++)
2669 tree parm_type
= TREE_VALUE (arg
);
2670 if (anum
== 0 && is_meth
&& INDIRECT_TYPE_P (parm_type
))
2672 /* Account for 'this' when the fn is a method. Unless it
2673 belongs to a CTOR or DTOR. */
2674 if (DECL_CONSTRUCTOR_P (fn
) || DECL_DESTRUCTOR_P (fn
))
2677 else if (!TYPE_REF_P (parm_type
))
2678 /* If it's not a reference, we don't care. */
2681 /* Fetch the value presented to the fn. */
2682 tree parm
= TREE_OPERAND (*stmt
, anum
+ offset
);
2684 while (TREE_CODE (parm
) == NOP_EXPR
)
2685 parm
= TREE_OPERAND (parm
, 0);
2687 /* We only care if we're taking the addr of a temporary. */
2688 if (TREE_CODE (parm
) != ADDR_EXPR
)
2691 parm
= TREE_OPERAND (parm
, 0);
2693 /* In case of component_ref, we need to capture the object of base
2694 class as if it is temporary object. There are two possibilities:
2695 (*base).field and base->field. */
2696 while (TREE_CODE (parm
) == COMPONENT_REF
)
2698 parm
= TREE_OPERAND (parm
, 0);
2699 if (TREE_CODE (parm
) == INDIRECT_REF
)
2700 parm
= TREE_OPERAND (parm
, 0);
2704 /* This isn't a temporary. */
2706 && (!DECL_ARTIFICIAL (parm
) || DECL_HAS_VALUE_EXPR_P (parm
)))
2707 || TREE_CODE (parm
) == PARM_DECL
2708 || TREE_CODE (parm
) == NON_LVALUE_EXPR
)
2711 if (TREE_CODE (parm
) == TARGET_EXPR
)
2713 /* We're taking the address of a temporary and using it as a ref. */
2714 tree tvar
= TREE_OPERAND (parm
, 0);
2715 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2717 susp_frame_data
*data
= (susp_frame_data
*) d
;
2718 data
->captures_temporary
= true;
2719 /* Record this one so we don't duplicate, and on the first
2720 occurrence note the target expr to be replaced. */
2721 if (!data
->captured_temps
.add (tvar
))
2722 vec_safe_push (data
->to_replace
, parm
);
2723 /* Now see if the initializer contains any more cases. */
2724 hash_set
<tree
> visited
;
2725 tree res
= cp_walk_tree (&TREE_OPERAND (parm
, 1),
2726 captures_temporary
, d
, &visited
);
2729 /* Otherwise, we're done with sub-trees for this. */
2731 else if (TREE_CODE (parm
) == CO_AWAIT_EXPR
)
2733 /* CO_AWAIT expressions behave in a similar manner to target
2734 expressions when the await_resume call is contained in one. */
2735 tree awr
= TREE_OPERAND (parm
, 3); /* call vector. */
2736 awr
= TREE_VEC_ELT (awr
, 2); /* resume call. */
2737 if (TREE_CODE (awr
) == TARGET_EXPR
)
2739 tree tvar
= TREE_OPERAND (awr
, 0);
2740 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2742 susp_frame_data
*data
= (susp_frame_data
*) d
;
2743 data
->captures_temporary
= true;
2744 /* Use this as a place-holder. */
2745 if (!data
->captured_temps
.add (tvar
))
2746 vec_safe_push (data
->to_replace
, parm
);
2748 /* We will walk the sub-trees of this co_await separately. */
2753 /* As far as it's necessary, we've walked the subtrees of the call
2759 /* If this is an await, then register it and decide on what coro
2760 frame storage is needed.
2761 If this is a co_yield (which embeds an await), drop the yield
2762 and record the await (the yield was kept for diagnostics only). */
2765 register_awaits (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
2767 susp_frame_data
*data
= (susp_frame_data
*) d
;
2769 /* We should have already lowered co_yields to their co_await. */
2770 gcc_checking_assert (TREE_CODE (*stmt
) != CO_YIELD_EXPR
);
2772 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
)
2775 tree aw_expr
= *stmt
;
2776 location_t aw_loc
= EXPR_LOCATION (aw_expr
); /* location of the co_xxxx. */
2778 /* If the awaitable is a parm or a local variable, then we already have
2779 a frame copy, so don't make a new one. */
2780 tree aw
= TREE_OPERAND (aw_expr
, 1);
2781 tree aw_field_type
= TREE_TYPE (aw
);
2782 tree aw_field_nam
= NULL_TREE
;
2783 if (INDIRECT_REF_P (aw
))
2784 aw
= TREE_OPERAND (aw
, 0);
2785 if (TREE_CODE (aw
) == PARM_DECL
2786 || (VAR_P (aw
) && (!DECL_ARTIFICIAL (aw
)
2787 || DECL_HAS_VALUE_EXPR_P (aw
))))
2788 ; /* Don't make an additional copy. */
2791 /* The required field has the same type as the proxy stored in the
2793 char *nam
= xasprintf ("__aw_s.%d", data
->await_number
);
2794 aw_field_nam
= coro_make_frame_entry (data
->field_list
, nam
,
2795 aw_field_type
, aw_loc
);
2799 tree o
= TREE_OPERAND (aw_expr
, 2); /* Initialiser for the frame var. */
2800 /* If this is a target expression, then we need to remake it to strip off
2801 any extra cleanups added. */
2802 if (TREE_CODE (o
) == TARGET_EXPR
)
2803 TREE_OPERAND (aw_expr
, 2) = get_target_expr (TREE_OPERAND (o
, 1));
2805 tree v
= TREE_OPERAND (aw_expr
, 3);
2806 o
= TREE_VEC_ELT (v
, 1);
2807 if (TREE_CODE (o
) == TARGET_EXPR
)
2808 TREE_VEC_ELT (v
, 1) = get_target_expr (TREE_OPERAND (o
, 1));
2810 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
);
2812 /* Count how many awaits the current expression contains. */
2814 /* Each await suspend context is unique, this is a function-wide value. */
2815 data
->await_number
++;
2817 /* We now need to know if to take special action on lifetime extension
2818 of temporaries captured by reference. This can only happen if such
2819 a case appears in the initializer for the awaitable. The callback
2820 records captured temporaries including subtrees of initializers. */
2821 hash_set
<tree
> visited
;
2822 tree res
= cp_walk_tree (&TREE_OPERAND (aw_expr
, 2), captures_temporary
, d
,
2827 /* The gimplifier correctly extends the lifetime of temporaries captured
2828 by reference (per. [class.temporary] (6.9) "A temporary object bound
2829 to a reference parameter in a function call persists until the completion
2830 of the full-expression containing the call"). However, that is not
2831 sufficient to work across a suspension - and we need to promote such
2832 temporaries to be regular vars that will then get a coro frame slot.
2833 We don't want to incur the effort of checking for this unless we have
2834 an await expression in the current full expression. */
2836 /* This takes the statement which contains one or more temporaries that have
2837 been 'captured' by reference in the initializer(s) of co_await(s).
2838 The statement is replaced by a bind expression that has actual variables
2839 to replace the temporaries. These variables will be added to the coro-
2840 frame in the same manner as user-authored ones. */
2843 replace_statement_captures (tree
*stmt
, void *d
)
2845 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2846 location_t sloc
= EXPR_LOCATION (*stmt
);
2848 = build3_loc (sloc
, BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2850 /* Any cleanup point expression might no longer be necessary, since we
2851 are removing one or more temporaries. */
2852 tree aw_statement_current
= *stmt
;
2853 if (TREE_CODE (aw_statement_current
) == CLEANUP_POINT_EXPR
)
2854 aw_statement_current
= TREE_OPERAND (aw_statement_current
, 0);
2856 /* Collected the scope vars we need move the temps to regular. */
2857 tree aw_bind_body
= push_stmt_list ();
2858 tree varlist
= NULL_TREE
;
2860 while (!awpts
->to_replace
->is_empty ())
2862 tree to_replace
= awpts
->to_replace
->pop ();
2864 if (TREE_CODE (to_replace
) == CO_AWAIT_EXPR
)
2866 orig_temp
= TREE_OPERAND (to_replace
, 3);
2867 orig_temp
= TREE_VEC_ELT (orig_temp
, 2);
2868 orig_temp
= TREE_OPERAND (orig_temp
, 0);
2871 orig_temp
= TREE_OPERAND (to_replace
, 0);
2873 tree var_type
= TREE_TYPE (orig_temp
);
2874 gcc_checking_assert (same_type_p (TREE_TYPE (to_replace
), var_type
));
2875 /* Build a variable to hold the captured value, this will be included
2876 in the frame along with any user-authored locals. */
2877 char *nam
= xasprintf ("aw_%d.tmp.%d", awpts
->await_number
, ++vnum
);
2878 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
2880 /* If we have better location than the whole expression use that, else
2881 fall back to the expression loc. */
2882 DECL_CONTEXT (newvar
) = DECL_CONTEXT (orig_temp
);
2883 if (DECL_SOURCE_LOCATION (orig_temp
))
2884 sloc
= DECL_SOURCE_LOCATION (orig_temp
);
2886 sloc
= EXPR_LOCATION (*stmt
);
2887 DECL_SOURCE_LOCATION (newvar
) = sloc
;
2888 DECL_CHAIN (newvar
) = varlist
;
2889 varlist
= newvar
; /* Chain it onto the list for the bind expr. */
2890 /* Declare and initialize it in the new bind scope. */
2891 add_decl_expr (newvar
);
2892 tree new_s
= build2_loc (sloc
, INIT_EXPR
, var_type
, newvar
, to_replace
);
2893 new_s
= coro_build_cvt_void_expr_stmt (new_s
, sloc
);
2896 /* Replace all instances of that temp in the original expr. */
2897 proxy_replace pr
= {to_replace
, newvar
};
2898 cp_walk_tree (&aw_statement_current
, replace_proxy
, &pr
, NULL
);
2901 /* What's left should be the original statement with any co_await captured
2902 temporaries broken out. Other temporaries might remain so see if we
2903 need to wrap the revised statement in a cleanup. */
2904 aw_statement_current
= maybe_cleanup_point_expr_void (aw_statement_current
);
2905 add_stmt (aw_statement_current
);
2907 BIND_EXPR_BODY (aw_bind
) = pop_stmt_list (aw_bind_body
);
2908 awpts
->captured_temps
.empty ();
2910 BIND_EXPR_VARS (aw_bind
) = nreverse (varlist
);
2911 tree b_block
= make_node (BLOCK
);
2912 if (!awpts
->block_stack
->is_empty ())
2914 tree s_block
= awpts
->block_stack
->last ();
2917 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
2918 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
2919 BLOCK_SUBBLOCKS (s_block
) = b_block
;
2922 BIND_EXPR_BLOCK (aw_bind
) = b_block
;
2923 TREE_SIDE_EFFECTS (aw_bind
) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (aw_bind
));
2927 /* This is called for single statements from the co-await statement walker.
2928 It checks to see if the statement contains any co-awaits and, if so,
2929 whether any of these 'capture' a temporary by reference. */
2932 maybe_promote_captured_temps (tree
*stmt
, void *d
)
2934 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2935 hash_set
<tree
> visited
;
2936 awpts
->saw_awaits
= 0;
2938 /* When register_awaits sees an await, it walks the initializer for
2939 that await looking for temporaries captured by reference and notes
2940 them in awpts->captured_temps. */
2942 if (tree res
= cp_walk_tree (stmt
, register_awaits
, d
, &visited
))
2943 return res
; /* We saw some reason to abort the tree walk. */
2945 /* We only need to take any action here if the statement contained any
2946 awaits and any of those had temporaries captured by reference in their
2949 if (awpts
->saw_awaits
> 0 && !awpts
->captured_temps
.is_empty ())
2950 replace_statement_captures (stmt
, d
);
2955 /* Lightweight callback to determine two key factors:
2956 1) If the statement/expression contains any await expressions.
2957 2) If the statement/expression potentially requires a re-write to handle
2958 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
2959 so that the await expressions are not processed in the case of the
2961 CO_YIELD expressions are re-written to their underlying co_await. */
2964 analyze_expression_awaits (tree
*stmt
, int *do_subtree
, void *d
)
2966 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2968 switch (TREE_CODE (*stmt
))
2970 default: return NULL_TREE
;
2972 /* co_yield is syntactic sugar, re-write it to co_await. */
2973 *stmt
= TREE_OPERAND (*stmt
, 1);
2976 awpts
->saw_awaits
++;
2978 case TRUTH_ANDIF_EXPR
:
2979 case TRUTH_ORIF_EXPR
:
2981 /* We don't need special action for awaits in the always-executed
2982 arm of a TRUTH_IF. */
2983 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 0),
2984 analyze_expression_awaits
, d
, NULL
))
2986 /* However, if there are await expressions on the conditionally
2987 executed branch, we must expand the TRUTH_IF to ensure that the
2988 expanded await expression control-flow is fully contained in the
2989 conditionally executed code. */
2990 unsigned aw_count
= awpts
->saw_awaits
;
2991 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 1),
2992 analyze_expression_awaits
, d
, NULL
))
2994 if (awpts
->saw_awaits
> aw_count
)
2996 awpts
->truth_aoif_to_expand
->add (*stmt
);
2997 awpts
->needs_truth_if_exp
= true;
2999 /* We've done the sub-trees here. */
3005 return NULL_TREE
; /* Recurse until done. */
3009 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3010 the conditional branch expand this to:
3012 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3013 A) bool t = always exec expr
3015 B) t = conditionally exec expr
3016 c) EXPR' = EXPR with TAOIE replaced by t.
3018 Then repeat this for A, B and C. */
3020 struct truth_if_transform
{
3023 hash_set
<tree
> *truth_aoif_to_expand
;
3027 expand_one_truth_if (tree
*expr
, int *do_subtree
, void *d
)
3029 truth_if_transform
*xform
= (truth_if_transform
*) d
;
3031 bool needs_not
= false;
3032 switch (TREE_CODE (*expr
))
3035 case TRUTH_ORIF_EXPR
:
3038 case TRUTH_ANDIF_EXPR
:
3040 if (!xform
->truth_aoif_to_expand
->contains (*expr
))
3043 location_t sloc
= EXPR_LOCATION (*expr
);
3044 tree type
= TREE_TYPE (xform
->scratch_var
);
3045 gcc_checking_assert (TREE_CODE (type
) == BOOLEAN_TYPE
);
3046 tree new_list
= push_stmt_list ();
3047 /* Init our scratch with the unconditionally-evaluated expr. */
3048 tree new_s
= build2_loc (sloc
, INIT_EXPR
, boolean_type_node
,
3050 TREE_OPERAND (*expr
, 0));
3051 finish_expr_stmt (new_s
);
3052 tree
*pre
= tsi_stmt_ptr (tsi_last (new_list
));
3053 tree if_cond
= xform
->scratch_var
;
3055 if_cond
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, if_cond
);
3056 tree if_stmt
= begin_if_stmt ();
3057 finish_if_stmt_cond (if_cond
, if_stmt
);
3058 /* If we take the if branch, then overwrite scratch with the cond
3060 new_s
= build2 (INIT_EXPR
, boolean_type_node
,
3061 xform
->scratch_var
, TREE_OPERAND (*expr
, 1));
3062 finish_expr_stmt (new_s
);
3063 finish_then_clause (if_stmt
);
3064 finish_if_stmt (if_stmt
);
3065 *expr
= xform
->scratch_var
; /* now contains the result. */
3066 /* So now we've got a statement list expanding one TAOIe. */
3067 add_stmt (*xform
->orig_stmt
);
3068 tree
*post
= tsi_stmt_ptr (tsi_last (new_list
));
3069 *xform
->orig_stmt
= pop_stmt_list (new_list
);
3070 /* Now recurse into the pre, if and post parts. */
3071 truth_if_transform sub_data
= {pre
, xform
->scratch_var
,
3072 xform
->truth_aoif_to_expand
};
3073 if (tree res
= cp_walk_tree (pre
, expand_one_truth_if
, &sub_data
,
3076 sub_data
.orig_stmt
= &THEN_CLAUSE (if_stmt
);
3077 if (tree res
= cp_walk_tree (&THEN_CLAUSE (if_stmt
),
3078 expand_one_truth_if
, &sub_data
, NULL
))
3080 sub_data
.orig_stmt
= post
;
3081 if (tree res
= cp_walk_tree (post
, expand_one_truth_if
, &sub_data
,
3084 /* We've done the sub-trees here. */
3092 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3093 name is made up from NAM_ROOT, NAM_VERS. */
3096 add_var_to_bind (tree
& bind
, tree var_type
,
3097 const char *nam_root
, unsigned nam_vers
)
3100 tree b_vars
= BIND_EXPR_VARS (bind
);
3101 /* Build a variable to hold the condition, this will be included in the
3102 frame as a local var. */
3103 char *nam
= xasprintf ("%s.%d", nam_root
, nam_vers
);
3104 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
3106 DECL_CHAIN (newvar
) = b_vars
;
3107 BIND_EXPR_VARS (bind
) = newvar
;
3111 /* Helper to build and add if (!cond) break; */
3114 coro_build_add_if_not_cond_break (tree cond
)
3116 tree if_stmt
= begin_if_stmt ();
3117 tree invert
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3118 finish_if_stmt_cond (invert
, if_stmt
);
3119 finish_break_stmt ();
3120 finish_then_clause (if_stmt
);
3121 finish_if_stmt (if_stmt
);
3124 /* Tree walk callback to analyze, register and pre-process statements that
3125 contain await expressions. */
3128 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
3130 tree res
= NULL_TREE
;
3131 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3133 /* Process a statement at a time. */
3134 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3136 /* For conditional expressions, we might wish to add an artificial var
3137 to their containing bind expr. */
3138 vec_safe_push (awpts
->bind_stack
, *stmt
);
3139 /* We might need to insert a new bind expression, and want to link it
3140 into the correct scope, so keep a note of the current block scope. */
3141 tree blk
= BIND_EXPR_BLOCK (*stmt
);
3142 vec_safe_push (awpts
->block_stack
, blk
);
3143 res
= cp_walk_tree (&BIND_EXPR_BODY (*stmt
), await_statement_walker
,
3145 awpts
->block_stack
->pop ();
3146 awpts
->bind_stack
->pop ();
3147 *do_subtree
= 0; /* Done subtrees. */
3150 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
3152 tree_stmt_iterator i
;
3153 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
3155 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_walker
,
3160 *do_subtree
= 0; /* Done subtrees. */
3164 /* We have something to be handled as a single statement. */
3165 hash_set
<tree
> visited
;
3166 awpts
->saw_awaits
= 0;
3167 hash_set
<tree
> truth_aoif_to_expand
;
3168 awpts
->truth_aoif_to_expand
= &truth_aoif_to_expand
;
3169 awpts
->needs_truth_if_exp
= false;
3171 if (STATEMENT_CLASS_P (*stmt
))
3172 switch (TREE_CODE (*stmt
))
3174 /* Unless it's a special case, just walk the subtrees as usual. */
3175 default: return NULL_TREE
;
3177 /* When we have a conditional expression, which contains one or more
3178 await expressions, we have to break the condition out into a
3179 regular statement so that the control flow introduced by the await
3180 transforms can be implemented. */
3183 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3184 bool cond = cond with awaits.
3185 if (cond) then stmt1 else stmt2. */
3186 tree if_stmt
= *stmt
;
3187 /* We treat the condition as if it was a stand-alone statement,
3188 to see if there are any await expressions which will be analysed
3190 if ((res
= cp_walk_tree (&IF_COND (if_stmt
),
3191 analyze_expression_awaits
, d
, &visited
)))
3193 if (!awpts
->saw_awaits
)
3194 return NULL_TREE
; /* Nothing special to do here. */
3196 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3197 tree
& bind_expr
= awpts
->bind_stack
->last ();
3198 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3199 "ifcd", awpts
->cond_number
++);
3200 tree insert_list
= push_stmt_list ();
3201 tree cond_inner
= IF_COND (if_stmt
);
3202 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3203 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3204 add_decl_expr (newvar
);
3205 location_t sloc
= EXPR_LOCATION (IF_COND (if_stmt
));
3206 /* We want to initialize the new variable with the expression
3207 that contains the await(s) and potentially also needs to
3208 have truth_if expressions expanded. */
3209 tree new_s
= build2_loc (sloc
, MODIFY_EXPR
, boolean_type_node
,
3210 newvar
, cond_inner
);
3211 finish_expr_stmt (new_s
);
3212 if (awpts
->needs_truth_if_exp
)
3214 tree
*sp
= tsi_stmt_ptr (tsi_last (insert_list
));
3215 truth_if_transform xf
= {sp
, newvar
, &truth_aoif_to_expand
};
3216 if ((res
= cp_walk_tree (sp
, expand_one_truth_if
, &xf
, NULL
)))
3219 IF_COND (if_stmt
) = newvar
;
3221 *stmt
= pop_stmt_list (insert_list
);
3222 /* So now walk the new statement list. */
3223 res
= cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3224 *do_subtree
= 0; /* Done subtrees. */
3230 /* We turn 'while (cond with awaits) stmt' into
3232 if (!(cond with awaits))
3236 tree while_stmt
= *stmt
;
3237 if ((res
= cp_walk_tree (&WHILE_COND (while_stmt
),
3238 analyze_expression_awaits
, d
, &visited
)))
3240 if (!awpts
->saw_awaits
)
3241 return NULL_TREE
; /* Nothing special to do here. */
3243 tree insert_list
= push_stmt_list ();
3244 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt
));
3245 /* The original while body. */
3246 add_stmt (WHILE_BODY (while_stmt
));
3247 /* The new while body. */
3248 WHILE_BODY (while_stmt
) = pop_stmt_list (insert_list
);
3249 WHILE_COND (while_stmt
) = boolean_true_node
;
3250 /* So now walk the new statement list. */
3251 res
= cp_walk_tree (&WHILE_BODY (while_stmt
),
3252 await_statement_walker
, d
, NULL
);
3253 *do_subtree
= 0; /* Done subtrees. */
3259 /* We turn do stmt while (cond with awaits) into:
3262 if (!(cond with awaits))
3265 tree do_stmt
= *stmt
;
3266 if ((res
= cp_walk_tree (&DO_COND (do_stmt
),
3267 analyze_expression_awaits
, d
, &visited
)))
3269 if (!awpts
->saw_awaits
)
3270 return NULL_TREE
; /* Nothing special to do here. */
3272 tree insert_list
= push_stmt_list ();
3273 /* The original do stmt body. */
3274 add_stmt (DO_BODY (do_stmt
));
3275 coro_build_add_if_not_cond_break (DO_COND (do_stmt
));
3276 /* The new while body. */
3277 DO_BODY (do_stmt
) = pop_stmt_list (insert_list
);
3278 DO_COND (do_stmt
) = boolean_true_node
;
3279 /* So now walk the new statement list. */
3280 res
= cp_walk_tree (&DO_BODY (do_stmt
), await_statement_walker
,
3282 *do_subtree
= 0; /* Done subtrees. */
3289 /* We turn 'switch (cond with awaits) stmt' into
3290 switch_type cond = cond with awaits
3291 switch (cond) stmt. */
3292 tree sw_stmt
= *stmt
;
3293 if ((res
= cp_walk_tree (&SWITCH_STMT_COND (sw_stmt
),
3294 analyze_expression_awaits
, d
, &visited
)))
3296 if (!awpts
->saw_awaits
)
3297 return NULL_TREE
; /* Nothing special to do here. */
3299 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3300 /* Build a variable to hold the condition, this will be
3301 included in the frame as a local var. */
3302 tree
& bind_expr
= awpts
->bind_stack
->last ();
3303 tree sw_type
= SWITCH_STMT_TYPE (sw_stmt
);
3304 tree newvar
= add_var_to_bind (bind_expr
, sw_type
, "swch",
3305 awpts
->cond_number
++);
3306 tree insert_list
= push_stmt_list ();
3307 add_decl_expr (newvar
);
3309 tree cond_inner
= SWITCH_STMT_COND (sw_stmt
);
3310 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3311 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3312 location_t sloc
= EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt
));
3313 tree new_s
= build2_loc (sloc
, INIT_EXPR
, sw_type
, newvar
,
3315 finish_expr_stmt (new_s
);
3316 SWITCH_STMT_COND (sw_stmt
) = newvar
;
3317 /* Now add the switch statement with the condition re-
3318 written to use the local var. */
3320 *stmt
= pop_stmt_list (insert_list
);
3321 /* Process the expanded list. */
3322 res
= cp_walk_tree (stmt
, await_statement_walker
,
3324 *do_subtree
= 0; /* Done subtrees. */
3329 else if (EXPR_P (*stmt
))
3331 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
, d
, &visited
)))
3333 *do_subtree
= 0; /* Done subtrees. */
3334 if (!awpts
->saw_awaits
)
3335 return NULL_TREE
; /* Nothing special to do here. */
3337 /* Unless we need to expand any truth-and/or-if expressions, then the
3338 remaining action is to check for temporaries to await expressions
3339 captured by refence. */
3340 if (!awpts
->needs_truth_if_exp
)
3341 return maybe_promote_captured_temps (stmt
, d
);
3343 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3344 tree
& bind_expr
= awpts
->bind_stack
->last ();
3345 /* Build a variable to hold the condition, this will be
3346 included in the frame as a local var. */
3347 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3348 "taoi", awpts
->cond_number
++);
3349 tree insert_list
= push_stmt_list ();
3350 add_decl_expr (newvar
);
3352 tree
*sp
= tsi_stmt_ptr (tsi_last (insert_list
));
3353 *stmt
= pop_stmt_list (insert_list
);
3355 truth_if_transform xf
= {sp
, newvar
, &truth_aoif_to_expand
};
3356 if ((res
= cp_walk_tree (sp
, expand_one_truth_if
, &xf
, NULL
)))
3358 /* Process the expanded trees. */
3359 return cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3362 /* Continue recursion, if needed. */
3366 /* For figuring out what param usage we have. */
3368 struct param_frame_data
3371 hash_map
<tree
, param_info
> *param_uses
;
3372 hash_set
<tree
*> *visited
;
3378 register_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
3380 param_frame_data
*data
= (param_frame_data
*) d
;
3382 /* For lambda closure content, we have to look specifically. */
3383 if (TREE_CODE (*stmt
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (*stmt
))
3385 tree t
= DECL_VALUE_EXPR (*stmt
);
3386 return cp_walk_tree (&t
, register_param_uses
, d
, NULL
);
3389 if (TREE_CODE (*stmt
) != PARM_DECL
)
3392 /* If we already saw the containing expression, then we're done. */
3393 if (data
->visited
->add (stmt
))
3397 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
3398 gcc_checking_assert (existed
);
3400 if (!parm
.body_uses
)
3402 vec_alloc (parm
.body_uses
, 4);
3403 parm
.body_uses
->quick_push (stmt
);
3404 data
->param_seen
= true;
3407 parm
.body_uses
->safe_push (stmt
);
3412 /* For figuring out what local variable usage we have. */
3414 struct local_vars_frame_data
3417 hash_map
<tree
, local_var_info
> *local_var_uses
;
3418 unsigned int nest_depth
, bind_indx
;
3421 bool local_var_seen
;
3425 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
3427 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
3429 /* As we enter a bind expression - record the vars there and then recurse.
3430 As we exit drop the nest depth.
3431 The bind index is a growing count of how many bind indices we've seen.
3432 We build a space in the frame for each local var. */
3434 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3439 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
3440 lvar
= DECL_CHAIN (lvar
))
3443 local_var_info
&local_var
3444 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
3445 gcc_checking_assert (!existed
);
3446 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
3447 tree lvtype
= TREE_TYPE (lvar
);
3448 local_var
.frame_type
= lvtype
;
3449 local_var
.field_idx
= local_var
.field_id
= NULL_TREE
;
3451 /* Make sure that we only present vars to the tests below. */
3452 if (TREE_CODE (lvar
) == TYPE_DECL
)
3455 /* We don't move static vars into the frame. */
3456 local_var
.is_static
= TREE_STATIC (lvar
);
3457 if (local_var
.is_static
)
3460 lvd
->local_var_seen
= true;
3461 /* If this var is a lambda capture proxy, we want to leave it alone,
3462 and later rewrite the DECL_VALUE_EXPR to indirect through the
3463 frame copy of the pointer to the lambda closure object. */
3464 local_var
.is_lambda_capture
= is_capture_proxy (lvar
);
3465 if (local_var
.is_lambda_capture
)
3468 /* If a variable has a value expression, then that's what needs
3470 local_var
.has_value_expr_p
= DECL_HAS_VALUE_EXPR_P (lvar
);
3471 if (local_var
.has_value_expr_p
)
3474 /* Make names depth+index unique, so that we can support nested
3475 scopes with identically named locals. */
3476 tree lvname
= DECL_NAME (lvar
);
3478 if (lvname
!= NULL_TREE
)
3479 buf
= xasprintf ("__lv.%u.%u.%s", lvd
->bind_indx
, lvd
->nest_depth
,
3480 IDENTIFIER_POINTER (lvname
));
3482 buf
= xasprintf ("__lv.%u.%u.D%u", lvd
->bind_indx
, lvd
->nest_depth
,
3484 /* TODO: Figure out if we should build a local type that has any
3485 excess alignment or size from the original decl. */
3487 = coro_make_frame_entry (lvd
->field_list
, buf
, lvtype
, lvd
->loc
);
3489 /* We don't walk any of the local var sub-trees, they won't contain
3492 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
3493 *do_subtree
= 0; /* We've done this. */
3499 /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
3500 for either actor or destroy functions. */
3503 act_des_fn (tree orig
, tree fn_type
, tree coro_frame_ptr
, const char* name
)
3505 tree fn_name
= get_fn_local_identifier (orig
, name
);
3506 tree fn
= build_lang_decl (FUNCTION_DECL
, fn_name
, fn_type
);
3507 DECL_CONTEXT (fn
) = DECL_CONTEXT (orig
);
3508 DECL_INITIAL (fn
) = error_mark_node
;
3509 tree id
= get_identifier ("frame_ptr");
3510 tree fp
= build_lang_decl (PARM_DECL
, id
, coro_frame_ptr
);
3511 DECL_CONTEXT (fp
) = fn
;
3512 DECL_ARG_TYPE (fp
) = type_passed_as (coro_frame_ptr
);
3513 DECL_ARGUMENTS (fn
) = fp
;
3517 /* Return a bind expression if we see one, else NULL_TREE. */
3519 bind_expr_find_in_subtree (tree
*stmt
, int *, void *)
3521 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3526 /* Return the first bind expression that the sub-tree given by STMT
3530 coro_body_contains_bind_expr_p (tree
*stmt
)
3532 hash_set
<tree
> visited
;
3533 return cp_walk_tree (stmt
, bind_expr_find_in_subtree
, NULL
, &visited
);
3537 a) Check that the function and promise type are valid for a
3539 b) Carry out the initial morph to create the skeleton of the
3540 coroutine ramp function and the rewritten body.
3544 1. We only hit this code once all dependencies are resolved.
3545 2. The function body will be either a bind expr or a statement list
3546 3. That cfun and current_function_decl are valid for the case we're
3548 4. 'input_location' will be of the final brace for the function.
3550 We do something like this:
3551 declare a dummy coro frame.
3553 using handle_type = coro::coroutine_handle<coro1::promise_type>;
3554 void (*__resume)(_R_frame *);
3555 void (*__destroy)(_R_frame *);
3556 coro1::promise_type __p;
3557 bool frame_needs_free; free the coro frame mem if set.
3558 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
3560 handle_type self_handle;
3561 (maybe) parameter copies.
3562 coro1::suspend_never_prt __is;
3563 coro1::suspend_always_prt __fs;
3564 (maybe) local variables saved
3565 (maybe) trailing space.
3569 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
3571 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
3573 *resumer
= error_mark_node
;
3574 *destroyer
= error_mark_node
;
3575 if (!coro_function_valid_p (orig
))
3577 /* For early errors, we do not want a diagnostic about the missing
3578 ramp return value, since the user cannot fix this - a 'return' is
3579 not allowed in a coroutine. */
3580 TREE_NO_WARNING (orig
) = true;
3581 /* Discard the body, we can't process it further. */
3582 pop_stmt_list (DECL_SAVED_TREE (orig
));
3583 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3587 /* We can't validly get here with an empty statement list, since there's no
3588 way for the FE to decide it's a coroutine in the absence of any code. */
3589 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
3590 gcc_checking_assert (fnbody
!= NULL_TREE
);
3592 /* We don't have the locus of the opening brace - it's filled in later (and
3593 there doesn't really seem to be any easy way to get at it).
3594 The closing brace is assumed to be input_location. */
3595 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
3596 gcc_rich_location
fn_start_loc (fn_start
);
3598 /* Initial processing of the function-body.
3599 If we have no expressions or just an error then punt. */
3600 tree body_start
= expr_first (fnbody
);
3601 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
3603 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3604 append_to_statement_list (fnbody
, &DECL_SAVED_TREE (orig
));
3605 /* Suppress warnings about the missing return value. */
3606 TREE_NO_WARNING (orig
) = true;
3610 /* So, we've tied off the original body. Now start the replacement.
3611 If we encounter a fatal error we might return a now-empty body.
3612 TODO: determine if it would help to restore the original.
3613 determine if looking for more errors in coro_function_valid_p()
3614 and stashing types is a better solution. */
3616 tree newbody
= push_stmt_list ();
3617 DECL_SAVED_TREE (orig
) = newbody
;
3619 /* If our original body is noexcept, then that's what we apply to our
3620 generated functions. Remember that we're NOEXCEPT and fish out the
3621 contained list (we tied off to the top level already). */
3622 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
3625 /* Simplified abstract from begin_eh_spec_block, since we already
3626 know the outcome. */
3627 fnbody
= TREE_OPERAND (body_start
, 0); /* Stash the original... */
3628 add_stmt (body_start
); /* ... and start the new. */
3629 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
3632 /* We can be presented with a function that currently has no outer bind
3633 expression. We will insert bind scopes in expanding await expressions,
3634 and therefore need a top level to the tree, so synthesize an outer bind
3635 expression and scope. */
3636 tree check_bind
= expr_first (fnbody
);
3637 if (check_bind
&& TREE_CODE (check_bind
) != BIND_EXPR
)
3639 tree update_body
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3640 tree blk
= make_node (BLOCK
);
3641 gcc_checking_assert (!coro_body_contains_bind_expr_p (&fnbody
));
3642 BIND_EXPR_BLOCK (update_body
) = blk
;
3643 if (TREE_CODE (fnbody
) == STATEMENT_LIST
)
3644 BIND_EXPR_BODY (update_body
) = fnbody
;
3647 tree tlist
= NULL_TREE
;
3648 append_to_statement_list_force (fnbody
, &tlist
);
3649 TREE_SIDE_EFFECTS (tlist
) = TREE_SIDE_EFFECTS (fnbody
);
3650 BIND_EXPR_BODY (update_body
) = tlist
;
3652 tree new_body_list
= NULL_TREE
;
3653 TREE_SIDE_EFFECTS (update_body
) = true;
3654 append_to_statement_list (update_body
, &new_body_list
);
3655 TREE_SIDE_EFFECTS (new_body_list
) = true;
3656 fnbody
= new_body_list
;
3659 /* Create the coro frame type, as far as it can be known at this stage.
3660 1. Types we already know. */
3662 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
3663 tree handle_type
= get_coroutine_handle_type (orig
);
3664 tree promise_type
= get_coroutine_promise_type (orig
);
3666 /* 2. Types we need to define or look up. */
3668 /* We need to know, and inspect, each suspend point in the function
3669 in several places. It's convenient to place this map out of line
3670 since it's used from tree walk callbacks. */
3671 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
3673 /* Initial and final suspend types are special in that the co_awaits for
3674 them are synthetic. We need to find the type for each awaiter from
3675 the coroutine promise. */
3676 tree initial_await
= build_init_or_final_await (fn_start
, false);
3677 if (initial_await
== error_mark_node
)
3679 /* Suppress warnings about the missing return value. */
3680 TREE_NO_WARNING (orig
) = true;
3683 /* The type of the frame var for this is the type of its temp proxy. */
3684 tree initial_suspend_type
= TREE_TYPE (TREE_OPERAND (initial_await
, 1));
3686 tree final_await
= build_init_or_final_await (fn_start
, true);
3687 if (final_await
== error_mark_node
)
3689 /* Suppress warnings about the missing return value. */
3690 TREE_NO_WARNING (orig
) = true;
3694 /* The type of the frame var for this is the type of its temp proxy. */
3695 tree final_suspend_type
= TREE_TYPE (TREE_OPERAND (final_await
, 1));
3697 tree fr_name
= get_fn_local_identifier (orig
, "frame");
3698 tree coro_frame_type
= xref_tag (record_type
, fr_name
, ts_current
, false);
3699 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
3700 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
3701 tree act_des_fn_type
3702 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
3703 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
3705 /* Declare the actor and destroyer function. */
3706 tree actor
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "actor");
3707 tree destroy
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "destroy");
3709 /* Build our dummy coro frame layout. */
3710 coro_frame_type
= begin_class_definition (coro_frame_type
);
3712 tree field_list
= NULL_TREE
;
3714 = coro_make_frame_entry (&field_list
, "__resume", act_des_fn_ptr
, fn_start
);
3715 tree destroy_name
= coro_make_frame_entry (&field_list
, "__destroy",
3716 act_des_fn_ptr
, fn_start
);
3718 = coro_make_frame_entry (&field_list
, "__p", promise_type
, fn_start
);
3719 tree fnf_name
= coro_make_frame_entry (&field_list
, "__frame_needs_free",
3720 boolean_type_node
, fn_start
);
3721 tree iarc_name
= coro_make_frame_entry (&field_list
, "__i_a_r_c",
3722 boolean_type_node
, fn_start
);
3723 tree resume_idx_name
3724 = coro_make_frame_entry (&field_list
, "__resume_at",
3725 short_unsigned_type_node
, fn_start
);
3727 /* We need a handle to this coroutine, which is passed to every
3728 await_suspend(). There's no point in creating it over and over. */
3729 (void) coro_make_frame_entry (&field_list
, "__self_h", handle_type
, fn_start
);
3731 /* Now add in fields for function params (if there are any).
3732 We do not attempt elision of copies at this stage, we do analyse the
3733 uses and build worklists to replace those when the state machine is
3736 hash_map
<tree
, param_info
> *param_uses
= NULL
;
3737 if (DECL_ARGUMENTS (orig
))
3739 /* Build a hash map with an entry for each param.
3740 The key is the param tree.
3741 Then we have an entry for the frame field name.
3742 Then a cache for the field ref when we come to use it.
3743 Then a tree list of the uses.
3744 The second two entries start out empty - and only get populated
3745 when we see uses. */
3746 param_uses
= new hash_map
<tree
, param_info
>;
3747 bool lambda_p
= LAMBDA_FUNCTION_P (orig
);
3749 unsigned no_name_parm
= 0;
3750 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3751 arg
= DECL_CHAIN (arg
))
3754 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3755 gcc_checking_assert (!existed
);
3756 parm
.body_uses
= NULL
;
3757 tree actual_type
= TREE_TYPE (arg
);
3758 actual_type
= complete_type_or_else (actual_type
, orig
);
3759 if (actual_type
== NULL_TREE
)
3760 actual_type
= error_mark_node
;
3761 parm
.orig_type
= actual_type
;
3762 parm
.by_ref
= parm
.pt_ref
= false;
3763 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
3765 /* If the user passes by reference, then we will save the
3766 pointer to the original. As noted in
3767 [dcl.fct.def.coroutine] / 13, if the lifetime of the
3768 referenced item ends and then the coroutine is resumed,
3769 we have UB; well, the user asked for it. */
3770 actual_type
= build_pointer_type (TREE_TYPE (actual_type
));
3773 else if (TYPE_REF_P (DECL_ARG_TYPE (arg
)))
3776 parm
.frame_type
= actual_type
;
3778 parm
.this_ptr
= is_this_parameter (arg
);
3779 /* See PR94807. When a lambda is in a template instantiation, the
3780 closure object is named 'this' instead of '__closure'. */
3783 parm
.lambda_cobj
= DECL_NAME (arg
) == closure_identifier
;
3784 gcc_checking_assert (!parm
.this_ptr
);
3787 parm
.lambda_cobj
= false;
3789 parm
.trivial_dtor
= TYPE_HAS_TRIVIAL_DESTRUCTOR (parm
.frame_type
);
3791 if (DECL_NAME (arg
))
3793 tree pname
= DECL_NAME (arg
);
3794 buf
= xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname
));
3797 buf
= xasprintf ("__unnamed_parm.%d", no_name_parm
++);
3798 parm
.field_id
= coro_make_frame_entry
3799 (&field_list
, buf
, actual_type
, DECL_SOURCE_LOCATION (arg
));
3803 /* We want to record every instance of param's use, so don't include
3804 a 'visited' hash_set on the tree walk, but only record a containing
3806 hash_set
<tree
*> visited
;
3807 param_frame_data param_data
3808 = {&field_list
, param_uses
, &visited
, fn_start
, false};
3809 cp_walk_tree (&fnbody
, register_param_uses
, ¶m_data
, NULL
);
3812 /* Initial suspend is mandated. */
3813 tree init_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.is",
3814 initial_suspend_type
, fn_start
);
3816 register_await_info (initial_await
, initial_suspend_type
, init_susp_name
);
3818 /* Now insert the data for any body await points, at this time we also need
3819 to promote any temporaries that are captured by reference (to regular
3820 vars) they will get added to the coro frame along with other locals. */
3821 susp_frame_data body_aw_points
3822 = {&field_list
, handle_type
, NULL
, NULL
, 0, 0,
3823 hash_set
<tree
> (), NULL
, NULL
, 0, false, false};
3824 body_aw_points
.block_stack
= make_tree_vector ();
3825 body_aw_points
.bind_stack
= make_tree_vector ();
3826 body_aw_points
.to_replace
= make_tree_vector ();
3827 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
3829 /* Final suspend is mandated. */
3830 tree fin_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.fs",
3831 final_suspend_type
, fn_start
);
3833 register_await_info (final_await
, final_suspend_type
, fin_susp_name
);
3835 /* 4. Now make space for local vars, this is conservative again, and we
3836 would expect to delete unused entries later. */
3837 hash_map
<tree
, local_var_info
> local_var_uses
;
3838 local_vars_frame_data local_vars_data
3839 = {&field_list
, &local_var_uses
, 0, 0, fn_start
, false, false};
3840 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
3842 /* Tie off the struct for now, so that we can build offsets to the
3844 TYPE_FIELDS (coro_frame_type
) = field_list
;
3845 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
3846 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
3847 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
3849 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
3852 /* Now build the ramp function pieces. */
3853 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3854 add_stmt (ramp_bind
);
3855 tree ramp_body
= push_stmt_list ();
3857 tree coro_fp
= build_lang_decl (VAR_DECL
, get_identifier ("coro.frameptr"),
3859 tree varlist
= coro_fp
;
3861 /* Collected the scope vars we need ... only one for now. */
3862 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
3864 /* We're now going to create a new top level scope block for the ramp
3866 tree top_block
= make_node (BLOCK
);
3868 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
3869 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
3870 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
3872 /* The decl_expr for the coro frame pointer, initialize to zero so that we
3873 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
3874 directly apparently). This avoids a "used uninitialized" warning. */
3875 tree zeroinit
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3876 DECL_INITIAL (coro_fp
) = zeroinit
;
3877 add_decl_expr (coro_fp
);
3879 /* The CO_FRAME internal function is a mechanism to allow the middle end
3880 to adjust the allocation in response to optimisations. We provide the
3881 current conservative estimate of the frame size (as per the current)
3883 tree frame_size
= TYPE_SIZE_UNIT (coro_frame_type
);
3885 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
3886 frame_size
, coro_fp
);
3888 /* [dcl.fct.def.coroutine] / 10 (part1)
3889 The unqualified-id get_return_object_on_allocation_failure is looked up
3890 in the scope of the promise type by class member access lookup. */
3893 = lookup_promise_method (orig
, coro_gro_on_allocation_fail_identifier
,
3894 fn_start
, /*musthave=*/false);
3896 tree grooaf
= NULL_TREE
;
3897 tree dummy_promise
= build_dummy_object (get_coroutine_promise_type (orig
));
3899 /* We don't require this, so lookup_promise_method can return NULL... */
3900 if (grooaf_meth
&& BASELINK_P (grooaf_meth
))
3902 /* ... but, if the lookup succeeds, then the function must be
3904 build_new_method_call () wants a valid pointer to (an empty) args
3905 list in this case. */
3906 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3907 grooaf
= build_new_method_call (dummy_promise
, grooaf_meth
, &args
,
3908 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
3909 tf_warning_or_error
);
3910 release_tree_vector (args
);
3913 /* Allocate the frame, this has several possibilities:
3914 [dcl.fct.def.coroutine] / 9 (part 1)
3915 The allocation function’s name is looked up in the scope of the promise
3916 type. It's not a failure for it to be absent see part 4, below. */
3917 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
3918 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
3919 /*musthave=*/false);
3920 tree new_fn
= NULL_TREE
;
3921 if (fns
&& BASELINK_P (fns
))
3923 /* [dcl.fct.def.coroutine] / 9 (part 2)
3924 If the lookup finds an allocation function in the scope of the promise
3925 type, overload resolution is performed on a function call created by
3926 assembling an argument list. The first argument is the amount of space
3927 requested, and has type std::size_t. The succeeding arguments are
3928 those of the original function. */
3929 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3930 vec_safe_push (args
, resizeable
); /* Space needed. */
3932 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3933 arg
= DECL_CHAIN (arg
))
3935 param_info
*parm_i
= param_uses
->get (arg
);
3936 gcc_checking_assert (parm_i
);
3937 if (parm_i
->lambda_cobj
)
3938 vec_safe_push (args
, arg
);
3939 else if (parm_i
->this_ptr
)
3941 /* We pass a reference to *this to the allocator lookup. */
3942 tree tt
= TREE_TYPE (TREE_TYPE (arg
));
3943 tree this_ref
= build1 (INDIRECT_REF
, tt
, arg
);
3944 tt
= cp_build_reference_type (tt
, false);
3945 this_ref
= convert_to_reference (tt
, this_ref
, CONV_STATIC
,
3946 LOOKUP_NORMAL
, NULL_TREE
,
3947 tf_warning_or_error
);
3948 vec_safe_push (args
, this_ref
);
3951 vec_safe_push (args
, arg
);
3954 /* We might need to check that the provided function is nothrow. */
3956 /* Failure is OK for the first attempt. */
3957 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
, NULL
,
3958 LOOKUP_NORMAL
, &func
, tf_none
);
3959 release_tree_vector (args
);
3961 if (!new_fn
|| new_fn
== error_mark_node
)
3963 /* [dcl.fct.def.coroutine] / 9 (part 3)
3964 If no viable function is found, overload resolution is performed
3965 again on a function call created by passing just the amount of
3966 space required as an argument of type std::size_t. */
3967 args
= make_tree_vector ();
3968 vec_safe_push (args
, resizeable
); /* Space needed. */
3969 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
,
3970 NULL_TREE
, LOOKUP_NORMAL
, &func
,
3972 release_tree_vector (args
);
3975 /* However, if the initial lookup succeeded, then one of these two
3976 options must be available. */
3977 if (!new_fn
|| new_fn
== error_mark_node
)
3979 error_at (fn_start
, "%qE is provided by %qT but is not usable with"
3980 " the function signature %qD", nwname
, promise_type
, orig
);
3981 new_fn
= error_mark_node
;
3983 else if (grooaf
&& !TYPE_NOTHROW_P (TREE_TYPE (func
)))
3984 error_at (fn_start
, "%qE is provided by %qT but %qE is not marked"
3985 " %<throw()%> or %<noexcept%>", grooaf
, promise_type
, nwname
);
3989 /* [dcl.fct.def.coroutine] / 9 (part 4)
3990 If this lookup fails, the allocation function’s name is looked up in
3991 the global scope. */
3993 vec
<tree
, va_gc
> *args
;
3994 /* build_operator_new_call () will insert size needed as element 0 of
3995 this, and we might need to append the std::nothrow constant. */
3996 vec_alloc (args
, 2);
4000 /* [dcl.fct.def.coroutine] / 10 (part 2)
4001 If any declarations (of the get return on allocation fail) are
4002 found, then the result of a call to an allocation function used
4003 to obtain storage for the coroutine state is assumed to return
4004 nullptr if it fails to obtain storage and, if a global allocation
4005 function is selected, the ::operator new(size_t, nothrow_t) form
4006 is used. The allocation function used in this case shall have a
4007 non-throwing noexcept-specification. So we need std::nothrow. */
4008 tree std_nt
= lookup_qualified_name (std_node
,
4009 get_identifier ("nothrow"),
4010 0, /*complain=*/true, false);
4011 vec_safe_push (args
, std_nt
);
4014 /* If we get to this point, we must succeed in looking up the global
4015 operator new for the params provided. Extract a simplified version
4016 of the machinery from build_operator_new_call. This can update the
4019 new_fn
= build_operator_new_call (nwname
, &args
, &frame_size
, &cookie
,
4021 /*size_check=*/NULL
, /*fn=*/NULL
,
4022 tf_warning_or_error
);
4023 resizeable
= build_call_expr_internal_loc
4024 (fn_start
, IFN_CO_FRAME
, size_type_node
, 2, frame_size
, coro_fp
);
4025 CALL_EXPR_ARG (new_fn
, 0) = resizeable
;
4027 release_tree_vector (args
);
4030 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
4031 tree r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, allocated
);
4032 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4035 /* If the user provided a method to return an object on alloc fail, then
4036 check the returned pointer and call the func if it's null.
4037 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4041 /* [dcl.fct.def.coroutine] / 10 (part 3)
4042 If the allocation function returns nullptr,the coroutine returns
4043 control to the caller of the coroutine and the return value is
4044 obtained by a call to T::get_return_object_on_allocation_failure(),
4045 where T is the promise type. */
4047 gcc_checking_assert (same_type_p (fn_return_type
, TREE_TYPE (grooaf
)));
4048 tree if_stmt
= begin_if_stmt ();
4049 tree cond
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
4050 cond
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, cond
);
4051 finish_if_stmt_cond (cond
, if_stmt
);
4052 if (VOID_TYPE_P (fn_return_type
))
4054 /* Execute the get-return-object-on-alloc-fail call... */
4055 finish_expr_stmt (grooaf
);
4056 /* ... but discard the result, since we return void. */
4057 finish_return_stmt (NULL_TREE
);
4061 /* Get the fallback return object. */
4062 r
= build_cplus_new (fn_return_type
, grooaf
, tf_warning_or_error
);
4063 finish_return_stmt (r
);
4065 finish_then_clause (if_stmt
);
4066 finish_if_stmt (if_stmt
);
4069 /* deref the frame pointer, to use in member access code. */
4070 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
4072 /* For now, once allocation has succeeded we always assume that this needs
4073 destruction, there's no impl. for frame allocation elision. */
4075 = lookup_member (coro_frame_type
, fnf_name
, 1, 0, tf_warning_or_error
);
4076 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
4077 false, tf_warning_or_error
);
4078 r
= build2 (INIT_EXPR
, boolean_type_node
, fnf_x
, boolean_true_node
);
4079 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4082 /* Put the resumer and destroyer functions in. */
4084 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
4086 = lookup_member (coro_frame_type
, resume_name
,
4087 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4088 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
4089 false, tf_warning_or_error
);
4090 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, resume_x
, actor_addr
);
4091 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4094 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
4096 = lookup_member (coro_frame_type
, destroy_name
,
4097 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4099 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
4100 tf_warning_or_error
);
4101 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, destroy_x
, destroy_addr
);
4102 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4105 /* [dcl.fct.def.coroutine] /13
4106 When a coroutine is invoked, a copy is created for each coroutine
4107 parameter. Each such copy is an object with automatic storage duration
4108 that is direct-initialized from an lvalue referring to the corresponding
4109 parameter if the parameter is an lvalue reference, and from an xvalue
4110 referring to it otherwise. A reference to a parameter in the function-
4111 body of the coroutine and in the call to the coroutine promise
4112 constructor is replaced by a reference to its copy. */
4114 vec
<tree
, va_gc
> *promise_args
= NULL
; /* So that we can adjust refs. */
4116 /* The initialization and destruction of each parameter copy occurs in the
4117 context of the called coroutine. Initializations of parameter copies are
4118 sequenced before the call to the coroutine promise constructor and
4119 indeterminately sequenced with respect to each other. The lifetime of
4120 parameter copies ends immediately after the lifetime of the coroutine
4121 promise object ends. */
4123 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
4125 if (DECL_ARGUMENTS (orig
))
4127 promise_args
= make_tree_vector ();
4128 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4129 arg
= DECL_CHAIN (arg
))
4132 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4134 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
4135 /*protect=*/1, /*want_type=*/0,
4136 tf_warning_or_error
);
4138 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
4139 false, tf_warning_or_error
);
4141 /* Add this to the promise CTOR arguments list, accounting for
4142 refs and special handling for method this ptr. */
4143 if (parm
.lambda_cobj
)
4144 vec_safe_push (promise_args
, arg
);
4145 else if (parm
.this_ptr
)
4147 /* We pass a reference to *this to the param preview. */
4148 tree tt
= TREE_TYPE (arg
);
4149 gcc_checking_assert (POINTER_TYPE_P (tt
));
4150 tree ct
= TREE_TYPE (tt
);
4151 tree this_ref
= build1 (INDIRECT_REF
, ct
, arg
);
4152 tree rt
= cp_build_reference_type (ct
, false);
4153 this_ref
= convert_to_reference (rt
, this_ref
, CONV_STATIC
,
4154 LOOKUP_NORMAL
, NULL_TREE
,
4155 tf_warning_or_error
);
4156 vec_safe_push (promise_args
, this_ref
);
4158 else if (parm
.by_ref
)
4159 vec_safe_push (promise_args
, fld_idx
);
4161 vec_safe_push (promise_args
, arg
);
4163 if (TYPE_NEEDS_CONSTRUCTING (parm
.frame_type
))
4165 vec
<tree
, va_gc
> *p_in
;
4166 if (CLASS_TYPE_P (parm
.frame_type
)
4167 && classtype_has_non_deleted_move_ctor (parm
.frame_type
))
4168 p_in
= make_tree_vector_single (move (arg
));
4169 else if (lvalue_p (arg
))
4170 p_in
= make_tree_vector_single (rvalue (arg
));
4172 p_in
= make_tree_vector_single (arg
);
4173 /* Construct in place or move as relevant. */
4174 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
4175 &p_in
, parm
.frame_type
,
4177 tf_warning_or_error
);
4178 release_tree_vector (p_in
);
4182 if (!same_type_p (parm
.frame_type
, DECL_ARG_TYPE (arg
)))
4183 r
= build1_loc (DECL_SOURCE_LOCATION (arg
), CONVERT_EXPR
,
4184 parm
.frame_type
, arg
);
4187 r
= build_modify_expr (fn_start
, fld_idx
, parm
.frame_type
,
4188 INIT_EXPR
, DECL_SOURCE_LOCATION (arg
), r
,
4191 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4193 if (!parm
.trivial_dtor
)
4195 if (param_dtor_list
== NULL
)
4196 param_dtor_list
= make_tree_vector ();
4197 vec_safe_push (param_dtor_list
, parm
.field_id
);
4202 /* Set up the promise. */
4204 = lookup_member (coro_frame_type
, promise_name
,
4205 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4207 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
4208 false, tf_warning_or_error
);
4210 if (TYPE_NEEDS_CONSTRUCTING (promise_type
))
4212 /* Do a placement new constructor for the promise type (we never call
4213 the new operator, just the constructor on the object in place in the
4216 First try to find a constructor with the same parameter list as the
4217 original function (if it has params), failing that find a constructor
4218 with no parameter list. */
4220 if (DECL_ARGUMENTS (orig
))
4222 r
= build_special_member_call (p
, complete_ctor_identifier
,
4223 &promise_args
, promise_type
,
4224 LOOKUP_NORMAL
, tf_none
);
4225 release_tree_vector (promise_args
);
4230 if (r
== NULL_TREE
|| r
== error_mark_node
)
4231 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
4232 promise_type
, LOOKUP_NORMAL
,
4233 tf_warning_or_error
);
4235 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4239 /* Set up a new bind context for the GRO. */
4240 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4241 /* Make and connect the scope blocks. */
4242 tree gro_block
= make_node (BLOCK
);
4243 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
4244 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
4245 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
4246 add_stmt (gro_context_bind
);
4248 tree gro_meth
= lookup_promise_method (orig
,
4249 coro_get_return_object_identifier
,
4250 fn_start
, /*musthave=*/true );
4252 = build_new_method_call (p
, gro_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
4253 tf_warning_or_error
);
4254 /* Without a return object we haven't got much clue what's going on. */
4255 if (get_ro
== error_mark_node
)
4257 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4258 DECL_SAVED_TREE (orig
) = newbody
;
4259 /* Suppress warnings about the missing return value. */
4260 TREE_NO_WARNING (orig
) = true;
4264 tree gro_context_body
= push_stmt_list ();
4265 bool gro_is_void_p
= VOID_TYPE_P (TREE_TYPE (get_ro
));
4267 tree gro
= NULL_TREE
;
4268 tree gro_bind_vars
= NULL_TREE
;
4269 /* We have to sequence the call to get_return_object before initial
4272 finish_expr_stmt (get_ro
);
4275 gro
= build_lang_decl (VAR_DECL
, get_identifier ("coro.gro"),
4276 TREE_TYPE (get_ro
));
4277 DECL_CONTEXT (gro
) = current_scope ();
4278 DECL_ARTIFICIAL (gro
) = true;
4279 DECL_IGNORED_P (gro
) = true;
4280 add_decl_expr (gro
);
4281 gro_bind_vars
= gro
;
4283 r
= build2_loc (fn_start
, INIT_EXPR
, TREE_TYPE (gro
), gro
, get_ro
);
4284 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4288 /* Initialize the resume_idx_name to 0, meaning "not started". */
4290 = lookup_member (coro_frame_type
, resume_idx_name
,
4291 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4293 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
4294 tf_warning_or_error
);
4295 r
= build_int_cst (short_unsigned_type_node
, 0);
4296 r
= build2_loc (fn_start
, INIT_EXPR
, short_unsigned_type_node
, resume_idx
, r
);
4297 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4300 /* Initialize 'initial-await-resume-called' as per
4301 [dcl.fct.def.coroutine] / 5.3 */
4303 = lookup_member (coro_frame_type
, iarc_name
, 1, 0, tf_warning_or_error
);
4304 tree i_a_r_c
= build_class_member_access_expr (deref_fp
, i_a_r_c_m
,
4306 tf_warning_or_error
);
4307 r
= build2 (INIT_EXPR
, boolean_type_node
, i_a_r_c
, boolean_false_node
);
4308 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4311 /* So .. call the actor .. */
4312 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
4313 r
= maybe_cleanup_point_expr_void (r
);
4316 /* Switch to using 'input_location' as the loc, since we're now more
4317 logically doing things related to the end of the function. */
4319 /* The ramp is done, we just need the return value. */
4320 if (!same_type_p (TREE_TYPE (get_ro
), fn_return_type
))
4322 /* construct the return value with a single GRO param, if it's not
4324 vec
<tree
, va_gc
> *args
= NULL
;
4325 vec
<tree
, va_gc
> **arglist
= NULL
;
4328 args
= make_tree_vector_single (gro
);
4331 r
= build_special_member_call (NULL_TREE
,
4332 complete_ctor_identifier
, arglist
,
4333 fn_return_type
, LOOKUP_NORMAL
,
4334 tf_warning_or_error
);
4335 r
= build_cplus_new (fn_return_type
, r
, tf_warning_or_error
);
4337 else if (!gro_is_void_p
)
4338 r
= rvalue (gro
); /* The GRO is the return value. */
4342 finish_return_stmt (r
);
4344 /* Finish up the ramp function. */
4345 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
4346 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
4347 TREE_SIDE_EFFECTS (gro_context_bind
) = true;
4348 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4349 TREE_SIDE_EFFECTS (ramp_bind
) = true;
4351 /* We know the "real" promise and have a frame layout with a slot for each
4352 suspend point, so we can build an actor function (which contains the
4353 functionality for both 'resume' and 'destroy').
4355 wrap the function body in a try {} catch (...) {} block, if exceptions
4358 /* First make a new block for the body - that will be embedded in the
4359 re-written function. */
4360 tree first
= expr_first (fnbody
);
4361 bool orig_fn_has_outer_bind
= false;
4362 tree replace_blk
= NULL_TREE
;
4363 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
4365 orig_fn_has_outer_bind
= true;
4366 tree block
= BIND_EXPR_BLOCK (first
);
4367 replace_blk
= make_node (BLOCK
);
4368 if (block
) /* missing block is probably an error. */
4370 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
4371 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
4372 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
4373 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
4374 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
4375 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
4377 BIND_EXPR_BLOCK (first
) = replace_blk
;
4380 /* actor's version of the promise. */
4381 tree actor_frame
= build1_loc (fn_start
, INDIRECT_REF
, coro_frame_type
,
4382 DECL_ARGUMENTS (actor
));
4383 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
4384 tf_warning_or_error
);
4385 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
,
4386 false, tf_warning_or_error
);
4388 /* Now we've built the promise etc, process fnbody for co_returns.
4389 We want the call to return_void () below and it has no params so
4390 we can create it once here.
4391 Calls to return_value () will have to be checked and created as
4394 tree return_void
= NULL_TREE
;
4396 = lookup_promise_method (orig
, coro_return_void_identifier
, fn_start
,
4397 /*musthave=*/false);
4398 if (rvm
&& rvm
!= error_mark_node
)
4400 = build_new_method_call (ap
, rvm
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
4401 tf_warning_or_error
);
4403 /* [stmt.return.coroutine] (2.2 : 3) if p.return_void() is a valid
4404 expression, flowing off the end of a coroutine is equivalent to
4405 co_return; otherwise UB.
4406 We just inject the call to p.return_void() here, and fall through to
4407 the final_suspend: label (eliding the goto). If the function body has
4408 a co_return, then this statement will be unreachable and DCEd. */
4409 if (return_void
!= NULL_TREE
)
4411 tree append
= push_stmt_list ();
4413 add_stmt (return_void
);
4414 fnbody
= pop_stmt_list(append
);
4417 if (flag_exceptions
)
4420 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
4421 fn_start
, /*musthave=*/true);
4422 /* Build promise.unhandled_exception(); */
4424 = build_new_method_call (ap
, ueh_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
4425 NULL
, tf_warning_or_error
);
4427 /* The try block is just the original function, there's no real
4428 need to call any function to do this. */
4429 fnbody
= build_stmt (fn_start
, TRY_BLOCK
, fnbody
, NULL_TREE
);
4430 TRY_HANDLERS (fnbody
) = push_stmt_list ();
4431 /* Mimic what the parser does for the catch. */
4432 tree handler
= begin_handler ();
4433 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
4435 /* Get the initial await resume called value. */
4436 tree i_a_r_c
= build_class_member_access_expr (actor_frame
, i_a_r_c_m
,
4438 tf_warning_or_error
);
4439 tree not_iarc_if
= begin_if_stmt ();
4440 tree not_iarc
= build1_loc (fn_start
, TRUTH_NOT_EXPR
,
4441 boolean_type_node
, i_a_r_c
);
4442 finish_if_stmt_cond (not_iarc
, not_iarc_if
);
4443 /* If the initial await resume called value is false, rethrow... */
4444 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
4445 TREE_NO_WARNING (rethrow
) = true;
4446 finish_expr_stmt (rethrow
);
4447 finish_then_clause (not_iarc_if
);
4448 tree iarc_scope
= IF_SCOPE (not_iarc_if
);
4449 IF_SCOPE (not_iarc_if
) = NULL
;
4450 not_iarc_if
= do_poplevel (iarc_scope
);
4451 add_stmt (not_iarc_if
);
4452 /* ... else call the promise unhandled exception method. */
4453 ueh
= maybe_cleanup_point_expr_void (ueh
);
4455 finish_handler (handler
);
4456 TRY_HANDLERS (fnbody
) = pop_stmt_list (TRY_HANDLERS (fnbody
));
4457 /* If the function starts with a BIND_EXPR, then we need to create
4458 one here to contain the try-catch and to link up the scopes. */
4459 if (orig_fn_has_outer_bind
)
4461 fnbody
= build3 (BIND_EXPR
, void_type_node
, NULL
, fnbody
, NULL
);
4462 /* Make and connect the scope blocks. */
4463 tree tcb_block
= make_node (BLOCK
);
4464 /* .. and connect it here. */
4465 BLOCK_SUPERCONTEXT (replace_blk
) = tcb_block
;
4466 BLOCK_SUBBLOCKS (tcb_block
) = replace_blk
;
4467 BIND_EXPR_BLOCK (fnbody
) = tcb_block
;
4468 TREE_SIDE_EFFECTS (fnbody
) = true;
4473 /* We still try to look for the promise method and warn if it's not
4476 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
4477 fn_start
, /*musthave=*/false);
4478 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
4479 warning_at (fn_start
, 0, "no member named %qE in %qT",
4480 coro_unhandled_exception_identifier
,
4481 get_coroutine_promise_type (orig
));
4483 /* Else we don't check and don't care if the method is missing. */
4485 /* Start to build the final functions.
4487 We push_deferring_access_checks to avoid these routines being seen as
4488 nested by the middle end; we are doing the outlining here. */
4490 push_deferring_access_checks (dk_no_check
);
4492 /* Build the actor... */
4493 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
, param_uses
,
4494 &local_var_uses
, param_dtor_list
, initial_await
, final_await
,
4495 body_aw_points
.await_number
, frame_size
);
4498 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
4500 pop_deferring_access_checks ();
4502 DECL_SAVED_TREE (orig
) = newbody
;
4503 /* Link our new functions into the list. */
4504 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
4505 TREE_CHAIN (actor
) = destroy
;
4506 TREE_CHAIN (orig
) = actor
;
4509 *destroyer
= destroy
;
4511 delete suspend_points
;
4512 suspend_points
= NULL
;
4516 #include "gt-cp-coroutines.h"