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 tree
find_promise_type (tree
);
37 static bool coro_promise_type_found_p (tree
, location_t
);
39 /* GCC C++ coroutines implementation.
41 The user authors a function that becomes a coroutine (lazily) by
42 making use of any of the co_await, co_yield or co_return keywords.
44 Unlike a regular function, where the activation record is placed on the
45 stack, and is destroyed on function exit, a coroutine has some state that
46 persists between calls - the coroutine frame (analogous to a stack frame).
48 We transform the user's function into three pieces:
49 1. A so-called ramp function, that establishes the coroutine frame and
50 begins execution of the coroutine.
51 2. An actor function that contains the state machine corresponding to the
52 user's suspend/resume structure.
53 3. A stub function that calls the actor function in 'destroy' mode.
55 The actor function is executed:
56 * from "resume point 0" by the ramp.
57 * from resume point N ( > 0 ) for handle.resume() calls.
58 * from the destroy stub for destroy point N for handle.destroy() calls.
60 The functions in this file carry out the necessary analysis of, and
61 transforms to, the AST to perform this.
63 The C++ coroutine design makes use of some helper functions that are
64 authored in a so-called "promise" class provided by the user.
66 At parse time (or post substitution) the type of the coroutine promise
67 will be determined. At that point, we can look up the required promise
68 class methods and issue diagnostics if they are missing or incorrect. To
69 avoid repeating these actions at code-gen time, we make use of temporary
70 'proxy' variables for the coroutine handle and the promise - which will
71 eventually be instantiated in the coroutine frame.
73 Each of the keywords will expand to a code sequence (although co_yield is
74 just syntactic sugar for a co_await).
76 We defer the analysis and transformation until template expansion is
77 complete so that we have complete types at that time. */
80 /* The state that we collect during parsing (and template expansion) for
83 struct GTY((for_user
)) coroutine_info
85 tree function_decl
; /* The original function decl. */
86 tree promise_type
; /* The cached promise type for this function. */
87 tree handle_type
; /* The cached coroutine handle for this function. */
88 tree self_h_proxy
; /* A handle instance that is used as the proxy for the
89 one that will eventually be allocated in the coroutine
91 tree promise_proxy
; /* Likewise, a proxy promise instance. */
92 location_t first_coro_keyword
; /* The location of the keyword that made this
93 function into a coroutine. */
96 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
98 typedef tree compare_type
; /* We only compare the function decl. */
99 static inline hashval_t
hash (coroutine_info
*);
100 static inline hashval_t
hash (const compare_type
&);
101 static inline bool equal (coroutine_info
*, coroutine_info
*);
102 static inline bool equal (coroutine_info
*, const compare_type
&);
105 /* This table holds all the collected coroutine state for coroutines in
106 the current translation unit. */
108 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
110 /* We will initialise state lazily. */
111 static bool coro_initialized
= false;
113 /* Return a hash value for the entry pointed to by INFO.
114 The compare type is a tree, but the only trees we are going use are
115 function decls. We use the DECL_UID as the hash value since that is
116 stable across PCH. */
119 coroutine_info_hasher::hash (coroutine_info
*info
)
121 return DECL_UID (info
->function_decl
);
124 /* Return a hash value for the compare value COMP. */
127 coroutine_info_hasher::hash (const compare_type
& comp
)
129 return DECL_UID (comp
);
132 /* Return true if the entries pointed to by LHS and RHS are for the
136 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
138 return lhs
->function_decl
== rhs
->function_decl
;
142 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
144 return lhs
->function_decl
== rhs
;
147 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
148 entry does not yet exist. */
151 get_or_insert_coroutine_info (tree fn_decl
)
153 gcc_checking_assert (coroutine_info_table
!= NULL
);
155 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
156 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
160 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
161 (*slot
)->function_decl
= fn_decl
;
167 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
170 get_coroutine_info (tree fn_decl
)
172 gcc_checking_assert (coroutine_info_table
!= NULL
);
174 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
175 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
181 /* We will lazily create all the identifiers that are used by coroutines
182 on the first attempt to lookup the traits. */
184 /* Identifiers that are used by all coroutines. */
186 static GTY(()) tree coro_traits_identifier
;
187 static GTY(()) tree coro_handle_identifier
;
188 static GTY(()) tree coro_promise_type_identifier
;
190 /* Required promise method name identifiers. */
192 static GTY(()) tree coro_await_transform_identifier
;
193 static GTY(()) tree coro_initial_suspend_identifier
;
194 static GTY(()) tree coro_final_suspend_identifier
;
195 static GTY(()) tree coro_return_void_identifier
;
196 static GTY(()) tree coro_return_value_identifier
;
197 static GTY(()) tree coro_yield_value_identifier
;
198 static GTY(()) tree coro_resume_identifier
;
199 static GTY(()) tree coro_from_address_identifier
;
200 static GTY(()) tree coro_get_return_object_identifier
;
201 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
202 static GTY(()) tree coro_unhandled_exception_identifier
;
204 /* Awaitable methods. */
206 static GTY(()) tree coro_await_ready_identifier
;
207 static GTY(()) tree coro_await_suspend_identifier
;
208 static GTY(()) tree coro_await_resume_identifier
;
210 /* Create the identifiers used by the coroutines library interfaces. */
213 coro_init_identifiers ()
215 coro_traits_identifier
= get_identifier ("coroutine_traits");
216 coro_handle_identifier
= get_identifier ("coroutine_handle");
217 coro_promise_type_identifier
= get_identifier ("promise_type");
219 coro_await_transform_identifier
= get_identifier ("await_transform");
220 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
221 coro_final_suspend_identifier
= get_identifier ("final_suspend");
222 coro_return_void_identifier
= get_identifier ("return_void");
223 coro_return_value_identifier
= get_identifier ("return_value");
224 coro_yield_value_identifier
= get_identifier ("yield_value");
225 coro_resume_identifier
= get_identifier ("resume");
226 coro_from_address_identifier
= get_identifier ("from_address");
227 coro_get_return_object_identifier
= get_identifier ("get_return_object");
228 coro_gro_on_allocation_fail_identifier
=
229 get_identifier ("get_return_object_on_allocation_failure");
230 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
232 coro_await_ready_identifier
= get_identifier ("await_ready");
233 coro_await_suspend_identifier
= get_identifier ("await_suspend");
234 coro_await_resume_identifier
= get_identifier ("await_resume");
237 /* Trees we only need to set up once. */
239 static GTY(()) tree coro_traits_templ
;
240 static GTY(()) tree coro_handle_templ
;
241 static GTY(()) tree void_coro_handle_type
;
243 /* ================= Parse, Semantics and Type checking ================= */
245 /* This initial set of routines are helper for the parsing and template
248 At the completion of this, we will have completed trees for each of the
249 keywords, but making use of proxy variables for the self-handle and the
250 promise class instance. */
252 /* [coroutine.traits]
253 Lookup the coroutine_traits template decl. */
256 find_coro_traits_template_decl (location_t kw
)
258 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
260 if (traits_decl
== NULL_TREE
|| traits_decl
== error_mark_node
)
262 error_at (kw
, "cannot find %<coroutine traits%> template");
269 /* Instantiate Coroutine traits for the function signature. */
272 instantiate_coro_traits (tree fndecl
, location_t kw
)
274 /* [coroutine.traits.primary]
275 So now build up a type list for the template <typename _R, typename...>.
276 The types are the function's arg types and _R is the function return
279 tree functyp
= TREE_TYPE (fndecl
);
280 tree arg_node
= TYPE_ARG_TYPES (functyp
);
281 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
284 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
286 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
287 arg_node
= TREE_CHAIN (arg_node
);
290 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
291 SET_ARGUMENT_PACK_ARGS (argtypepack
, argtypes
);
293 tree targ
= make_tree_vec (2);
294 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
295 TREE_VEC_ELT (targ
, 1) = argtypepack
;
298 = lookup_template_class (coro_traits_templ
, targ
,
299 /*in_decl=*/ NULL_TREE
,
300 /*context=*/ NULL_TREE
/*std_node*/,
301 /*entering scope=*/ false, tf_warning_or_error
);
303 if (traits_class
== error_mark_node
|| traits_class
== NULL_TREE
)
305 error_at (kw
, "cannot instantiate %<coroutine traits%>");
312 /* [coroutine.handle] */
315 find_coro_handle_template_decl (location_t kw
)
317 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
319 if (handle_decl
== NULL_TREE
|| handle_decl
== error_mark_node
)
321 error_at (kw
, "cannot find %<coroutine handle%> template");
328 /* Instantiate the handle template for a given promise type. */
331 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
333 /* So now build up a type list for the template, one entry, the promise. */
334 tree targ
= make_tree_vec (1);
335 TREE_VEC_ELT (targ
, 0) = promise_type
;
337 = lookup_template_class (coro_handle_identifier
, targ
,
338 /* in_decl */ NULL_TREE
,
339 /* context */ std_node
,
340 /* entering scope */ false, tf_warning_or_error
);
342 if (handle_type
== error_mark_node
)
344 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
345 " promise type %qT", promise_type
);
352 /* Look for the promise_type in the instantiated traits. */
355 find_promise_type (tree traits_class
)
358 = lookup_member (traits_class
, coro_promise_type_identifier
,
359 /* protect */ 1, /*want_type=*/true, tf_warning_or_error
);
363 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
365 /* NULL_TREE on fail. */
370 coro_promise_type_found_p (tree fndecl
, location_t loc
)
372 gcc_assert (fndecl
!= NULL_TREE
);
374 /* Save the coroutine data on the side to avoid the overhead on every
377 /* We only need one entry per coroutine in a TU, the assumption here is that
378 there are typically not 1000s. */
379 if (!coro_initialized
)
381 gcc_checking_assert (coroutine_info_table
== NULL
);
382 /* A table to hold the state, per coroutine decl. */
383 coroutine_info_table
=
384 hash_table
<coroutine_info_hasher
>::create_ggc (11);
385 /* Set up the identifiers we will use. */
386 gcc_checking_assert (coro_traits_identifier
== NULL
);
387 coro_init_identifiers ();
388 /* Trees we only need to create once. */
389 /* Coroutine traits template. */
390 coro_traits_templ
= find_coro_traits_template_decl (loc
);
391 gcc_checking_assert (coro_traits_templ
!= NULL
);
392 /* coroutine_handle<> template. */
393 coro_handle_templ
= find_coro_handle_template_decl (loc
);
394 gcc_checking_assert (coro_handle_templ
!= NULL
);
395 /* We can also instantiate the void coroutine_handle<> */
396 void_coro_handle_type
=
397 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
398 gcc_checking_assert (void_coro_handle_type
!= NULL
);
399 coro_initialized
= true;
402 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
403 /* Without this, we cannot really proceed. */
404 gcc_checking_assert (coro_info
);
406 /* If we don't already have a current promise type, try to look it up. */
407 if (coro_info
->promise_type
== NULL_TREE
)
409 /* Get the coroutine traits template class instance for the function
410 signature we have - coroutine_traits <R, ...> */
411 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
413 /* Find the promise type for that. */
414 coro_info
->promise_type
= find_promise_type (templ_class
);
416 /* If we don't find it, punt on the rest. */
417 if (coro_info
->promise_type
== NULL_TREE
)
419 error_at (loc
, "unable to find the promise type for this coroutine");
423 /* Try to find the handle type for the promise. */
425 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
426 if (handle_type
== NULL_TREE
)
429 /* Complete this, we're going to use it. */
430 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
432 /* Diagnostic would be emitted by complete_type_or_else. */
433 if (!coro_info
->handle_type
)
436 /* Build a proxy for a handle to "self" as the param to
437 await_suspend() calls. */
438 coro_info
->self_h_proxy
439 = build_lang_decl (VAR_DECL
, get_identifier ("self_h.proxy"),
440 coro_info
->handle_type
);
442 /* Build a proxy for the promise so that we can perform lookups. */
443 coro_info
->promise_proxy
444 = build_lang_decl (VAR_DECL
, get_identifier ("promise.proxy"),
445 coro_info
->promise_type
);
447 /* Note where we first saw a coroutine keyword. */
448 coro_info
->first_coro_keyword
= loc
;
454 /* These functions assumes that the caller has verified that the state for
455 the decl has been initialized, we try to minimize work here. */
458 get_coroutine_promise_type (tree decl
)
460 if (coroutine_info
*info
= get_coroutine_info (decl
))
461 return info
->promise_type
;
467 get_coroutine_handle_type (tree decl
)
469 if (coroutine_info
*info
= get_coroutine_info (decl
))
470 return info
->handle_type
;
476 get_coroutine_self_handle_proxy (tree decl
)
478 if (coroutine_info
*info
= get_coroutine_info (decl
))
479 return info
->self_h_proxy
;
485 get_coroutine_promise_proxy (tree decl
)
487 if (coroutine_info
*info
= get_coroutine_info (decl
))
488 return info
->promise_proxy
;
494 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
497 tree promise
= get_coroutine_promise_type (fndecl
);
499 = lookup_member (promise
, member_id
,
500 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
501 if (musthave
&& pm_memb
== NULL_TREE
)
503 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
504 return error_mark_node
;
509 /* Lookup an Awaitable member, which should be await_ready, await_suspend
513 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
516 = lookup_member (await_type
, member_id
,
517 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
518 if (aw_memb
== NULL_TREE
)
520 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
521 return error_mark_node
;
526 /* Here we check the constraints that are common to all keywords (since the
527 presence of a coroutine keyword makes the function into a coroutine). */
530 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
533 if (fndecl
== NULL_TREE
)
535 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
539 /* This is arranged in order of prohibitions in the std. */
540 if (DECL_MAIN_P (fndecl
))
542 // [basic.start.main] 3. The function main shall not be a coroutine.
543 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
548 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
550 // [dcl.constexpr] 3.3 it shall not be a coroutine.
551 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
553 cp_function_chain
->invalid_constexpr
= true;
557 if (FNDECL_USED_AUTO (fndecl
))
559 // [dcl.spec.auto] 15. A function declared with a return type that uses
560 // a placeholder type shall not be a coroutine .
562 "%qs cannot be used in a function with a deduced return type",
567 if (varargs_function_p (fndecl
))
569 // [dcl.fct.def.coroutine] The parameter-declaration-clause of the
570 // coroutine shall not terminate with an ellipsis that is not part
571 // of a parameter-declaration.
573 "%qs cannot be used in a varargs function", kw_name
);
577 if (DECL_CONSTRUCTOR_P (fndecl
))
579 // [class.ctor] 7. a constructor shall not be a coroutine.
580 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
584 if (DECL_DESTRUCTOR_P (fndecl
))
586 // [class.dtor] 21. a destructor shall not be a coroutine.
587 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
594 /* Here we check the constraints that are not per keyword. */
597 coro_function_valid_p (tree fndecl
)
599 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
601 /* Since we think the function is a coroutine, that implies we parsed
602 a keyword that triggered this. Keywords check promise validity for
603 their context and thus the promise type should be known at this point. */
604 gcc_checking_assert (get_coroutine_handle_type (fndecl
) != NULL_TREE
605 && get_coroutine_promise_type (fndecl
) != NULL_TREE
);
607 if (current_function_returns_value
|| current_function_returns_null
)
609 /* TODO: record or extract positions of returns (and the first coro
610 keyword) so that we can add notes to the diagnostic about where
611 the bad keyword is and what made the function into a coro. */
612 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
613 " did you mean %<co_return%>?");
620 enum suspend_point_kind
{
621 CO_AWAIT_SUSPEND_POINT
= 0,
622 CO_YIELD_SUSPEND_POINT
,
623 INITIAL_SUSPEND_POINT
,
627 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
628 It is also used to build the initial and final suspend points.
630 'a', 'o' and 'e' are used as per the description in the section noted.
632 A, the original yield/await expr, is found at source location LOC.
634 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
635 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
638 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
640 /* Try and overload of operator co_await, .... */
642 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
644 tree overload
= NULL_TREE
;
645 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
646 NULL_TREE
, &overload
, tf_warning_or_error
);
647 /* If no viable functions are found, o is a. */
648 if (!o
|| o
== error_mark_node
)
652 o
= a
; /* This is most likely about to fail anyway. */
654 tree o_type
= TREE_TYPE (o
);
655 if (o_type
&& !VOID_TYPE_P (o_type
))
656 o_type
= complete_type_or_else (o_type
, o
);
659 return error_mark_node
;
661 if (TREE_CODE (o_type
) != RECORD_TYPE
)
663 error_at (loc
, "awaitable type %qT is not a structure",
665 return error_mark_node
;
668 /* Check for required awaitable members and their types. */
670 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
671 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
672 return error_mark_node
;
674 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
675 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
676 return error_mark_node
;
678 /* The type of the co_await is the return type of the awaitable's
679 await_resume, so we need to look that up. */
681 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
682 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
683 return error_mark_node
;
685 /* To complete the lookups, we need an instance of 'e' which is built from
686 'o' according to [expr.await] 3.4. However, we don't want to materialize
687 'e' here (it might need to be placed in the coroutine frame) so we will
688 make a temp placeholder instead. */
689 tree e_proxy
= build_lang_decl (VAR_DECL
, NULL_TREE
, o_type
);
691 /* I suppose we could check that this is contextually convertible to bool. */
692 tree awrd_func
= NULL_TREE
;
694 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
695 &awrd_func
, tf_warning_or_error
);
697 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
698 return error_mark_node
;
700 /* The suspend method may return one of three types:
701 1. void (no special action needed).
702 2. bool (if true, we don't need to suspend).
703 3. a coroutine handle, we execute the handle.resume() call. */
704 tree awsp_func
= NULL_TREE
;
705 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
706 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
708 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
709 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
711 release_tree_vector (args
);
712 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
713 return error_mark_node
;
716 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
717 if (same_type_p (susp_return_type
, void_type_node
))
719 else if (same_type_p (susp_return_type
, boolean_type_node
))
721 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
722 && CLASS_TYPE_P (susp_return_type
))
724 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
725 if (tt
== coro_handle_templ
)
731 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
732 " a coroutine handle");
733 return error_mark_node
;
736 /* Finally, the type of e.await_resume() is the co_await's type. */
737 tree awrs_func
= NULL_TREE
;
739 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
740 &awrs_func
, tf_warning_or_error
);
742 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
743 return error_mark_node
;
745 /* We now have three call expressions, in terms of the promise, handle and
746 'e' proxies. Save them in the await expression for later expansion. */
748 tree awaiter_calls
= make_tree_vec (3);
749 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
750 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
751 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
753 return build5_loc (loc
, CO_AWAIT_EXPR
, TREE_TYPE (awrs_call
), a
,
754 e_proxy
, o
, awaiter_calls
,
755 build_int_cst (integer_type_node
, (int) suspend_kind
));
759 finish_co_await_expr (location_t kw
, tree expr
)
761 if (!expr
|| error_operand_p (expr
))
762 return error_mark_node
;
764 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
766 return error_mark_node
;
768 /* The current function has now become a coroutine, if it wasn't already. */
769 DECL_COROUTINE_P (current_function_decl
) = 1;
771 if (processing_template_decl
)
773 current_function_returns_value
= 1;
775 if (check_for_bare_parameter_packs (expr
))
776 return error_mark_node
;
778 /* If we don't know the promise type, we can't proceed. */
779 tree functype
= TREE_TYPE (current_function_decl
);
780 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
781 return build5_loc (kw
, CO_AWAIT_EXPR
, TREE_TYPE (expr
), expr
, NULL_TREE
,
782 NULL_TREE
, NULL_TREE
, integer_zero_node
);
785 /* We must be able to look up the "await_transform" method in the scope of
786 the promise type, and obtain its return type. */
787 if (!coro_promise_type_found_p (current_function_decl
, kw
))
788 return error_mark_node
;
791 The incoming cast expression might be transformed by a promise
792 'await_transform()'. */
794 = lookup_promise_method (current_function_decl
,
795 coro_await_transform_identifier
, kw
,
796 /*musthave=*/ false);
797 if (at_meth
== error_mark_node
)
798 return error_mark_node
;
803 /* try to build a = p.await_transform (e). */
804 tree at_fn
= NULL_TREE
;
805 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
806 a
= build_new_method_call (get_coroutine_promise_proxy (
807 current_function_decl
),
808 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
809 &at_fn
, tf_warning_or_error
);
811 /* As I read the section.
812 We saw an await_transform method, so it's mandatory that we replace
813 expr with p.await_transform (expr), therefore if the method call fails
814 (presumably, we don't have suitable arguments) then this part of the
816 if (!at_fn
|| a
== error_mark_node
)
817 return error_mark_node
;
820 /* Now we want to build co_await a. */
821 tree op
= build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
822 TREE_SIDE_EFFECTS (op
) = 1;
823 SET_EXPR_LOCATION (op
, kw
);
828 /* Take the EXPR given and attempt to build:
829 co_await p.yield_value (expr);
830 per [expr.yield] para 1. */
833 finish_co_yield_expr (location_t kw
, tree expr
)
835 if (!expr
|| error_operand_p (expr
))
836 return error_mark_node
;
838 /* Check the general requirements and simple syntax errors. */
839 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
841 return error_mark_node
;
843 /* The current function has now become a coroutine, if it wasn't already. */
844 DECL_COROUTINE_P (current_function_decl
) = 1;
846 if (processing_template_decl
)
848 current_function_returns_value
= 1;
850 if (check_for_bare_parameter_packs (expr
))
851 return error_mark_node
;
853 tree functype
= TREE_TYPE (current_function_decl
);
854 /* If we don't know the promise type, we can't proceed. */
855 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
856 return build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (expr
), expr
,
860 if (!coro_promise_type_found_p (current_function_decl
, kw
))
861 /* We must be able to look up the "yield_value" method in the scope of
862 the promise type, and obtain its return type. */
863 return error_mark_node
;
865 /* The incoming expr is "e" per [expr.yield] para 1, lookup and build a
866 call for p.yield_value(e). */
867 tree y_meth
= lookup_promise_method (current_function_decl
,
868 coro_yield_value_identifier
, kw
,
870 if (!y_meth
|| y_meth
== error_mark_node
)
871 return error_mark_node
;
873 tree yield_fn
= NULL_TREE
;
874 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
875 tree yield_call
= build_new_method_call (
876 get_coroutine_promise_proxy (current_function_decl
), y_meth
, &args
,
877 NULL_TREE
, LOOKUP_NORMAL
, &yield_fn
, tf_warning_or_error
);
879 if (!yield_fn
|| yield_call
== error_mark_node
)
880 return error_mark_node
;
882 /* So now we have the type of p.yield_value (e).
883 Now we want to build co_await p.yield_value (e).
884 Noting that for co_yield, there is no evaluation of any potential
885 promise transform_await(). */
887 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
889 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
890 TREE_SIDE_EFFECTS (op
) = 1;
895 /* Check that it's valid to have a co_return keyword here.
896 If it is, then check and build the p.return_{void(),value(expr)}.
897 These are built against the promise proxy, but saved for expand time. */
900 finish_co_return_stmt (location_t kw
, tree expr
)
902 if (expr
== error_mark_node
)
903 return error_mark_node
;
905 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
907 return error_mark_node
;
909 /* The current function has now become a coroutine, if it wasn't
911 DECL_COROUTINE_P (current_function_decl
) = 1;
913 if (processing_template_decl
)
915 current_function_returns_value
= 1;
917 if (check_for_bare_parameter_packs (expr
))
918 return error_mark_node
;
920 tree functype
= TREE_TYPE (current_function_decl
);
921 /* If we don't know the promise type, we can't proceed, return the
922 expression as it is. */
923 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
926 = build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, NULL_TREE
);
927 expr
= maybe_cleanup_point_expr_void (expr
);
928 expr
= add_stmt (expr
);
933 if (!coro_promise_type_found_p (current_function_decl
, kw
))
934 return error_mark_node
;
936 if (error_operand_p (expr
))
937 return error_mark_node
;
939 /* Suppress -Wreturn-type for co_return, we need to check indirectly
940 whether the promise type has a suitable return_void/return_value. */
941 TREE_NO_WARNING (current_function_decl
) = true;
943 if (!processing_template_decl
&& warn_sequence_point
)
944 verify_sequence_points (expr
);
946 /* If the promise object doesn't have the correct return call then
947 there's a mis-match between the co_return <expr> and this. */
948 tree co_ret_call
= NULL_TREE
;
949 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
952 = lookup_promise_method (current_function_decl
,
953 coro_return_void_identifier
, kw
,
955 if (!crv_meth
|| crv_meth
== error_mark_node
)
956 return error_mark_node
;
958 co_ret_call
= build_new_method_call (
959 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, NULL
,
960 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
965 = lookup_promise_method (current_function_decl
,
966 coro_return_value_identifier
, kw
,
968 if (!crv_meth
|| crv_meth
== error_mark_node
)
969 return error_mark_node
;
971 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
972 co_ret_call
= build_new_method_call (
973 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, &args
,
974 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
977 /* Makes no sense for a co-routine really. */
978 if (TREE_THIS_VOLATILE (current_function_decl
))
980 "function declared %<noreturn%> has a"
981 " %<co_return%> statement");
983 if (!co_ret_call
|| co_ret_call
== error_mark_node
)
984 return error_mark_node
;
986 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
987 expr
= maybe_cleanup_point_expr_void (expr
);
988 expr
= add_stmt (expr
);
992 /* We need to validate the arguments to __builtin_coro_promise, since the
993 second two must be constant, and the builtins machinery doesn't seem to
994 deal with that properly. */
997 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
999 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1001 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1002 switch (DECL_FUNCTION_CODE (fn
))
1007 case BUILT_IN_CORO_PROMISE
:
1009 /* Argument 0 is already checked by the normal built-in machinery
1010 Argument 1 must be a constant of size type. It probably makes
1011 little sense if it's not a power of 2, but that isn't specified
1013 tree arg
= CALL_EXPR_ARG (call
, 1);
1014 location_t loc
= EXPR_LOCATION (arg
);
1016 /* We expect alignof expressions in templates. */
1017 if (TREE_CODE (arg
) == NON_DEPENDENT_EXPR
1018 && TREE_CODE (TREE_OPERAND (arg
, 0)) == ALIGNOF_EXPR
)
1020 else if (!TREE_CONSTANT (arg
))
1022 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1023 " must be a constant");
1024 return error_mark_node
;
1026 /* Argument 2 is the direction - to / from handle address to promise
1028 arg
= CALL_EXPR_ARG (call
, 2);
1029 loc
= EXPR_LOCATION (arg
);
1030 if (!TREE_CONSTANT (arg
))
1032 error_at (loc
, "the direction argument to"
1033 " %<__builtin_coro_promise%> must be a constant");
1034 return error_mark_node
;
1042 /* ================= Morph and Expand. =================
1044 The entry point here is morph_fn_to_coro () which is called from
1045 finish_function () when we have completed any template expansion.
1047 This is preceded by helper functions that implement the phases below.
1049 The process proceeds in four phases.
1052 The user's function body is wrapped in the initial and final suspend
1053 points and we begin building the coroutine frame.
1054 We build empty decls for the actor and destroyer functions at this
1056 When exceptions are enabled, the user's function body will also be
1057 wrapped in a try-catch block with the catch invoking the promise
1058 class 'unhandled_exception' method.
1061 The user's function body is analyzed to determine the suspend points,
1062 if any, and to capture local variables that might persist across such
1063 suspensions. In most cases, it is not necessary to capture compiler
1064 temporaries, since the tree-lowering nests the suspensions correctly.
1065 However, in the case of a captured reference, there is a lifetime
1066 extension to the end of the full expression - which can mean across a
1067 suspend point in which case it must be promoted to a frame variable.
1069 At the conclusion of analysis, we have a conservative frame layout and
1070 maps of the local variables to their frame entry points.
1072 C Build the ramp function.
1073 Carry out the allocation for the coroutine frame (NOTE; the actual size
1074 computation is deferred until late in the middle end to allow for future
1075 optimizations that will be allowed to elide unused frame entries).
1076 We build the return object.
1078 D Build and expand the actor and destroyer function bodies.
1079 The destroyer is a trivial shim that sets a bit to indicate that the
1080 destroy dispatcher should be used and then calls into the actor.
1082 The actor function is the implementation of the user's state machine.
1083 The current suspend point is noted in an index.
1084 Each suspend point is encoded as a pair of internal functions, one in
1085 the relevant dispatcher, and one representing the suspend point.
1087 During this process, the user's local variables and the proxies for the
1088 self-handle and the promise class instance are re-written to their
1089 coroutine frame equivalents.
1091 The complete bodies for the ramp, actor and destroy function are passed
1092 back to finish_function for folding and gimplification. */
1094 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1097 coro_build_expr_stmt (tree expr
, location_t loc
)
1099 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1103 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1105 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1106 return coro_build_expr_stmt (t
, loc
);
1109 /* Helpers for label creation:
1110 1. Create a named label in the specified context. */
1113 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1115 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1117 DECL_CONTEXT (lab
) = ctx
;
1118 DECL_ARTIFICIAL (lab
) = true;
1119 DECL_IGNORED_P (lab
) = true;
1120 TREE_USED (lab
) = true;
1124 /* 2. Create a named label in the specified context. */
1127 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1129 tree lab_id
= get_identifier (name
);
1130 tree lab
= define_label (loc
, lab_id
);
1131 DECL_CONTEXT (lab
) = ctx
;
1132 DECL_ARTIFICIAL (lab
) = true;
1133 TREE_USED (lab
) = true;
1137 struct proxy_replace
1143 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1145 proxy_replace
*data
= (proxy_replace
*) d
;
1147 if (*here
== data
->from
)
1157 /* Support for expansion of co_return statements. */
1159 struct coro_ret_data
1166 /* If this is a coreturn statement (or one wrapped in a cleanup) then
1167 return the list of statements to replace it. */
1170 coro_maybe_expand_co_return (tree co_ret_expr
, coro_ret_data
*data
)
1172 /* Look inside <(void) (expr)> cleanup */
1173 if (TREE_CODE (co_ret_expr
) == CLEANUP_POINT_EXPR
)
1174 co_ret_expr
= TREE_OPERAND (co_ret_expr
, 0);
1176 if (TREE_CODE (co_ret_expr
) != CO_RETURN_EXPR
)
1179 location_t loc
= EXPR_LOCATION (co_ret_expr
);
1180 tree expr
= TREE_OPERAND (co_ret_expr
, 0);
1181 tree call
= TREE_OPERAND (co_ret_expr
, 1);
1182 tree stmt_list
= NULL
;
1183 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
1185 /* [stmt.return.coroutine], 2.2
1186 If expr is present and void, it is placed immediately before
1187 the call for return_void; */
1188 expr
= maybe_cleanup_point_expr_void (expr
);
1189 append_to_statement_list (expr
, &stmt_list
);
1192 /* Now replace the promise proxy with its real value. */
1193 proxy_replace p_data
;
1194 p_data
.from
= data
->promise_proxy
;
1195 p_data
.to
= data
->real_promise
;
1196 cp_walk_tree (&call
, replace_proxy
, &p_data
, NULL
);
1198 /* The types of p.return_void and p.return_value are not explicitly stated
1199 at least in n4835, it is expected that they will return void. */
1200 call
= maybe_cleanup_point_expr_void (call
);
1201 append_to_statement_list (call
, &stmt_list
);
1202 tree r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->fs_label
);
1203 append_to_statement_list (r
, &stmt_list
);
1207 /* Callback that rewrites co_return as per [stmt.return.coroutine]
1209 { p.return_void (); goto final_suspend; }
1210 - for co_return [void expr];
1211 { expr; p.return_void(); goto final_suspend;}
1212 - for co_return [non void expr];
1213 { p.return_value(expr); goto final_suspend; } */
1216 co_return_expander (tree
*stmt
, int *do_subtree
, void *d
)
1218 coro_ret_data
*data
= (coro_ret_data
*) d
;
1220 /* To avoid nesting statement lists, walk them and insert as needed. */
1221 if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1223 tree_stmt_iterator i
;
1224 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1226 tree
*new_stmt
= tsi_stmt_ptr (i
);
1227 tree replace
= coro_maybe_expand_co_return (*new_stmt
, data
);
1228 /* If we got something, it will be list and we want to splice
1230 if (replace
!= NULL_TREE
)
1232 /* Splice it in ... */
1233 tsi_link_before (&i
, replace
, TSI_SAME_STMT
);
1234 /* ... and delete what we expanded. */
1236 /* Maybe, even likely, we replaced the last in the list. */
1240 else /* Continue the walk. */
1241 cp_walk_tree (new_stmt
, co_return_expander
, d
, NULL
);
1243 *do_subtree
= 0; /* Done subtrees. */
1247 /* We might have a single co_return statement, in which case, we do
1248 have to replace it with a list. */
1249 tree replace
= coro_maybe_expand_co_return (*stmt
, data
);
1250 if (replace
!= NULL_TREE
)
1253 *do_subtree
= 0; /* Done here. */
1259 /* Walk the original function body, rewriting co_returns. */
1262 expand_co_returns (tree
*fnbody
, tree promise_proxy
, tree promise
,
1265 coro_ret_data data
= {promise_proxy
, promise
, fs_label
};
1266 cp_walk_tree (fnbody
, co_return_expander
, &data
, NULL
);
1270 /* Support for expansion of co_await statements. */
1274 tree actor_fn
; /* Decl for context. */
1275 tree coro_fp
; /* Frame pointer var. */
1276 tree resume_idx
; /* This is the index var in the frame. */
1277 tree self_h
; /* This is a handle to the current coro (frame var). */
1278 tree cleanup
; /* This is where to go once we complete local destroy. */
1279 tree cororet
; /* This is where to go if we suspend. */
1280 unsigned index
; /* This is our current resume index. */
1284 co_await_find_in_subtree (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
1286 tree
**p
= (tree
**) d
;
1287 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1295 /* When we come here:
1296 the first operand is the [currently unused] handle for suspend.
1297 the second operand is the var to be copy-initialized
1298 the third operand is 'o' (the initializer for the second)
1299 as defined in [await.expr] (3.3)
1300 the fourth operand is the mode as per the comment on build_co_await ().
1303 the IFN_CO_YIELD carries the labels of the resume and destroy
1304 branch targets for this await. */
1307 co_await_expander (tree
*stmt
, int * /*do_subtree*/, void *d
)
1309 if (STATEMENT_CLASS_P (*stmt
) || !EXPR_P (*stmt
))
1312 coro_aw_data
*data
= (coro_aw_data
*) d
;
1314 enum tree_code stmt_code
= TREE_CODE (*stmt
);
1315 tree stripped_stmt
= *stmt
;
1317 /* Look inside <(void) (expr)> cleanup */
1318 if (stmt_code
== CLEANUP_POINT_EXPR
)
1320 stripped_stmt
= TREE_OPERAND (*stmt
, 0);
1321 stmt_code
= TREE_CODE (stripped_stmt
);
1322 if (stmt_code
== EXPR_STMT
1323 && (TREE_CODE (EXPR_STMT_EXPR (stripped_stmt
)) == CONVERT_EXPR
1324 || TREE_CODE (EXPR_STMT_EXPR (stripped_stmt
)) == CAST_EXPR
)
1325 && VOID_TYPE_P (TREE_TYPE (EXPR_STMT_EXPR (stripped_stmt
))))
1327 stripped_stmt
= TREE_OPERAND (EXPR_STMT_EXPR (stripped_stmt
), 0);
1328 stmt_code
= TREE_CODE (stripped_stmt
);
1332 tree
*buried_stmt
= NULL
;
1333 tree saved_co_await
= NULL_TREE
;
1334 enum tree_code sub_code
= NOP_EXPR
;
1336 if (stmt_code
== EXPR_STMT
1337 && TREE_CODE (EXPR_STMT_EXPR (stripped_stmt
)) == CO_AWAIT_EXPR
)
1339 = EXPR_STMT_EXPR (stripped_stmt
); /* hopefully, a void exp. */
1340 else if (stmt_code
== MODIFY_EXPR
|| stmt_code
== INIT_EXPR
)
1342 sub_code
= TREE_CODE (TREE_OPERAND (stripped_stmt
, 1));
1343 if (sub_code
== CO_AWAIT_EXPR
)
1344 saved_co_await
= TREE_OPERAND (stripped_stmt
, 1); /* Get the RHS. */
1346 = cp_walk_tree (&TREE_OPERAND (stripped_stmt
, 1),
1347 co_await_find_in_subtree
, &buried_stmt
, NULL
))
1350 else if (stmt_code
== CALL_EXPR
)
1352 if (tree r
= cp_walk_tree (&stripped_stmt
, co_await_find_in_subtree
,
1353 &buried_stmt
, NULL
))
1357 if (!saved_co_await
)
1360 /* We want to splice in the await_resume() value in some cases. */
1361 tree saved_statement
= *stmt
;
1363 tree actor
= data
->actor_fn
;
1364 location_t loc
= EXPR_LOCATION (*stmt
);
1365 tree sv_handle
= TREE_OPERAND (saved_co_await
, 0);
1366 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1367 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1368 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1370 tree source
= TREE_OPERAND (saved_co_await
, 4);
1371 bool is_final
= (source
1372 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1373 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1374 int resume_point
= data
->index
;
1375 size_t bufsize
= sizeof ("destroy.") + 10;
1376 char *buf
= (char *) alloca (bufsize
);
1377 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1378 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1379 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1380 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1381 tree empty_list
= build_empty_stmt (loc
);
1383 tree dtor
= NULL_TREE
;
1384 tree await_type
= TREE_TYPE (var
);
1386 dtor
= build_special_member_call (var
, complete_dtor_identifier
, NULL
,
1387 await_type
, LOOKUP_NORMAL
,
1388 tf_warning_or_error
);
1390 tree stmt_list
= NULL
;
1391 /* Initialize the var from the provided 'o' expression. */
1392 tree r
= build2 (INIT_EXPR
, await_type
, var
, expr
);
1393 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1394 append_to_statement_list (r
, &stmt_list
);
1396 /* Use the await_ready() call to test if we need to suspend. */
1397 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1398 ready_cond
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, ready_cond
);
1400 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1402 tree body_list
= NULL
;
1403 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1404 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1406 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1407 append_to_statement_list (r
, &body_list
);
1409 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1411 if (sv_handle
== NULL_TREE
)
1413 /* void return, we just call it and hit the yield. */
1414 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1415 append_to_statement_list (suspend
, &body_list
);
1417 else if (sv_handle
== boolean_type_node
)
1419 /* Boolean return, continue if the call returns false. */
1420 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1422 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1423 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1424 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1426 append_to_statement_list (r
, &body_list
);
1430 r
= build2_loc (loc
, INIT_EXPR
, TREE_TYPE (sv_handle
), sv_handle
,
1432 append_to_statement_list (r
, &body_list
);
1434 = lookup_member (TREE_TYPE (sv_handle
), coro_resume_identifier
, 1, 0,
1435 tf_warning_or_error
);
1436 resume
= build_new_method_call (sv_handle
, resume
, NULL
, NULL_TREE
,
1437 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1438 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
1439 append_to_statement_list (resume
, &body_list
);
1443 = build1 (ADDR_EXPR
, build_reference_type (void_type_node
), destroy_label
);
1445 = build1 (ADDR_EXPR
, build_reference_type (void_type_node
), resume_label
);
1447 = build1 (ADDR_EXPR
, build_reference_type (void_type_node
), data
->cororet
);
1448 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1450 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1452 tree sw
= begin_switch_stmt ();
1453 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1454 DECL_ARTIFICIAL (cond
) = 1;
1455 DECL_IGNORED_P (cond
) = 1;
1456 layout_decl (cond
, 0);
1458 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1459 susp_idx
, final_susp
, r_l
, d_l
,
1461 r
= build2 (INIT_EXPR
, integer_type_node
, cond
, r
);
1462 finish_switch_cond (r
, sw
);
1463 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1464 create_anon_label_with_ctx (loc
, actor
));
1465 add_stmt (r
); /* case 0: */
1466 /* Implement the suspend, a scope exit without clean ups. */
1467 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1, susp
);
1468 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1469 add_stmt (r
); // goto ret;
1470 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1471 create_anon_label_with_ctx (loc
, actor
));
1472 add_stmt (r
); // case 1:
1473 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1474 add_stmt (r
); // goto resume;
1475 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1476 create_anon_label_with_ctx (loc
, actor
));
1477 add_stmt (r
); // default:;
1478 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1479 add_stmt (r
); // goto destroy;
1481 /* part of finish switch. */
1482 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1484 tree scope
= SWITCH_STMT_SCOPE (sw
);
1485 SWITCH_STMT_SCOPE (sw
) = NULL
;
1486 r
= do_poplevel (scope
);
1487 append_to_statement_list (r
, &body_list
);
1489 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1490 append_to_statement_list (destroy_label
, &body_list
);
1492 append_to_statement_list (dtor
, &body_list
);
1493 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1494 append_to_statement_list (r
, &body_list
);
1496 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1499 append_to_statement_list (r
, &stmt_list
);
1502 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1503 append_to_statement_list (resume_label
, &stmt_list
);
1505 /* This will produce the value (if one is provided) from the co_await
1507 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1510 default: /* not likely to work .. but... */
1511 append_to_statement_list (resume_call
, &stmt_list
);
1516 /* Replace the use of co_await by the resume expr. */
1517 if (sub_code
== CO_AWAIT_EXPR
)
1519 /* We're updating the interior of a possibly <(void) expr>cleanup. */
1520 TREE_OPERAND (stripped_stmt
, 1) = resume_call
;
1521 append_to_statement_list (saved_statement
, &stmt_list
);
1523 else if (buried_stmt
!= NULL
)
1525 *buried_stmt
= resume_call
;
1526 append_to_statement_list (saved_statement
, &stmt_list
);
1530 error_at (loc
, "failed to substitute the resume method in %qE",
1532 append_to_statement_list (saved_statement
, &stmt_list
);
1537 append_to_statement_list (dtor
, &stmt_list
);
1544 expand_co_awaits (tree fn
, tree
*fnbody
, tree coro_fp
, tree resume_idx
,
1545 tree cleanup
, tree cororet
, tree self_h
)
1548 = {fn
, coro_fp
, resume_idx
, self_h
, cleanup
, cororet
, 2};
1549 cp_walk_tree (fnbody
, co_await_expander
, &data
, NULL
);
1553 /* Suspend point hash_map. */
1555 struct suspend_point_info
1557 /* coro frame field type. */
1558 tree awaitable_type
;
1559 /* coro frame field name. */
1560 tree await_field_id
;
1561 /* suspend method return type. */
1563 /* suspend handle field name, NULL_TREE if not needed. */
1564 tree susp_handle_id
;
1567 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1569 struct await_xform_data
1578 /* When we built the await expressions, we didn't know the coro frame
1579 layout, therefore no idea where to find the promise or where to put
1580 the awaitables. Now we know these things, fill them in. */
1583 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1585 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1586 location_t loc
= EXPR_LOCATION (await_expr
);
1589 error_at (loc
, "no suspend point info for %qD", await_expr
);
1590 return error_mark_node
;
1593 /* So, on entry, we have:
1594 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1595 We no longer need a [it had diagnostic value, maybe?]
1596 We need to replace the promise proxy in all elements
1597 We need to replace the e_proxy in the awr_call.
1600 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1601 tree ah
= NULL_TREE
;
1602 if (si
->susp_handle_id
)
1605 = lookup_member (coro_frame_type
, si
->susp_handle_id
,
1606 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
1607 ah
= build_class_member_access_expr (xform
->actor_frame
, ah_m
, NULL_TREE
,
1608 true, tf_warning_or_error
);
1610 else if (TREE_CODE (si
->suspend_type
) == BOOLEAN_TYPE
)
1611 ah
= boolean_type_node
;
1613 /* Replace Op 0 with the frame slot for the temporary handle, if it's needed.
1614 If there's no frame type to be stored we flag boolean_type for that case
1615 and an empty pointer for void return. */
1616 TREE_OPERAND (await_expr
, 0) = ah
;
1618 /* Get a reference to the initial suspend var in the frame. */
1620 = lookup_member (coro_frame_type
, si
->await_field_id
,
1621 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
1622 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
, NULL_TREE
,
1623 true, tf_warning_or_error
);
1625 /* Replace references to the instance proxy with the frame entry now
1627 proxy_replace data
= {TREE_OPERAND (await_expr
, 1), as
};
1628 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1630 /* .. and replace. */
1631 TREE_OPERAND (await_expr
, 1) = as
;
1633 /* Now do the self_handle. */
1634 data
.from
= xform
->self_h_proxy
;
1635 data
.to
= xform
->real_self_h
;
1636 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1638 /* Now do the promise. */
1639 data
.from
= xform
->promise_proxy
;
1640 data
.to
= xform
->real_promise
;
1641 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1646 /* A wrapper for the transform_await_expr function so that it can be a
1647 callback from cp_walk_tree. */
1650 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1652 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
&& TREE_CODE (*stmt
) != CO_YIELD_EXPR
)
1655 tree await_expr
= *stmt
;
1656 await_xform_data
*xform
= (await_xform_data
*) d
;
1658 *stmt
= transform_await_expr (await_expr
, xform
);
1659 if (*stmt
== error_mark_node
)
1667 vec
<tree
*> *body_uses
;
1671 struct local_var_info
1680 /* For figuring out what local variable usage we have. */
1681 struct local_vars_transform
1685 tree coro_frame_type
;
1687 hash_map
<tree
, local_var_info
> *local_var_uses
;
1691 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
1693 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
1695 /* For each var in this bind expr (that has a frame id, which means it was
1696 accessed), build a frame reference for each and then walk the bind expr
1697 statements, substituting the frame ref for the original var. */
1699 if (TREE_CODE (*stmt
) == BIND_EXPR
)
1702 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1703 lvar
= DECL_CHAIN (lvar
))
1706 local_var_info
&local_var
1707 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
1708 gcc_checking_assert (existed
);
1710 /* Re-write the variable's context to be in the actor func. */
1711 DECL_CONTEXT (lvar
) = lvd
->context
;
1713 /* we need to walk some of the decl trees, which might contain
1714 references to vars replaced at a higher level. */
1715 cp_walk_tree (&DECL_INITIAL (lvar
), transform_local_var_uses
, d
,
1717 cp_walk_tree (&DECL_SIZE (lvar
), transform_local_var_uses
, d
, NULL
);
1718 cp_walk_tree (&DECL_SIZE_UNIT (lvar
), transform_local_var_uses
, d
,
1721 /* TODO: implement selective generation of fields when vars are
1723 if (local_var
.field_id
== NULL_TREE
)
1724 continue; /* Wasn't used. */
1727 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
1728 /*protect*/ 1, /*want_type*/ 0,
1729 tf_warning_or_error
);
1730 tree fld_idx
= build3_loc (lvd
->loc
, COMPONENT_REF
, TREE_TYPE (lvar
),
1731 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
1732 local_var
.field_idx
= fld_idx
;
1734 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
1735 /* Now we have processed and removed references to the original vars,
1736 we can drop those from the bind. */
1737 for (tree
*pvar
= &BIND_EXPR_VARS (*stmt
); *pvar
!= NULL
;)
1740 local_var_info
&local_var
1741 = lvd
->local_var_uses
->get_or_insert (*pvar
, &existed
);
1742 gcc_checking_assert (existed
);
1744 if (local_var
.field_id
== NULL_TREE
)
1745 pvar
= &DECL_CHAIN (*pvar
); /* Wasn't used. */
1747 *pvar
= DECL_CHAIN (*pvar
); // discard this one, we replaced it.
1750 *do_subtree
= 0; /* We've done the body already. */
1754 tree var_decl
= *stmt
;
1755 /* Look inside cleanups, we don't want to wrap a statement list in a
1757 bool needs_cleanup
= true;
1758 if (TREE_CODE (var_decl
) == CLEANUP_POINT_EXPR
)
1759 var_decl
= TREE_OPERAND (var_decl
, 0);
1761 needs_cleanup
= false;
1763 /* Look inside the decl_expr for the actual var. */
1764 bool decl_expr_p
= TREE_CODE (var_decl
) == DECL_EXPR
;
1765 if (decl_expr_p
&& TREE_CODE (DECL_EXPR_DECL (var_decl
)) == VAR_DECL
)
1766 var_decl
= DECL_EXPR_DECL (var_decl
);
1767 else if (TREE_CODE (var_decl
) != VAR_DECL
)
1770 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1771 for the promise and coroutine handle(s), to global vars or to compiler
1772 temporaries. Skip past these, we will handle them later. */
1773 local_var_info
*local_var_i
= lvd
->local_var_uses
->get (var_decl
);
1774 if (local_var_i
== NULL
)
1777 /* This is our revised 'local' i.e. a frame slot. */
1778 tree revised
= local_var_i
->field_idx
;
1779 gcc_checking_assert (DECL_CONTEXT (var_decl
) == lvd
->context
);
1781 if (decl_expr_p
&& DECL_INITIAL (var_decl
))
1783 location_t loc
= DECL_SOURCE_LOCATION (var_decl
);
1785 = cp_build_modify_expr (loc
, revised
, INIT_EXPR
,
1786 DECL_INITIAL (var_decl
), tf_warning_or_error
);
1788 r
= coro_build_cvt_void_expr_stmt (r
, EXPR_LOCATION (*stmt
));
1795 *do_subtree
= 0; /* We've accounted for the nested use. */
1799 /* The actor transform. */
1802 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
1803 tree orig
, hash_map
<tree
, param_info
> *param_uses
,
1804 hash_map
<tree
, local_var_info
> *local_var_uses
,
1805 vec
<tree
, va_gc
> *param_dtor_list
, tree initial_await
,
1806 tree final_await
, unsigned body_count
)
1808 verify_stmt_tree (fnbody
);
1809 /* Some things we inherit from the original function. */
1810 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
1811 tree handle_type
= get_coroutine_handle_type (orig
);
1812 tree self_h_proxy
= get_coroutine_self_handle_proxy (orig
);
1813 tree promise_type
= get_coroutine_promise_type (orig
);
1814 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
1815 tree act_des_fn_type
1816 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
1817 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
1819 /* One param, the coro frame pointer. */
1821 = build_lang_decl (PARM_DECL
, get_identifier ("frame_ptr"), coro_frame_ptr
);
1822 DECL_CONTEXT (actor_fp
) = actor
;
1823 DECL_ARG_TYPE (actor_fp
) = type_passed_as (coro_frame_ptr
);
1824 DECL_ARGUMENTS (actor
) = actor_fp
;
1826 /* A void return. */
1827 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
1828 DECL_ARTIFICIAL (resdecl
) = 1;
1829 DECL_IGNORED_P (resdecl
) = 1;
1830 DECL_RESULT (actor
) = resdecl
;
1831 DECL_COROUTINE_P (actor
) = 1;
1833 /* We have a definition here. */
1834 TREE_STATIC (actor
) = 1;
1836 tree actor_outer
= push_stmt_list ();
1837 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
1838 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
1840 /* ??? Can we dispense with the enclosing bind if the function body does
1841 not start with a bind_expr? (i.e. there's no contained scopes). */
1842 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
1843 tree top_block
= make_node (BLOCK
);
1844 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
1846 /* Update the block associated with the outer scope of the orig fn. */
1847 tree first
= expr_first (fnbody
);
1848 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
1850 /* We will discard this, since it's connected to the original scope
1852 tree block
= BIND_EXPR_BLOCK (first
);
1853 if (block
) // For this to be missing is probably a bug.
1855 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
1856 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
1857 BLOCK_SUPERCONTEXT (block
) = top_block
;
1858 BLOCK_SUBBLOCKS (top_block
) = block
;
1862 add_stmt (actor_bind
);
1863 tree actor_body
= push_stmt_list ();
1865 /* The entry point for the actor code from the ramp. */
1866 tree actor_begin_label
1867 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
1868 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
1870 /* Re-write param references in the body, no code should be generated
1872 if (DECL_ARGUMENTS (orig
) && param_uses
!= NULL
)
1875 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
1878 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
1879 if (parm
.field_id
== NULL_TREE
)
1880 continue; /* Wasn't used. */
1881 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
1882 /*protect*/ 1, /*want_type*/ 0,
1883 tf_warning_or_error
);
1884 tree fld_idx
= build3_loc (loc
, COMPONENT_REF
, TREE_TYPE (arg
),
1885 actor_frame
, fld_ref
, NULL_TREE
);
1888 FOR_EACH_VEC_ELT (*parm
.body_uses
, i
, puse
)
1895 /* Re-write local vars, similarly. */
1896 local_vars_transform xform_vars_data
1897 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
1898 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
1900 tree resume_idx_name
= get_identifier ("__resume_at");
1901 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
1902 tf_warning_or_error
);
1903 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
1904 rat_field
, NULL_TREE
);
1907 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
1909 tree lsb_if
= begin_if_stmt ();
1910 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
1911 build_int_cst (short_unsigned_type_node
, 1));
1912 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
1913 build_int_cst (short_unsigned_type_node
, 0));
1914 finish_if_stmt_cond (chkb0
, lsb_if
);
1916 tree destroy_dispatcher
= begin_switch_stmt ();
1917 finish_switch_cond (rat
, destroy_dispatcher
);
1918 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
1919 create_anon_label_with_ctx (loc
, actor
));
1921 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1922 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
1925 short unsigned lab_num
= 3;
1926 for (unsigned destr_pt
= 0; destr_pt
< body_count
+ 2; destr_pt
++)
1928 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
1929 b
= build_case_label (l_num
, NULL_TREE
,
1930 create_anon_label_with_ctx (loc
, actor
));
1932 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
1934 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
1936 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
1941 /* Insert the prototype dispatcher. */
1942 finish_switch_stmt (destroy_dispatcher
);
1944 finish_then_clause (lsb_if
);
1946 tree dispatcher
= begin_switch_stmt ();
1947 finish_switch_cond (rat
, dispatcher
);
1948 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
1949 create_anon_label_with_ctx (loc
, actor
));
1951 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
1954 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
1955 create_anon_label_with_ctx (loc
, actor
));
1957 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
1958 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
1962 /* The final resume should be made to hit the default (trap, UB) entry. */
1963 for (unsigned resu_pt
= 0; resu_pt
< body_count
+ 1; resu_pt
++)
1965 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
1966 b
= build_case_label (l_num
, NULL_TREE
,
1967 create_anon_label_with_ctx (loc
, actor
));
1969 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
1971 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
1973 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
1978 /* Insert the prototype dispatcher. */
1979 finish_switch_stmt (dispatcher
);
1981 finish_if_stmt (lsb_if
);
1983 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
1986 /* actor's version of the promise. */
1987 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
1988 tf_warning_or_error
);
1989 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
, false,
1990 tf_warning_or_error
);
1992 /* actor's coroutine 'self handle'. */
1993 tree ash_m
= lookup_member (coro_frame_type
, get_identifier ("__self_h"), 1,
1994 0, tf_warning_or_error
);
1995 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
1996 false, tf_warning_or_error
);
1997 /* So construct the self-handle from the frame address. */
1998 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
1999 0, tf_warning_or_error
);
2001 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2002 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2003 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2004 NULL
, tf_warning_or_error
);
2005 r
= build2 (INIT_EXPR
, handle_type
, ash
, hfa
);
2006 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2008 release_tree_vector (args
);
2010 /* Now we know the real promise, and enough about the frame layout to
2011 decide where to put things. */
2013 await_xform_data xform
2014 = {actor_frame
, promise_proxy
, ap
, self_h_proxy
, ash
};
2016 /* Get a reference to the initial suspend var in the frame. */
2017 transform_await_expr (initial_await
, &xform
);
2018 r
= coro_build_expr_stmt (initial_await
, loc
);
2021 /* Now we've built the promise etc, process fnbody for co_returns.
2022 We want the call to return_void () below and it has no params so
2023 we can create it once here.
2024 Calls to return_value () will have to be checked and created as
2027 tree return_void
= NULL_TREE
;
2029 = lookup_promise_method (orig
, coro_return_void_identifier
, loc
,
2030 /*musthave=*/ false);
2031 if (rvm
&& rvm
!= error_mark_node
)
2033 = build_new_method_call (ap
, rvm
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2034 tf_warning_or_error
);
2036 /* co_return branches to the final_suspend label, so declare that now. */
2037 tree fs_label
= create_named_label_with_ctx (loc
, "final.suspend", actor
);
2039 /* Expand co_returns in the saved function body */
2040 fnbody
= expand_co_returns (&fnbody
, promise_proxy
, ap
, fs_label
);
2042 /* Transform the await expressions in the function body. Only do each
2044 hash_set
<tree
> pset
;
2045 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2047 /* Add in our function body with the co_returns rewritten to final form. */
2050 /* [stmt.return.coroutine] (2.2 : 3) if p.return_void() is a valid
2051 expression, flowing off the end of a coroutine is equivalent to
2052 co_return; otherwise UB.
2053 We just inject the call to p.return_void() here, and fall through to
2054 the final_suspend: label (eliding the goto). If the function body has
2055 a co_return, then this statement will be unreachable and DCEd. */
2056 if (return_void
!= NULL_TREE
)
2057 add_stmt (return_void
);
2059 /* Final suspend starts here. */
2060 r
= build_stmt (loc
, LABEL_EXPR
, fs_label
);
2063 /* Set the actor pointer to null, so that 'done' will work.
2064 Resume from here is UB anyway - although a 'ready' await will
2065 branch to the final resume, and fall through to the destroy. */
2067 = lookup_member (coro_frame_type
, get_identifier ("__resume"),
2068 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
2069 tree res_x
= build_class_member_access_expr (actor_frame
, resume_m
, NULL_TREE
,
2070 false, tf_warning_or_error
);
2071 r
= build1 (CONVERT_EXPR
, act_des_fn_ptr
, integer_zero_node
);
2072 r
= build2 (INIT_EXPR
, act_des_fn_ptr
, res_x
, r
);
2073 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2076 /* Get a reference to the final suspend var in the frame. */
2077 transform_await_expr (final_await
, &xform
);
2078 r
= coro_build_expr_stmt (final_await
, loc
);
2081 /* now do the tail of the function. */
2082 tree del_promise_label
2083 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2084 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2087 /* Destructors for the things we built explicitly. */
2088 r
= build_special_member_call (ap
, complete_dtor_identifier
, NULL
,
2089 promise_type
, LOOKUP_NORMAL
,
2090 tf_warning_or_error
);
2093 tree del_frame_label
2094 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2095 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2098 /* Here deallocate the frame (if we allocated it), which we will have at
2101 = lookup_member (coro_frame_type
, get_identifier ("__frame_needs_free"), 1,
2102 0, tf_warning_or_error
);
2103 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2104 false, tf_warning_or_error
);
2106 tree need_free_if
= begin_if_stmt ();
2107 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2108 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2109 finish_if_stmt_cond (cmp
, need_free_if
);
2110 if (param_dtor_list
!= NULL
)
2114 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2117 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2118 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2119 false, tf_warning_or_error
);
2120 tree t
= TREE_TYPE (a
);
2123 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2124 LOOKUP_NORMAL
, tf_warning_or_error
);
2129 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2130 tree arg
= build1 (CONVERT_EXPR
, ptr_type_node
, actor_fp
);
2131 vec
<tree
, va_gc
> *arglist
= make_tree_vector_single (arg
);
2133 /* The user can (optionally) provide a delete function in the promise
2134 type, it's not a failure for it to be absent. */
2135 tree fns
= lookup_promise_method (orig
, delname
, loc
, false);
2136 tree del_coro_fr
= NULL_TREE
;
2137 if (fns
&& fns
!= error_mark_node
)
2139 del_coro_fr
= lookup_arg_dependent (delname
, fns
, arglist
);
2140 if (OVL_P (del_coro_fr
))
2141 del_coro_fr
= OVL_FIRST (del_coro_fr
);
2143 del_coro_fr
= BASELINK_FUNCTIONS (del_coro_fr
);
2145 gcc_checking_assert (DECL_STATIC_FUNCTION_P (del_coro_fr
));
2146 TREE_USED (del_coro_fr
) = 1;
2147 del_coro_fr
= build_call_expr_loc_vec (loc
, del_coro_fr
, arglist
);
2150 /* If that fails, then fall back to the global delete operator. */
2151 if (del_coro_fr
== NULL_TREE
|| del_coro_fr
== error_mark_node
)
2153 fns
=lookup_name_real (delname
, 0, 1, /*block_p=*/true, 0, 0);
2154 del_coro_fr
= lookup_arg_dependent (del_coro_fr
, fns
, arglist
);
2155 del_coro_fr
= build_new_function_call (del_coro_fr
, &arglist
, true);
2158 del_coro_fr
= coro_build_cvt_void_expr_stmt (del_coro_fr
, loc
);
2159 add_stmt (del_coro_fr
);
2160 finish_then_clause (need_free_if
);
2161 tree scope
= IF_SCOPE (need_free_if
);
2162 IF_SCOPE (need_free_if
) = NULL
;
2163 r
= do_poplevel (scope
);
2167 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2168 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2169 r
= maybe_cleanup_point_expr_void (r
);
2172 /* This is the suspend return point. */
2173 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2176 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2177 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2178 r
= maybe_cleanup_point_expr_void (r
);
2181 /* We need the resume index to work with. */
2183 = lookup_member (coro_frame_type
, resume_idx_name
,
2184 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
2186 = build_class_member_access_expr (actor_frame
, res_idx_m
, NULL_TREE
, false,
2187 tf_warning_or_error
);
2189 /* We've now rewritten the tree and added the initial and final
2190 co_awaits. Now pass over the tree and expand the co_awaits. */
2191 actor_body
= expand_co_awaits (actor
, &actor_body
, actor_fp
, res_idx
,
2192 del_promise_label
, ret_label
, ash
);
2194 actor_body
= pop_stmt_list (actor_body
);
2195 BIND_EXPR_BODY (actor_bind
) = actor_body
;
2197 finish_compound_stmt (stmt
);
2198 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2199 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2202 /* The prototype 'destroy' function :
2203 frame->__resume_at |= 1;
2207 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2210 /* One param, the coro frame pointer. */
2211 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
2213 = build_lang_decl (PARM_DECL
, get_identifier ("frame_ptr"), coro_frame_ptr
);
2214 DECL_CONTEXT (destr_fp
) = destroy
;
2215 DECL_ARG_TYPE (destr_fp
) = type_passed_as (coro_frame_ptr
);
2216 DECL_ARGUMENTS (destroy
) = destr_fp
;
2218 /* A void return. */
2219 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2220 DECL_ARTIFICIAL (resdecl
) = 1;
2221 DECL_IGNORED_P (resdecl
) = 1;
2222 DECL_RESULT (destroy
) = resdecl
;
2224 /* We have a definition here. */
2225 TREE_STATIC (destroy
) = 1;
2226 DECL_COROUTINE_P (destroy
) = 1;
2228 tree destr_outer
= push_stmt_list ();
2229 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2230 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2232 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2234 tree resume_idx_name
= get_identifier ("__resume_at");
2235 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2236 tf_warning_or_error
);
2237 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, destr_frame
,
2238 rat_field
, NULL_TREE
);
2240 /* _resume_at |= 1 */
2241 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2242 build_int_cst (short_unsigned_type_node
, 1));
2243 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2244 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2247 /* So .. call the actor .. */
2248 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2249 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2253 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2254 r
= maybe_cleanup_point_expr_void (r
);
2257 finish_compound_stmt (dstr_stmt
);
2258 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2261 /* Helper that returns an identifier for an appended extension to the
2262 current un-mangled function name. */
2265 get_fn_local_identifier (tree orig
, const char *append
)
2267 /* Figure out the bits we need to generate names for the outlined things
2268 For consistency, this needs to behave the same way as
2269 ASM_FORMAT_PRIVATE_NAME does. */
2270 tree nm
= DECL_NAME (orig
);
2271 const char *sep
, *pfx
= "";
2272 #ifndef NO_DOT_IN_LABEL
2275 #ifndef NO_DOLLAR_IN_LABEL
2284 if (DECL_ASSEMBLER_NAME (orig
))
2285 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2287 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2288 && DECL_TI_ARGS (orig
))
2290 tree tpl_args
= DECL_TI_ARGS (orig
);
2291 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2292 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2294 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2295 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2297 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2300 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2302 return get_identifier (an
);
2306 build_init_or_final_await (location_t loc
, bool is_final
)
2308 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2309 : coro_initial_suspend_identifier
;
2310 tree setup_meth
= lookup_promise_method (current_function_decl
, suspend_alt
,
2311 loc
, /*musthave=*/ true);
2312 if (!setup_meth
|| setup_meth
== error_mark_node
)
2313 return error_mark_node
;
2315 tree s_fn
= NULL_TREE
;
2316 tree setup_call
= build_new_method_call (
2317 get_coroutine_promise_proxy (current_function_decl
), setup_meth
, NULL
,
2318 NULL_TREE
, LOOKUP_NORMAL
, &s_fn
, tf_warning_or_error
);
2320 if (!s_fn
|| setup_call
== error_mark_node
)
2321 return error_mark_node
;
2323 /* So build the co_await for this */
2324 /* For initial/final suspends the call is is "a" per [expr.await] 3.2. */
2325 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2326 : INITIAL_SUSPEND_POINT
));
2329 /* Callback to record the essential data for each await point found in the
2333 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
, tree susp_type
,
2334 tree susp_handle_nam
)
2337 suspend_point_info
&s
2338 = suspend_points
->get_or_insert (await_expr
, &seen
);
2341 error_at (EXPR_LOCATION (await_expr
), "duplicate info for %qE",
2345 s
.awaitable_type
= aw_type
;
2346 s
.await_field_id
= aw_nam
;
2347 s
.suspend_type
= susp_type
;
2348 s
.susp_handle_id
= susp_handle_nam
;
2352 /* Small helper for the repetitive task of adding a new field to the coro
2356 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
2359 tree id
= get_identifier (name
);
2360 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
2361 DECL_CHAIN (decl
) = *field_list
;
2366 struct susp_frame_data
2370 hash_set
<tree
> captured_temps
;
2371 vec
<tree
, va_gc
> *to_replace
;
2372 vec
<tree
, va_gc
> *block_stack
;
2374 unsigned saw_awaits
;
2375 bool captures_temporary
;
2378 /* Helper to return the type of an awaiter's await_suspend() method.
2379 We start with the result of the build method call, which will be either
2380 a call expression (void, bool) or a target expressions (handle). */
2383 get_await_suspend_return_type (tree aw_expr
)
2385 tree susp_fn
= TREE_VEC_ELT (TREE_OPERAND (aw_expr
, 3), 1);
2386 if (TREE_CODE (susp_fn
) == CALL_EXPR
)
2388 susp_fn
= CALL_EXPR_FN (susp_fn
);
2389 if (TREE_CODE (susp_fn
) == ADDR_EXPR
)
2390 susp_fn
= TREE_OPERAND (susp_fn
, 0);
2391 return TREE_TYPE (TREE_TYPE (susp_fn
));
2393 else if (TREE_CODE (susp_fn
) == TARGET_EXPR
)
2394 return TREE_TYPE (susp_fn
);
2395 return TREE_TYPE (susp_fn
);
2398 /* Walk the sub-tree looking for call expressions that both capture
2399 references and have compiler-temporaries as parms. */
2402 captures_temporary (tree
*stmt
, int *do_subtree
, void *d
)
2404 /* Stop recursing if we see an await expression, the subtrees
2405 of that will be handled when it it processed. */
2406 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
|| TREE_CODE (*stmt
) == CO_YIELD_EXPR
)
2412 /* We're only interested in calls. */
2413 if (TREE_CODE (*stmt
) != CALL_EXPR
)
2416 /* Does this call capture references?
2417 Strip the ADDRESS_EXPR to get the fn decl and inspect it. */
2418 tree fn
= TREE_OPERAND (CALL_EXPR_FN (*stmt
), 0);
2419 bool is_meth
= TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
;
2420 tree arg
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2421 unsigned offset
= 3;
2422 for (unsigned anum
= 0; arg
!= NULL
; arg
= TREE_CHAIN (arg
), anum
++)
2424 tree parm_type
= TREE_VALUE (arg
);
2425 if (anum
== 0 && is_meth
&& INDIRECT_TYPE_P (parm_type
))
2427 /* Account for 'this' when the fn is a method. Unless it
2428 belongs to a CTOR or DTOR. */
2429 if (DECL_CONSTRUCTOR_P (fn
) || DECL_DESTRUCTOR_P (fn
))
2432 else if (!TYPE_REF_P (parm_type
))
2433 /* If it's not a reference, we don't care. */
2436 /* Fetch the value presented to the fn. */
2437 tree parm
= TREE_OPERAND (*stmt
, anum
+ offset
);
2439 while (TREE_CODE (parm
) == NOP_EXPR
)
2440 parm
= TREE_OPERAND (parm
, 0);
2442 /* We only care if we're taking the addr of a temporary. */
2443 if (TREE_CODE (parm
) != ADDR_EXPR
)
2446 parm
= TREE_OPERAND (parm
, 0);
2447 if (TREE_CODE (parm
) == VAR_DECL
&& !DECL_ARTIFICIAL (parm
))
2448 /* This isn't a temporary... */
2451 if (TREE_CODE (parm
) == PARM_DECL
)
2452 /* .. nor is this... */
2455 if (TREE_CODE (parm
) == TARGET_EXPR
)
2457 /* We're taking the address of a temporary and using it as a ref. */
2458 tree tvar
= TREE_OPERAND (parm
, 0);
2459 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2461 susp_frame_data
*data
= (susp_frame_data
*) d
;
2462 data
->captures_temporary
= true;
2463 /* Record this one so we don't duplicate, and on the first
2464 occurrence note the target expr to be replaced. */
2465 if (!data
->captured_temps
.add (tvar
))
2466 vec_safe_push (data
->to_replace
, parm
);
2467 /* Now see if the initializer contains any more cases. */
2468 hash_set
<tree
> visited
;
2469 tree res
= cp_walk_tree (&TREE_OPERAND (parm
, 1),
2470 captures_temporary
, d
, &visited
);
2473 /* Otherwise, we're done with sub-trees for this. */
2475 else if (TREE_CODE (parm
) == CO_AWAIT_EXPR
)
2477 /* CO_AWAIT expressions behave in a similar manner to target
2478 expressions when the await_resume call is contained in one. */
2479 tree awr
= TREE_OPERAND (parm
, 3); /* call vector. */
2480 awr
= TREE_VEC_ELT (awr
, 2); /* resume call. */
2481 if (TREE_CODE (awr
) == TARGET_EXPR
)
2483 tree tvar
= TREE_OPERAND (awr
, 0);
2484 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2486 susp_frame_data
*data
= (susp_frame_data
*) d
;
2487 data
->captures_temporary
= true;
2488 /* Use this as a place-holder. */
2489 if (!data
->captured_temps
.add (tvar
))
2490 vec_safe_push (data
->to_replace
, parm
);
2492 /* We will walk the sub-trees of this co_await separately. */
2497 /* As far as it's necessary, we've walked the subtrees of the call
2503 /* If this is an await, then register it and decide on what coro
2504 frame storage is needed.
2505 If this is a co_yield (which embeds an await), drop the yield
2506 and record the await (the yield was kept for diagnostics only). */
2509 register_awaits (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
2511 susp_frame_data
*data
= (susp_frame_data
*) d
;
2513 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
&& TREE_CODE (*stmt
) != CO_YIELD_EXPR
)
2516 /* co_yield is syntactic sugar, re-write it to co_await. */
2517 tree aw_expr
= *stmt
;
2518 location_t aw_loc
= EXPR_LOCATION (aw_expr
); /* location of the co_xxxx. */
2519 if (TREE_CODE (aw_expr
) == CO_YIELD_EXPR
)
2521 aw_expr
= TREE_OPERAND (aw_expr
, 1);
2525 /* Count how many awaits full expression contains. This is not the same
2526 as the counter used for the function-wide await point number. */
2529 /* The required field has the same type as the proxy stored in the
2531 tree aw_field_type
= TREE_TYPE (TREE_OPERAND (aw_expr
, 1));
2533 size_t bufsize
= sizeof ("__aw_s.") + 10;
2534 char *buf
= (char *) alloca (bufsize
);
2535 snprintf (buf
, bufsize
, "__aw_s.%d", data
->count
);
2537 = coro_make_frame_entry (data
->field_list
, buf
, aw_field_type
, aw_loc
);
2539 /* Find out what we have to do with the awaiter's suspend method (this
2540 determines if we need somewhere to stash the suspend method's handle).
2541 Cache the result of this in the suspend point info.
2543 (5.1) If the result of await-ready is false, the coroutine is considered
2545 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
2546 await-suspend.resume() is evaluated.
2547 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
2548 and the coroutine is resumed if the result is false.
2549 (5.1.3) Otherwise, await-suspend is evaluated.
2551 tree susp_typ
= get_await_suspend_return_type (aw_expr
);
2552 tree handle_field_nam
;
2553 if (VOID_TYPE_P (susp_typ
) || TREE_CODE (susp_typ
) == BOOLEAN_TYPE
)
2554 handle_field_nam
= NULL_TREE
; /* no handle is needed. */
2557 snprintf (buf
, bufsize
, "__aw_h.%u", data
->count
);
2559 = coro_make_frame_entry (data
->field_list
, buf
, susp_typ
, aw_loc
);
2561 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
, susp_typ
,
2564 data
->count
++; /* Each await suspend context is unique. */
2566 /* We now need to know if to take special action on lifetime extension
2567 of temporaries captured by reference. This can only happen if such
2568 a case appears in the initializer for the awaitable. The callback
2569 records captured temporaries including subtrees of initializers. */
2570 hash_set
<tree
> visited
;
2571 tree res
= cp_walk_tree (&TREE_OPERAND (aw_expr
, 2), captures_temporary
, d
,
2576 /* The gimplifier correctly extends the lifetime of temporaries captured
2577 by reference (per. [class.temporary] (6.9) "A temporary object bound
2578 to a reference parameter in a function call persists until the completion
2579 of the full-expression containing the call"). However, that is not
2580 sufficient to work across a suspension - and we need to promote such
2581 temporaries to be regular vars that will then get a coro frame slot.
2582 We don't want to incur the effort of checking for this unless we have
2583 an await expression in the current full expression. */
2586 maybe_promote_captured_temps (tree
*stmt
, void *d
)
2588 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2589 hash_set
<tree
> visited
;
2590 awpts
->saw_awaits
= 0;
2592 /* When register_awaits sees an await, it walks the initializer for
2593 that await looking for temporaries captured by reference and notes
2594 them in awpts->captured_temps. We only need to take any action
2595 here if the statement contained any awaits, and any of those had
2596 temporaries captured by reference in the initializers for their class.
2599 tree res
= cp_walk_tree (stmt
, register_awaits
, d
, &visited
);
2600 if (!res
&& awpts
->saw_awaits
> 0 && !awpts
->captured_temps
.is_empty ())
2602 location_t sloc
= EXPR_LOCATION (*stmt
);
2604 = build3_loc (sloc
, BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2605 tree aw_statement_current
;
2606 if (TREE_CODE (*stmt
) == CLEANUP_POINT_EXPR
)
2607 aw_statement_current
= TREE_OPERAND (*stmt
, 0);
2609 aw_statement_current
= *stmt
;
2610 /* Collected the scope vars we need move the temps to regular. */
2611 tree aw_bind_body
= push_stmt_list ();
2612 tree varlist
= NULL_TREE
;
2614 while (!awpts
->to_replace
->is_empty ())
2616 size_t bufsize
= sizeof ("__aw_.tmp.") + 20;
2617 char *buf
= (char *) alloca (bufsize
);
2618 snprintf (buf
, bufsize
, "__aw_%d.tmp.%d", awpts
->count
, vnum
);
2619 tree to_replace
= awpts
->to_replace
->pop ();
2621 if (TREE_CODE (to_replace
) == CO_AWAIT_EXPR
)
2623 orig_temp
= TREE_OPERAND (to_replace
, 3);
2624 orig_temp
= TREE_VEC_ELT (orig_temp
, 2);
2625 orig_temp
= TREE_OPERAND (orig_temp
, 0);
2628 orig_temp
= TREE_OPERAND (to_replace
, 0);
2630 tree var_type
= TREE_TYPE (orig_temp
);
2631 gcc_assert (same_type_p (TREE_TYPE (to_replace
), var_type
));
2633 = build_lang_decl (VAR_DECL
, get_identifier (buf
), var_type
);
2634 DECL_CONTEXT (newvar
) = DECL_CONTEXT (orig_temp
);
2635 if (DECL_SOURCE_LOCATION (orig_temp
))
2636 sloc
= DECL_SOURCE_LOCATION (orig_temp
);
2637 DECL_SOURCE_LOCATION (newvar
) = sloc
;
2638 DECL_CHAIN (newvar
) = varlist
;
2641 = build2_loc (sloc
, INIT_EXPR
, var_type
, newvar
, to_replace
);
2642 stmt
= coro_build_cvt_void_expr_stmt (stmt
, sloc
);
2644 proxy_replace pr
= {to_replace
, newvar
};
2645 /* Replace all instances of that temp in the original expr. */
2646 cp_walk_tree (&aw_statement_current
, replace_proxy
, &pr
, NULL
);
2648 /* What's left should be the original statement with any temporaries
2650 add_stmt (aw_statement_current
);
2651 BIND_EXPR_BODY (aw_bind
) = pop_stmt_list (aw_bind_body
);
2652 awpts
->captured_temps
.empty ();
2654 BIND_EXPR_VARS (aw_bind
) = nreverse (varlist
);
2655 tree b_block
= make_node (BLOCK
);
2656 if (!awpts
->block_stack
->is_empty ())
2658 tree s_block
= awpts
->block_stack
->last ();
2661 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
2662 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
2663 BLOCK_SUBBLOCKS (s_block
) = b_block
;
2666 BIND_EXPR_BLOCK (aw_bind
) = b_block
;
2674 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
2676 tree res
= NULL_TREE
;
2677 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2679 /* We might need to insert a new bind expression, and want to link it
2680 into the correct scope, so keep a note of the current block scope. */
2681 if (TREE_CODE (*stmt
) == BIND_EXPR
)
2683 tree
*body
= &BIND_EXPR_BODY (*stmt
);
2684 tree blk
= BIND_EXPR_BLOCK (*stmt
);
2685 vec_safe_push (awpts
->block_stack
, blk
);
2687 if (TREE_CODE (*body
) == STATEMENT_LIST
)
2689 tree_stmt_iterator i
;
2690 for (i
= tsi_start (*body
); !tsi_end_p (i
); tsi_next (&i
))
2692 tree
*new_stmt
= tsi_stmt_ptr (i
);
2693 if (STATEMENT_CLASS_P (*new_stmt
) || !EXPR_P (*new_stmt
)
2694 || TREE_CODE (*new_stmt
) == BIND_EXPR
)
2695 res
= cp_walk_tree (new_stmt
, await_statement_walker
, d
, NULL
);
2697 res
= maybe_promote_captured_temps (new_stmt
, d
);
2701 *do_subtree
= 0; /* Done subtrees. */
2703 else if (!STATEMENT_CLASS_P (*body
) && EXPR_P (*body
)
2704 && TREE_CODE (*body
) != BIND_EXPR
)
2706 res
= maybe_promote_captured_temps (body
, d
);
2707 *do_subtree
= 0; /* Done subtrees. */
2709 awpts
->block_stack
->pop ();
2711 else if (!STATEMENT_CLASS_P (*stmt
) && EXPR_P (*stmt
)
2712 && TREE_CODE (*stmt
) != BIND_EXPR
)
2714 res
= maybe_promote_captured_temps (stmt
, d
);
2715 *do_subtree
= 0; /* Done subtrees. */
2717 /* If it wasn't a statement list, or a single statement, continue. */
2721 /* For figuring out what param usage we have. */
2723 struct param_frame_data
2726 hash_map
<tree
, param_info
> *param_uses
;
2732 register_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
2734 param_frame_data
*data
= (param_frame_data
*) d
;
2736 if (TREE_CODE (*stmt
) != PARM_DECL
)
2740 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
2741 gcc_checking_assert (existed
);
2743 if (parm
.field_id
== NULL_TREE
)
2745 tree actual_type
= TREE_TYPE (*stmt
);
2747 if (!COMPLETE_TYPE_P (actual_type
))
2748 actual_type
= complete_type_or_else (actual_type
, *stmt
);
2750 if (actual_type
== NULL_TREE
)
2751 /* Diagnostic emitted by complete_type_or_else. */
2752 actual_type
= error_mark_node
;
2754 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
2755 actual_type
= build_pointer_type (TREE_TYPE (actual_type
));
2757 parm
.frame_type
= actual_type
;
2758 tree pname
= DECL_NAME (*stmt
);
2759 size_t namsize
= sizeof ("__parm.") + IDENTIFIER_LENGTH (pname
) + 1;
2760 char *buf
= (char *) alloca (namsize
);
2761 snprintf (buf
, namsize
, "__parm.%s", IDENTIFIER_POINTER (pname
));
2763 = coro_make_frame_entry (data
->field_list
, buf
, actual_type
, data
->loc
);
2764 vec_alloc (parm
.body_uses
, 4);
2765 parm
.body_uses
->quick_push (stmt
);
2766 data
->param_seen
= true;
2769 parm
.body_uses
->safe_push (stmt
);
2774 /* For figuring out what local variable usage we have. */
2776 struct local_vars_frame_data
2779 hash_map
<tree
, local_var_info
> *local_var_uses
;
2780 vec
<local_var_info
> *captures
;
2781 unsigned int nest_depth
, bind_indx
;
2784 bool local_var_seen
;
2788 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
2790 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
2792 /* As we enter a bind expression - record the vars there and then recurse.
2793 As we exit drop the nest depth.
2794 The bind index is a growing count of how many bind indices we've seen.
2795 We build a space in the frame for each local var.
2797 if (TREE_CODE (*stmt
) == BIND_EXPR
)
2802 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
2803 lvar
= DECL_CHAIN (lvar
))
2806 local_var_info
&local_var
2807 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
2808 gcc_checking_assert (!existed
);
2809 tree lvtype
= TREE_TYPE (lvar
);
2810 tree lvname
= DECL_NAME (lvar
);
2811 bool captured
= is_normal_capture_proxy (lvar
);
2812 /* Make names depth+index unique, so that we can support nested
2813 scopes with identically named locals. */
2815 size_t namsize
= sizeof ("__lv...") + 18;
2816 const char *nm
= (captured
? "cp" : "lv");
2817 if (lvname
!= NULL_TREE
)
2819 namsize
+= IDENTIFIER_LENGTH (lvname
);
2820 buf
= (char *) alloca (namsize
);
2821 snprintf (buf
, namsize
, "__%s.%u.%u.%s", nm
, lvd
->bind_indx
,
2822 lvd
->nest_depth
, IDENTIFIER_POINTER (lvname
));
2826 namsize
+= 10; // 'D' followed by an unsigned.
2827 buf
= (char *) alloca (namsize
);
2828 snprintf (buf
, namsize
, "__%s.%u.%u.D%u", nm
, lvd
->bind_indx
,
2829 lvd
->nest_depth
, DECL_UID (lvar
));
2831 /* TODO: Figure out if we should build a local type that has any
2832 excess alignment or size from the original decl. */
2834 = coro_make_frame_entry (lvd
->field_list
, buf
, lvtype
, lvd
->loc
);
2835 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
2836 local_var
.frame_type
= lvtype
;
2837 local_var
.field_idx
= NULL_TREE
;
2840 gcc_checking_assert (DECL_INITIAL (lvar
) == NULL_TREE
);
2841 local_var
.captured
= lvar
;
2842 lvd
->captures
->safe_push (local_var
);
2843 lvd
->saw_capture
= true;
2846 local_var
.captured
= NULL
;
2847 lvd
->local_var_seen
= true;
2848 /* We don't walk any of the local var sub-trees, they won't contain
2851 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
2852 *do_subtree
= 0; /* We've done this. */
2859 a) Check that the function and promise type are valid for a
2861 b) Carry out the initial morph to create the skeleton of the
2862 coroutine ramp function and the rewritten body.
2866 1. We only hit this code once all dependencies are resolved.
2867 2. The function body will be either a bind expr or a statement list
2868 3. That cfun and current_function_decl are valid for the case we're
2870 4. 'input_location' will be of the final brace for the function.
2872 We do something like this:
2873 declare a dummy coro frame.
2875 using handle_type = coro::coroutine_handle<coro1::promise_type>;
2876 void (*__resume)(_R_frame *);
2877 void (*__destroy)(_R_frame *);
2878 coro1::promise_type __p;
2879 bool frame_needs_free; // free the coro frame mem if set.
2880 short __resume_at; // this is where clang puts it - but it's a smaller entity.
2881 coro1::suspend_never_prt __is;
2882 (maybe) handle_type i_hand;
2883 coro1::suspend_always_prt __fs;
2884 (maybe) handle_type f_hand;
2885 (maybe) parameters used in the body.
2886 (maybe) local variables saved
2887 (maybe) trailing space.
2891 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
2893 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
2895 if (!coro_function_valid_p (orig
))
2898 /* The ramp function does return a value. */
2899 current_function_returns_value
= 1;
2901 /* We can't validly get here with an empty statement list, since there's no
2902 way for the FE to decide it's a coroutine in the absence of any code. */
2903 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
2904 if (fnbody
== NULL_TREE
)
2907 /* We don't have the locus of the opening brace - it's filled in later (and
2908 there doesn't really seem to be any easy way to get at it).
2909 The closing brace is assumed to be input_location. */
2910 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
2911 gcc_rich_location
fn_start_loc (fn_start
);
2913 /* Initial processing of the captured body.
2914 If we have no expressions or just an error then punt. */
2915 tree body_start
= expr_first (fnbody
);
2916 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
2918 DECL_SAVED_TREE (orig
) = push_stmt_list ();
2919 append_to_statement_list (DECL_SAVED_TREE (orig
), &fnbody
);
2923 /* So, we've tied off the original body. Now start the replacement.
2924 If we encounter a fatal error we might return a now-empty body.
2925 TODO: determine if it would help to restore the original.
2926 determine if looking for more errors in coro_function_valid_p()
2927 and stashing types is a better solution.
2930 tree newbody
= push_stmt_list ();
2931 DECL_SAVED_TREE (orig
) = newbody
;
2933 /* If our original body is noexcept, then that's what we apply to our
2934 generated functions. Remember that we're NOEXCEPT and fish out the
2935 contained list (we tied off to the top level already). */
2936 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
2939 /* Simplified abstract from begin_eh_spec_block, since we already
2940 know the outcome. */
2941 fnbody
= TREE_OPERAND (body_start
, 0); /* Stash the original... */
2942 add_stmt (body_start
); /* ... and start the new. */
2943 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
2946 /* Create the coro frame type, as far as it can be known at this stage.
2947 1. Types we already know. */
2949 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
2950 gcc_assert (!VOID_TYPE_P (fn_return_type
));
2951 tree handle_type
= get_coroutine_handle_type (orig
);
2952 tree promise_type
= get_coroutine_promise_type (orig
);
2954 /* 2. Types we need to define or look up. */
2956 /* We need to know, and inspect, each suspend point in the function
2957 in several places. It's convenient to place this map out of line
2958 since it's used from tree walk callbacks. */
2959 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
2961 /* Initial and final suspend types are special in that the co_awaits for
2962 them are synthetic. We need to find the type for each awaiter from
2963 the coroutine promise. */
2964 tree initial_await
= build_init_or_final_await (fn_start
, false);
2965 if (initial_await
== error_mark_node
)
2967 /* The type of the frame var for this is the type of its temp proxy. */
2968 tree initial_suspend_type
= TREE_TYPE (TREE_OPERAND (initial_await
, 1));
2970 tree final_await
= build_init_or_final_await (fn_start
, true);
2971 if (final_await
== error_mark_node
)
2974 /* The type of the frame var for this is the type of its temp proxy. */
2975 tree final_suspend_type
= TREE_TYPE (TREE_OPERAND (final_await
, 1));
2977 tree fr_name
= get_fn_local_identifier (orig
, "frame");
2978 tree coro_frame_type
= xref_tag (record_type
, fr_name
, ts_current
, false);
2979 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
2980 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
2981 tree act_des_fn_type
2982 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
2983 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
2985 /* Declare the actor function. */
2986 tree actor_name
= get_fn_local_identifier (orig
, "actor");
2987 tree actor
= build_lang_decl (FUNCTION_DECL
, actor_name
, act_des_fn_type
);
2988 DECL_CONTEXT (actor
) = DECL_CONTEXT (orig
);
2989 DECL_INITIAL (actor
) = error_mark_node
;
2991 /* Declare the destroyer function. */
2992 tree destr_name
= get_fn_local_identifier (orig
, "destroy");
2993 tree destroy
= build_lang_decl (FUNCTION_DECL
, destr_name
, act_des_fn_type
);
2994 DECL_CONTEXT (destroy
) = DECL_CONTEXT (orig
);
2995 DECL_INITIAL (destroy
) = error_mark_node
;
2997 /* Build our dummy coro frame layout. */
2998 coro_frame_type
= begin_class_definition (coro_frame_type
);
3000 tree field_list
= NULL_TREE
;
3002 = coro_make_frame_entry (&field_list
, "__resume", act_des_fn_ptr
, fn_start
);
3003 tree destroy_name
= coro_make_frame_entry (&field_list
, "__destroy",
3004 act_des_fn_ptr
, fn_start
);
3006 = coro_make_frame_entry (&field_list
, "__p", promise_type
, fn_start
);
3007 tree fnf_name
= coro_make_frame_entry (&field_list
, "__frame_needs_free",
3008 boolean_type_node
, fn_start
);
3009 tree resume_idx_name
3010 = coro_make_frame_entry (&field_list
, "__resume_at",
3011 short_unsigned_type_node
, fn_start
);
3013 /* We need a handle to this coroutine, which is passed to every
3014 await_suspend(). There's no point in creating it over and over. */
3015 (void) coro_make_frame_entry (&field_list
, "__self_h", handle_type
, fn_start
);
3017 /* Initial suspend is mandated. */
3018 tree init_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.is",
3019 initial_suspend_type
, fn_start
);
3021 /* Figure out if we need a saved handle from the awaiter type. */
3022 tree ret_typ
= get_await_suspend_return_type (initial_await
);
3023 tree init_hand_name
;
3024 if (VOID_TYPE_P (ret_typ
) || TREE_CODE (ret_typ
) == BOOLEAN_TYPE
)
3025 init_hand_name
= NULL_TREE
; /* no handle is needed. */
3029 = coro_make_frame_entry (&field_list
, "__ih", ret_typ
, fn_start
);
3032 register_await_info (initial_await
, initial_suspend_type
, init_susp_name
,
3033 ret_typ
, init_hand_name
);
3035 /* Now insert the data for any body await points, at this time we also need
3036 to promote any temporaries that are captured by reference (to regular
3037 vars) they will get added to the coro frame along with other locals. */
3038 susp_frame_data body_aw_points
3039 = {&field_list
, handle_type
, hash_set
<tree
> (), NULL
, NULL
, 0, 0, false};
3040 body_aw_points
.to_replace
= make_tree_vector ();
3041 body_aw_points
.block_stack
= make_tree_vector ();
3042 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
3044 /* Final suspend is mandated. */
3045 tree fin_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.fs",
3046 final_suspend_type
, fn_start
);
3048 ret_typ
= get_await_suspend_return_type (final_await
);
3050 if (VOID_TYPE_P (ret_typ
) || TREE_CODE (ret_typ
) == BOOLEAN_TYPE
)
3051 fin_hand_name
= NULL_TREE
; /* no handle is needed. */
3055 = coro_make_frame_entry (&field_list
, "__fh", ret_typ
, fn_start
);
3058 register_await_info (final_await
, final_suspend_type
, fin_susp_name
,
3059 void_type_node
, fin_hand_name
);
3061 /* 3. Now add in fields for function params (if there are any) that are used
3062 within the function body. This is conservative; we can't tell at this
3063 stage if such uses might be optimized away, or if they might turn out not
3064 to persist across any suspend points. Of course, even if they don't
3065 persist across suspend points, when the actor is out of line the saved
3066 frame version is still needed. */
3067 hash_map
<tree
, param_info
> *param_uses
= NULL
;
3068 if (DECL_ARGUMENTS (orig
))
3070 /* Build a hash map with an entry for each param.
3071 The key is the param tree.
3072 Then we have an entry for the frame field name.
3073 Then a cache for the field ref when we come to use it.
3074 Then a tree list of the uses.
3075 The second two entries start out empty - and only get populated
3076 when we see uses. */
3077 param_uses
= new hash_map
<tree
, param_info
>;
3079 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3080 arg
= DECL_CHAIN (arg
))
3083 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3084 gcc_checking_assert (!existed
);
3085 parm
.field_id
= NULL_TREE
;
3086 parm
.body_uses
= NULL
;
3089 param_frame_data param_data
3090 = {&field_list
, param_uses
, fn_start
, false};
3091 /* We want to record every instance of param's use, so don't include
3092 a 'visited' hash_set. */
3093 cp_walk_tree (&fnbody
, register_param_uses
, ¶m_data
, NULL
);
3095 /* If no uses for any param were seen, act as if there were no
3096 params (it could be that they are only used to construct the
3098 if (!param_data
.param_seen
)
3105 /* 4. Now make space for local vars, this is conservative again, and we
3106 would expect to delete unused entries later. */
3107 hash_map
<tree
, local_var_info
> local_var_uses
;
3108 auto_vec
<local_var_info
> captures
;
3110 local_vars_frame_data local_vars_data
3111 = {&field_list
, &local_var_uses
, &captures
, 0, 0, fn_start
, false, false};
3112 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
3114 /* Tie off the struct for now, so that we can build offsets to the
3116 TYPE_FIELDS (coro_frame_type
) = field_list
;
3117 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
3118 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
3119 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
3121 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
3124 /* Now build the ramp function pieces. */
3125 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3126 add_stmt (ramp_bind
);
3127 tree ramp_body
= push_stmt_list ();
3128 tree empty_list
= build_empty_stmt (fn_start
);
3130 tree coro_fp
= build_lang_decl (VAR_DECL
, get_identifier ("coro.frameptr"),
3132 tree varlist
= coro_fp
;
3133 local_var_info
*cap
;
3134 if (!captures
.is_empty())
3135 for (int ix
= 0; captures
.iterate (ix
, &cap
); ix
++)
3137 if (cap
->field_id
== NULL_TREE
)
3139 tree t
= cap
->captured
;
3140 DECL_CHAIN (t
) = varlist
;
3144 /* Collected the scope vars we need ... only one for now. */
3145 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
3147 /* We're now going to create a new top level scope block for the ramp
3149 tree top_block
= make_node (BLOCK
);
3151 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
3152 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
3153 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
3155 /* The decl_expr for the coro frame pointer, initialize to zero so that we
3156 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
3157 directly apparently). This avoids a "used uninitialized" warning. */
3158 tree r
= build_stmt (fn_start
, DECL_EXPR
, coro_fp
);
3159 tree zeroinit
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3160 r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, zeroinit
);
3161 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3164 /* We are going to copy the behavior of clang w.r.t to failed allocation
3165 of the coroutine frame.
3166 1. If the promise has a 'get_return_object_on_allocation_failure()'
3167 method, then we use a nothrow new and check the return value, calling
3168 the method on failure to initialize an early return.
3169 2. Otherwise, we call new and the ramp is expected to terminate with an
3170 unhandled exception in the case of failure to allocate.
3172 The get_return_object_on_allocation_failure() must be a static method.
3175 = lookup_promise_method (orig
, coro_gro_on_allocation_fail_identifier
,
3176 fn_start
, /*musthave=*/ false);
3178 /* The CO_FRAME internal function is a mechanism to allow the middle end
3179 to adjust the allocation in response to optimisations. We provide the
3180 current conservative estimate of the frame size (as per the current)
3183 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
3184 TYPE_SIZE_UNIT (coro_frame_type
), coro_fp
);
3186 /* We need to adjust the operator new call as per the description above when
3187 there is a return on allocation fail function provided in the promise. */
3188 tree grooaf
= NULL_TREE
;
3189 vec
<tree
, va_gc
> *arglist
;
3190 vec_alloc (arglist
, 2);
3191 arglist
->quick_push (resizeable
);
3192 if (grooaf_meth
&& BASELINK_P (grooaf_meth
))
3194 tree fn
= BASELINK_FUNCTIONS (grooaf_meth
);
3195 if (TREE_CODE (fn
) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (fn
))
3197 grooaf
= build_call_expr_loc (fn_start
, fn
, 0);
3200 tree nth_ns
= lookup_qualified_name (std_node
, get_identifier ("nothrow"),
3201 0, /*complain=*/ true, false);
3202 arglist
->quick_push (nth_ns
);
3205 /* Allocate the frame. */
3207 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
3208 /* The user can (optionally) provide an allocation function in the promise
3209 type, it's not a failure for it to be absent. */
3210 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
3211 /*musthave=*/ false);
3212 tree new_fn
= NULL_TREE
;
3213 if (fns
&& fns
!= error_mark_node
)
3215 new_fn
= lookup_arg_dependent (nwname
, fns
, arglist
);
3217 new_fn
= OVL_FIRST (new_fn
);
3219 new_fn
= BASELINK_FUNCTIONS (new_fn
);
3221 gcc_checking_assert (DECL_STATIC_FUNCTION_P (new_fn
));
3222 TREE_USED (new_fn
) = 1;
3223 new_fn
= build_call_expr_loc_vec (fn_start
, new_fn
, arglist
);
3226 /* If that fails, then fall back to the global operator new. */
3227 if (new_fn
== NULL_TREE
|| new_fn
== error_mark_node
)
3229 fns
=lookup_name_real (nwname
, 0, 1, /*block_p=*/true, 0, 0);
3230 new_fn
= lookup_arg_dependent (nwname
, fns
, arglist
);
3231 new_fn
= build_new_function_call (new_fn
, &arglist
, /*complain=*/ true);
3234 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
3235 r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, allocated
);
3236 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3239 /* If the user provided a method to return an object on alloc fail, then
3240 check the returned pointer and call the func if it's null.
3241 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
3246 = create_named_label_with_ctx (fn_start
, "coro.frame.active",
3248 tree early_ret_list
= NULL
;
3249 /* init the retval using the user's func. */
3250 r
= build2 (INIT_EXPR
, TREE_TYPE (DECL_RESULT (orig
)), DECL_RESULT (orig
),
3252 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3253 append_to_statement_list (r
, &early_ret_list
);
3254 // We know it's the correct type.
3255 r
= DECL_RESULT (orig
);
3256 r
= build_stmt (fn_start
, RETURN_EXPR
, r
);
3257 TREE_NO_WARNING (r
) |= 1;
3258 r
= maybe_cleanup_point_expr_void (r
);
3259 append_to_statement_list (r
, &early_ret_list
);
3261 tree goto_st
= NULL
;
3262 r
= build1 (GOTO_EXPR
, void_type_node
, cfra_label
);
3263 append_to_statement_list (r
, &goto_st
);
3265 tree ckk
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3266 tree ckz
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, ckk
);
3267 r
= build3 (COND_EXPR
, void_type_node
, ckz
, early_ret_list
, empty_list
);
3270 cfra_label
= build_stmt (fn_start
, LABEL_EXPR
, cfra_label
);
3271 add_stmt (cfra_label
);
3274 /* deref the frame pointer, to use in member access code. */
3275 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
3277 /* For now, we always assume that this needs destruction, there's no impl.
3278 for frame allocation elision. */
3280 = lookup_member (coro_frame_type
, fnf_name
, 1, 0, tf_warning_or_error
);
3281 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
3282 false, tf_warning_or_error
);
3283 r
= build2 (INIT_EXPR
, boolean_type_node
, fnf_x
, boolean_true_node
);
3284 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3287 /* Put the resumer and destroyer functions in. */
3289 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
3291 = lookup_member (coro_frame_type
, resume_name
,
3292 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
3293 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
3294 false, tf_warning_or_error
);
3295 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, resume_x
, actor_addr
);
3296 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3299 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
3301 = lookup_member (coro_frame_type
, destroy_name
,
3302 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
3304 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
3305 tf_warning_or_error
);
3306 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, destroy_x
, destroy_addr
);
3307 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3310 /* Set up the promise. */
3312 = lookup_member (coro_frame_type
, promise_name
,
3313 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
3315 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
3316 false, tf_warning_or_error
);
3318 if (TYPE_NEEDS_CONSTRUCTING (promise_type
))
3320 /* Do a placement new constructor for the promise type (we never call
3321 the new operator, just the constructor on the object in place in the
3324 First try to find a constructor with the same parameter list as the
3325 original function (if it has params), failing that find a constructor
3326 with no parameter list.
3329 if (DECL_ARGUMENTS (orig
))
3331 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3333 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
3334 vec_safe_push (args
, arg
);
3335 r
= build_special_member_call (p
, complete_ctor_identifier
, &args
,
3336 promise_type
, LOOKUP_NORMAL
, tf_none
);
3337 release_tree_vector (args
);
3342 if (r
== NULL_TREE
|| r
== error_mark_node
)
3343 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
3344 promise_type
, LOOKUP_NORMAL
,
3345 tf_warning_or_error
);
3347 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3351 /* Copy in any of the function params we found to be used.
3352 Param types with non-trivial dtors will have to be moved into position
3353 and the dtor run before the frame is freed. */
3354 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
3355 if (DECL_ARGUMENTS (orig
) && param_uses
!= NULL
)
3358 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
3361 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3362 if (parm
.field_id
== NULL_TREE
)
3363 continue; /* Wasn't used. */
3365 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
3366 /*protect*/ 1, /*want_type*/ 0,
3367 tf_warning_or_error
);
3369 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
3370 false, tf_warning_or_error
);
3372 if (TYPE_NEEDS_CONSTRUCTING (parm
.frame_type
))
3374 vec
<tree
, va_gc
> *p_in
;
3375 if (TYPE_REF_P (DECL_ARG_TYPE (arg
))
3376 && (CLASSTYPE_LAZY_MOVE_CTOR (parm
.frame_type
)
3377 || CLASSTYPE_LAZY_MOVE_ASSIGN (parm
.frame_type
)
3378 || classtype_has_move_assign_or_move_ctor_p
3379 (parm
.frame_type
, /* user-declared */ true)))
3380 p_in
= make_tree_vector_single (rvalue (arg
));
3382 p_in
= make_tree_vector_single (arg
);
3383 /* Construct in place or move as relevant. */
3384 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
3385 &p_in
, parm
.frame_type
,
3387 tf_warning_or_error
);
3388 release_tree_vector (p_in
);
3389 if (param_dtor_list
== NULL
)
3390 param_dtor_list
= make_tree_vector ();
3391 vec_safe_push (param_dtor_list
, parm
.field_id
);
3395 if (!same_type_p (parm
.frame_type
, DECL_ARG_TYPE (arg
)))
3396 r
= build1_loc (DECL_SOURCE_LOCATION (arg
), CONVERT_EXPR
,
3397 parm
.frame_type
, arg
);
3400 r
= build_modify_expr (fn_start
, fld_idx
, parm
.frame_type
,
3401 INIT_EXPR
, DECL_SOURCE_LOCATION (arg
), r
,
3404 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3409 vec
<tree
, va_gc
> *captures_dtor_list
= NULL
;
3410 while (!captures
.is_empty())
3412 local_var_info cap
= captures
.pop();
3413 if (cap
.field_id
== NULL_TREE
)
3416 tree fld_ref
= lookup_member (coro_frame_type
, cap
.field_id
,
3417 /*protect*/ 1, /*want_type*/ 0,
3418 tf_warning_or_error
);
3420 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
3421 false, tf_warning_or_error
);
3423 tree cap_type
= cap
.frame_type
;
3425 /* When we have a reference, we do not want to change the referenced
3426 item, but actually to set the reference to the proxy var. */
3427 if (REFERENCE_REF_P (fld_idx
))
3428 fld_idx
= TREE_OPERAND (fld_idx
, 0);
3430 if (TYPE_NEEDS_CONSTRUCTING (cap_type
))
3432 vec
<tree
, va_gc
> *p_in
;
3433 if (TYPE_REF_P (cap_type
)
3434 && (CLASSTYPE_LAZY_MOVE_CTOR (cap_type
)
3435 || CLASSTYPE_LAZY_MOVE_ASSIGN (cap_type
)
3436 || classtype_has_move_assign_or_move_ctor_p
3437 (cap_type
, /* user-declared */ true)))
3438 p_in
= make_tree_vector_single (rvalue (cap
.captured
));
3440 p_in
= make_tree_vector_single (cap
.captured
);
3441 /* Construct in place or move as relevant. */
3442 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
3443 &p_in
, cap_type
, LOOKUP_NORMAL
,
3444 tf_warning_or_error
);
3445 release_tree_vector (p_in
);
3446 if (captures_dtor_list
== NULL
)
3447 captures_dtor_list
= make_tree_vector ();
3448 vec_safe_push (captures_dtor_list
, cap
.field_id
);
3452 if (!same_type_p (cap_type
, TREE_TYPE (cap
.captured
)))
3453 r
= build1_loc (DECL_SOURCE_LOCATION (cap
.captured
), CONVERT_EXPR
,
3454 cap_type
, cap
.captured
);
3457 r
= build_modify_expr (fn_start
, fld_idx
, cap_type
,
3458 INIT_EXPR
, DECL_SOURCE_LOCATION (cap
.captured
),
3461 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3465 /* Set up a new bind context for the GRO. */
3466 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3467 /* Make and connect the scope blocks. */
3468 tree gro_block
= make_node (BLOCK
);
3469 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
3470 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
3471 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
3472 add_stmt (gro_context_bind
);
3474 tree gro_meth
= lookup_promise_method (orig
,
3475 coro_get_return_object_identifier
,
3476 fn_start
, /*musthave=*/ true );
3478 = build_new_method_call (p
, gro_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
3479 tf_warning_or_error
);
3480 /* Without a return object we haven't got much clue what's going on. */
3481 if (get_ro
== error_mark_node
)
3483 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
3484 DECL_SAVED_TREE (orig
) = newbody
;
3488 tree gro_context_body
= push_stmt_list ();
3489 tree gro
, gro_bind_vars
;
3490 if (same_type_p (TREE_TYPE (get_ro
), fn_return_type
))
3492 gro
= DECL_RESULT (orig
);
3493 gro_bind_vars
= NULL_TREE
; // We don't need a separate var.
3497 gro
= build_lang_decl (VAR_DECL
, get_identifier ("coro.gro"),
3498 TREE_TYPE (TREE_OPERAND (get_ro
, 0)));
3499 DECL_CONTEXT (gro
) = current_scope ();
3500 r
= build_stmt (fn_start
, DECL_EXPR
, gro
);
3502 gro_bind_vars
= gro
; // We need a temporary var.
3505 // init our actual var.
3506 r
= build2_loc (fn_start
, INIT_EXPR
, TREE_TYPE (gro
), gro
, get_ro
);
3507 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3510 /* Initialize the resume_idx_name to 0, meaning "not started". */
3512 = lookup_member (coro_frame_type
, resume_idx_name
,
3513 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error
);
3515 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
3516 tf_warning_or_error
);
3517 r
= build_int_cst (short_unsigned_type_node
, 0);
3518 r
= build2_loc (fn_start
, INIT_EXPR
, short_unsigned_type_node
, resume_idx
, r
);
3519 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3522 /* So .. call the actor .. */
3523 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
3524 r
= maybe_cleanup_point_expr_void (r
);
3527 /* Switch to using 'input_location' as the loc, since we're now more
3528 logically doing things related to the end of the function. */
3529 /* done, we just need the return value. */
3531 if (same_type_p (TREE_TYPE (gro
), fn_return_type
))
3533 /* Already got the result. */
3534 r
= check_return_expr (DECL_RESULT (orig
), &no_warning
);
3538 // construct the return value with a single GRO param.
3539 vec
<tree
, va_gc
> *args
= make_tree_vector_single (gro
);
3540 r
= build_special_member_call (DECL_RESULT (orig
),
3541 complete_ctor_identifier
, &args
,
3542 fn_return_type
, LOOKUP_NORMAL
,
3543 tf_warning_or_error
);
3544 r
= coro_build_cvt_void_expr_stmt (r
, input_location
);
3546 release_tree_vector (args
);
3549 r
= build_stmt (input_location
, RETURN_EXPR
, DECL_RESULT (orig
));
3550 TREE_NO_WARNING (r
) |= no_warning
;
3551 r
= maybe_cleanup_point_expr_void (r
);
3553 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
3554 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
3555 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
3557 /* We know the "real" promise and have a frame layout with a slot for each
3558 suspend point, so we can build an actor function (which contains the
3559 functionality for both 'resume' and 'destroy').
3561 wrap the function body in a try {} catch (...) {} block, if exceptions
3564 /* First make a new block for the body - that will be embedded in the
3565 re-written function. */
3566 tree first
= expr_first (fnbody
);
3567 bool orig_fn_has_outer_bind
= false;
3568 tree replace_blk
= NULL_TREE
;
3569 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
3571 orig_fn_has_outer_bind
= true;
3572 tree block
= BIND_EXPR_BLOCK (first
);
3573 replace_blk
= make_node (BLOCK
);
3574 if (block
) // missing block is probably an error.
3576 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
3577 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
3578 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
3579 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
3580 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
3581 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
3583 BIND_EXPR_BLOCK (first
) = replace_blk
;
3586 if (flag_exceptions
)
3589 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
3590 fn_start
, /*musthave=*/ true);
3591 /* Build promise.unhandled_exception(); */
3593 = build_new_method_call (p
, ueh_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
3594 NULL
, tf_warning_or_error
);
3596 /* The try block is just the original function, there's no real
3597 need to call any function to do this. */
3598 tree tcb
= build_stmt (fn_start
, TRY_BLOCK
, NULL_TREE
, NULL_TREE
);
3599 TRY_STMTS (tcb
) = fnbody
;
3600 TRY_HANDLERS (tcb
) = push_stmt_list ();
3601 /* Mimic what the parser does for the catch. */
3602 tree handler
= begin_handler ();
3603 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
3604 ueh
= maybe_cleanup_point_expr_void (ueh
);
3606 finish_handler (handler
);
3607 TRY_HANDLERS (tcb
) = pop_stmt_list (TRY_HANDLERS (tcb
));
3608 /* If the function starts with a BIND_EXPR, then we need to create
3609 one here to contain the try-catch and to link up the scopes. */
3610 if (orig_fn_has_outer_bind
)
3612 tree tcb_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3613 /* Make and connect the scope blocks. */
3614 tree tcb_block
= make_node (BLOCK
);
3615 /* .. and connect it here. */
3616 BLOCK_SUPERCONTEXT (replace_blk
) = tcb_block
;
3617 BLOCK_SUBBLOCKS (tcb_block
) = replace_blk
;
3618 BIND_EXPR_BLOCK (tcb_bind
) = tcb_block
;
3619 BIND_EXPR_BODY (tcb_bind
) = tcb
;
3627 /* We still try to look for the promise method and warn if it's not
3630 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
3631 fn_start
, /*musthave=*/ false);
3632 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
3633 warning_at (fn_start
, 0, "no member named %qE in %qT",
3634 coro_unhandled_exception_identifier
,
3635 get_coroutine_promise_type (orig
));
3637 /* Else we don't check and don't care if the method is missing. */
3639 /* Start to build the final functions.
3641 We push_deferring_access_checks to avoid these routines being seen as
3642 nested by the middle end; we are doing the outlining here. */
3644 push_deferring_access_checks (dk_no_check
);
3647 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
, param_uses
,
3648 &local_var_uses
, param_dtor_list
, initial_await
, final_await
,
3649 body_aw_points
.count
);
3652 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
3654 pop_deferring_access_checks ();
3656 DECL_SAVED_TREE (orig
) = newbody
;
3657 /* Link our new functions into the list. */
3658 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
3659 TREE_CHAIN (actor
) = destroy
;
3660 TREE_CHAIN (orig
) = actor
;
3663 *destroyer
= destroy
;
3665 delete suspend_points
;
3666 suspend_points
= NULL
;
3670 #include "gt-cp-coroutines.h"