1 /* coroutine-specific state, expansions and tests.
3 Copyright (C) 2018-2020 Free Software Foundation, Inc.
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
28 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
33 #include "gcc-rich-location.h"
36 static bool coro_promise_type_found_p (tree
, location_t
);
38 /* GCC C++ coroutines implementation.
40 The user authors a function that becomes a coroutine (lazily) by
41 making use of any of the co_await, co_yield or co_return keywords.
43 Unlike a regular function, where the activation record is placed on the
44 stack, and is destroyed on function exit, a coroutine has some state that
45 persists between calls - the coroutine frame (analogous to a stack frame).
47 We transform the user's function into three pieces:
48 1. A so-called ramp function, that establishes the coroutine frame and
49 begins execution of the coroutine.
50 2. An actor function that contains the state machine corresponding to the
51 user's suspend/resume structure.
52 3. A stub function that calls the actor function in 'destroy' mode.
54 The actor function is executed:
55 * from "resume point 0" by the ramp.
56 * from resume point N ( > 0 ) for handle.resume() calls.
57 * from the destroy stub for destroy point N for handle.destroy() calls.
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
62 The C++ coroutine design makes use of some helper functions that are
63 authored in a so-called "promise" class provided by the user.
65 At parse time (or post substitution) the type of the coroutine promise
66 will be determined. At that point, we can look up the required promise
67 class methods and issue diagnostics if they are missing or incorrect. To
68 avoid repeating these actions at code-gen time, we make use of temporary
69 'proxy' variables for the coroutine handle and the promise - which will
70 eventually be instantiated in the coroutine frame.
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
79 /* The state that we collect during parsing (and template expansion) for
82 struct GTY((for_user
)) coroutine_info
84 tree function_decl
; /* The original function decl. */
85 tree promise_type
; /* The cached promise type for this function. */
86 tree handle_type
; /* The cached coroutine handle for this function. */
87 tree self_h_proxy
; /* A handle instance that is used as the proxy for the
88 one that will eventually be allocated in the coroutine
90 tree promise_proxy
; /* Likewise, a proxy promise instance. */
91 location_t first_coro_keyword
; /* The location of the keyword that made this
92 function into a coroutine. */
93 /* Flags to avoid repeated errors for per-function issues. */
94 bool coro_ret_type_error_emitted
;
95 bool coro_promise_error_emitted
;
98 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
100 typedef tree compare_type
; /* We only compare the function decl. */
101 static inline hashval_t
hash (coroutine_info
*);
102 static inline hashval_t
hash (const compare_type
&);
103 static inline bool equal (coroutine_info
*, coroutine_info
*);
104 static inline bool equal (coroutine_info
*, const compare_type
&);
107 /* This table holds all the collected coroutine state for coroutines in
108 the current translation unit. */
110 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
112 /* We will initialise state lazily. */
113 static bool coro_initialized
= false;
115 /* Return a hash value for the entry pointed to by INFO.
116 The compare type is a tree, but the only trees we are going use are
117 function decls. We use the DECL_UID as the hash value since that is
118 stable across PCH. */
121 coroutine_info_hasher::hash (coroutine_info
*info
)
123 return DECL_UID (info
->function_decl
);
126 /* Return a hash value for the compare value COMP. */
129 coroutine_info_hasher::hash (const compare_type
& comp
)
131 return DECL_UID (comp
);
134 /* Return true if the entries pointed to by LHS and RHS are for the
138 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
140 return lhs
->function_decl
== rhs
->function_decl
;
144 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
146 return lhs
->function_decl
== rhs
;
149 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
150 entry does not yet exist. */
153 get_or_insert_coroutine_info (tree fn_decl
)
155 gcc_checking_assert (coroutine_info_table
!= NULL
);
157 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
158 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
162 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
163 (*slot
)->function_decl
= fn_decl
;
169 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
172 get_coroutine_info (tree fn_decl
)
174 if (coroutine_info_table
== NULL
)
177 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
178 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
184 /* We will lazily create all the identifiers that are used by coroutines
185 on the first attempt to lookup the traits. */
187 /* Identifiers that are used by all coroutines. */
189 static GTY(()) tree coro_traits_identifier
;
190 static GTY(()) tree coro_handle_identifier
;
191 static GTY(()) tree coro_promise_type_identifier
;
193 /* Required promise method name identifiers. */
195 static GTY(()) tree coro_await_transform_identifier
;
196 static GTY(()) tree coro_initial_suspend_identifier
;
197 static GTY(()) tree coro_final_suspend_identifier
;
198 static GTY(()) tree coro_return_void_identifier
;
199 static GTY(()) tree coro_return_value_identifier
;
200 static GTY(()) tree coro_yield_value_identifier
;
201 static GTY(()) tree coro_resume_identifier
;
202 static GTY(()) tree coro_address_identifier
;
203 static GTY(()) tree coro_from_address_identifier
;
204 static GTY(()) tree coro_get_return_object_identifier
;
205 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
206 static GTY(()) tree coro_unhandled_exception_identifier
;
208 /* Awaitable methods. */
210 static GTY(()) tree coro_await_ready_identifier
;
211 static GTY(()) tree coro_await_suspend_identifier
;
212 static GTY(()) tree coro_await_resume_identifier
;
214 /* Create the identifiers used by the coroutines library interfaces. */
217 coro_init_identifiers ()
219 coro_traits_identifier
= get_identifier ("coroutine_traits");
220 coro_handle_identifier
= get_identifier ("coroutine_handle");
221 coro_promise_type_identifier
= get_identifier ("promise_type");
223 coro_await_transform_identifier
= get_identifier ("await_transform");
224 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
225 coro_final_suspend_identifier
= get_identifier ("final_suspend");
226 coro_return_void_identifier
= get_identifier ("return_void");
227 coro_return_value_identifier
= get_identifier ("return_value");
228 coro_yield_value_identifier
= get_identifier ("yield_value");
229 coro_resume_identifier
= get_identifier ("resume");
230 coro_address_identifier
= get_identifier ("address");
231 coro_from_address_identifier
= get_identifier ("from_address");
232 coro_get_return_object_identifier
= get_identifier ("get_return_object");
233 coro_gro_on_allocation_fail_identifier
=
234 get_identifier ("get_return_object_on_allocation_failure");
235 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
237 coro_await_ready_identifier
= get_identifier ("await_ready");
238 coro_await_suspend_identifier
= get_identifier ("await_suspend");
239 coro_await_resume_identifier
= get_identifier ("await_resume");
242 /* Trees we only need to set up once. */
244 static GTY(()) tree coro_traits_templ
;
245 static GTY(()) tree coro_handle_templ
;
246 static GTY(()) tree void_coro_handle_type
;
248 /* ================= Parse, Semantics and Type checking ================= */
250 /* This initial set of routines are helper for the parsing and template
253 At the completion of this, we will have completed trees for each of the
254 keywords, but making use of proxy variables for the self-handle and the
255 promise class instance. */
257 /* [coroutine.traits]
258 Lookup the coroutine_traits template decl. */
261 find_coro_traits_template_decl (location_t kw
)
263 /* If we are missing fundmental information, such as the traits, (or the
264 declaration found is not a type template), then don't emit an error for
265 every keyword in a TU, just do it once. */
266 static bool traits_error_emitted
= false;
268 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
270 /*complain=*/!traits_error_emitted
);
271 if (traits_decl
== error_mark_node
272 || !DECL_TYPE_TEMPLATE_P (traits_decl
))
274 if (!traits_error_emitted
)
276 gcc_rich_location
richloc (kw
);
277 error_at (&richloc
, "coroutines require a traits template; cannot"
278 " find %<%E::%E%>", std_node
, coro_traits_identifier
);
279 inform (&richloc
, "perhaps %<#include <coroutine>%> is missing");
280 traits_error_emitted
= true;
288 /* Instantiate Coroutine traits for the function signature. */
291 instantiate_coro_traits (tree fndecl
, location_t kw
)
293 /* [coroutine.traits.primary]
294 So now build up a type list for the template <typename _R, typename...>.
295 The types are the function's arg types and _R is the function return
298 tree functyp
= TREE_TYPE (fndecl
);
299 tree arg_node
= TYPE_ARG_TYPES (functyp
);
300 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
303 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
305 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
306 arg_node
= TREE_CHAIN (arg_node
);
309 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
310 SET_ARGUMENT_PACK_ARGS (argtypepack
, argtypes
);
312 tree targ
= make_tree_vec (2);
313 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
314 TREE_VEC_ELT (targ
, 1) = argtypepack
;
317 = lookup_template_class (coro_traits_templ
, targ
,
318 /*in_decl=*/NULL_TREE
, /*context=*/NULL_TREE
,
319 /*entering scope=*/false, tf_warning_or_error
);
321 if (traits_class
== error_mark_node
)
323 error_at (kw
, "cannot instantiate %<coroutine traits%>");
330 /* [coroutine.handle] */
333 find_coro_handle_template_decl (location_t kw
)
335 /* As for the coroutine traits, this error is per TU, so only emit
337 static bool coro_handle_error_emitted
= false;
338 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
339 0, !coro_handle_error_emitted
);
340 if (handle_decl
== error_mark_node
341 || !DECL_CLASS_TEMPLATE_P (handle_decl
))
343 if (!coro_handle_error_emitted
)
344 error_at (kw
, "coroutines require a handle class template;"
345 " cannot find %<%E::%E%>", std_node
, coro_handle_identifier
);
346 coro_handle_error_emitted
= true;
353 /* Instantiate the handle template for a given promise type. */
356 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
358 /* So now build up a type list for the template, one entry, the promise. */
359 tree targ
= make_tree_vec (1);
360 TREE_VEC_ELT (targ
, 0) = promise_type
;
362 = lookup_template_class (coro_handle_identifier
, targ
,
363 /* in_decl=*/NULL_TREE
,
364 /* context=*/std_node
,
365 /* entering scope=*/false, tf_warning_or_error
);
367 if (handle_type
== error_mark_node
)
369 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
370 " promise type %qT", promise_type
);
377 /* Look for the promise_type in the instantiated traits. */
380 find_promise_type (tree traits_class
)
383 = lookup_member (traits_class
, coro_promise_type_identifier
,
384 /* protect=*/1, /*want_type=*/true, tf_warning_or_error
);
388 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
390 /* NULL_TREE on fail. */
395 coro_promise_type_found_p (tree fndecl
, location_t loc
)
397 gcc_assert (fndecl
!= NULL_TREE
);
399 if (!coro_initialized
)
401 /* Trees we only need to create once.
402 Set up the identifiers we will use. */
403 coro_init_identifiers ();
405 /* Coroutine traits template. */
406 coro_traits_templ
= find_coro_traits_template_decl (loc
);
407 if (coro_traits_templ
== NULL_TREE
)
410 /* coroutine_handle<> template. */
411 coro_handle_templ
= find_coro_handle_template_decl (loc
);
412 if (coro_handle_templ
== NULL_TREE
)
415 /* We can also instantiate the void coroutine_handle<> */
416 void_coro_handle_type
=
417 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
418 if (void_coro_handle_type
== NULL_TREE
)
421 /* A table to hold the state, per coroutine decl. */
422 gcc_checking_assert (coroutine_info_table
== NULL
);
423 coroutine_info_table
=
424 hash_table
<coroutine_info_hasher
>::create_ggc (11);
426 if (coroutine_info_table
== NULL
)
429 coro_initialized
= true;
432 /* Save the coroutine data on the side to avoid the overhead on every
433 function decl tree. */
435 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
436 /* Without this, we cannot really proceed. */
437 gcc_checking_assert (coro_info
);
439 /* If we don't already have a current promise type, try to look it up. */
440 if (coro_info
->promise_type
== NULL_TREE
)
442 /* Get the coroutine traits template class instance for the function
443 signature we have - coroutine_traits <R, ...> */
444 tree return_type
= TREE_TYPE (TREE_TYPE (fndecl
));
445 if (!CLASS_TYPE_P (return_type
))
447 /* It makes more sense to show the function header for this, even
448 though we will have encountered it when processing a keyword.
449 Only emit the error once, not for every keyword we encounter. */
450 if (!coro_info
->coro_ret_type_error_emitted
)
451 error_at (DECL_SOURCE_LOCATION (fndecl
), "coroutine return type"
452 " %qT is not a class", return_type
);
453 coro_info
->coro_ret_type_error_emitted
= true;
457 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
459 /* Find the promise type for that. */
460 coro_info
->promise_type
= find_promise_type (templ_class
);
462 /* If we don't find it, punt on the rest. */
463 if (coro_info
->promise_type
== NULL_TREE
)
465 if (!coro_info
->coro_promise_error_emitted
)
466 error_at (loc
, "unable to find the promise type for"
468 coro_info
->coro_promise_error_emitted
= true;
472 /* Try to find the handle type for the promise. */
474 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
475 if (handle_type
== NULL_TREE
)
478 /* Complete this, we're going to use it. */
479 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
481 /* Diagnostic would be emitted by complete_type_or_else. */
482 if (!coro_info
->handle_type
)
485 /* Build a proxy for a handle to "self" as the param to
486 await_suspend() calls. */
487 coro_info
->self_h_proxy
488 = build_lang_decl (VAR_DECL
, get_identifier ("self_h.proxy"),
489 coro_info
->handle_type
);
491 /* Build a proxy for the promise so that we can perform lookups. */
492 coro_info
->promise_proxy
493 = build_lang_decl (VAR_DECL
, get_identifier ("promise.proxy"),
494 coro_info
->promise_type
);
496 /* Note where we first saw a coroutine keyword. */
497 coro_info
->first_coro_keyword
= loc
;
503 /* These functions assumes that the caller has verified that the state for
504 the decl has been initialized, we try to minimize work here. */
507 get_coroutine_promise_type (tree decl
)
509 if (coroutine_info
*info
= get_coroutine_info (decl
))
510 return info
->promise_type
;
516 get_coroutine_handle_type (tree decl
)
518 if (coroutine_info
*info
= get_coroutine_info (decl
))
519 return info
->handle_type
;
525 get_coroutine_self_handle_proxy (tree decl
)
527 if (coroutine_info
*info
= get_coroutine_info (decl
))
528 return info
->self_h_proxy
;
534 get_coroutine_promise_proxy (tree decl
)
536 if (coroutine_info
*info
= get_coroutine_info (decl
))
537 return info
->promise_proxy
;
543 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
546 tree promise
= get_coroutine_promise_type (fndecl
);
548 = lookup_member (promise
, member_id
,
549 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
550 if (musthave
&& pm_memb
== NULL_TREE
)
552 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
553 return error_mark_node
;
558 /* Lookup an Awaitable member, which should be await_ready, await_suspend
562 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
565 = lookup_member (await_type
, member_id
,
566 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
567 if (aw_memb
== NULL_TREE
)
569 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
570 return error_mark_node
;
575 /* Here we check the constraints that are common to all keywords (since the
576 presence of a coroutine keyword makes the function into a coroutine). */
579 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
582 if (fndecl
== NULL_TREE
)
584 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
588 /* This is arranged in order of prohibitions in the std. */
589 if (DECL_MAIN_P (fndecl
))
591 /* [basic.start.main] 3. The function main shall not be a coroutine. */
592 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
597 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
599 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
600 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
602 cp_function_chain
->invalid_constexpr
= true;
606 if (FNDECL_USED_AUTO (fndecl
))
608 /* [dcl.spec.auto] 15. A function declared with a return type that uses
609 a placeholder type shall not be a coroutine. */
611 "%qs cannot be used in a function with a deduced return type",
616 if (varargs_function_p (fndecl
))
618 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
619 coroutine shall not terminate with an ellipsis that is not part
620 of a parameter-declaration. */
622 "%qs cannot be used in a varargs function", kw_name
);
626 if (DECL_CONSTRUCTOR_P (fndecl
))
628 /* [class.ctor] 7. a constructor shall not be a coroutine. */
629 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
633 if (DECL_DESTRUCTOR_P (fndecl
))
635 /* [class.dtor] 21. a destructor shall not be a coroutine. */
636 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
643 /* Here we check the constraints that are not per keyword. */
646 coro_function_valid_p (tree fndecl
)
648 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
650 /* For cases where fundamental information cannot be found, e.g. the
651 coroutine traits are missing, we need to punt early. */
652 if (!coro_promise_type_found_p (fndecl
, f_loc
))
655 /* Since we think the function is a coroutine, that implies we parsed
656 a keyword that triggered this. Keywords check promise validity for
657 their context and thus the promise type should be known at this point. */
658 if (get_coroutine_handle_type (fndecl
) == NULL_TREE
659 || get_coroutine_promise_type (fndecl
) == NULL_TREE
)
662 if (current_function_returns_value
|| current_function_returns_null
)
664 /* TODO: record or extract positions of returns (and the first coro
665 keyword) so that we can add notes to the diagnostic about where
666 the bad keyword is and what made the function into a coro. */
667 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
668 " did you mean %<co_return%>?");
675 enum suspend_point_kind
{
676 CO_AWAIT_SUSPEND_POINT
= 0,
677 CO_YIELD_SUSPEND_POINT
,
678 INITIAL_SUSPEND_POINT
,
682 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
683 It is also used to build the initial and final suspend points.
685 'a', 'o' and 'e' are used as per the description in the section noted.
687 A, the original yield/await expr, is found at source location LOC.
689 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
690 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
693 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
695 /* Try and overload of operator co_await, .... */
697 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
699 tree overload
= NULL_TREE
;
700 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
701 NULL_TREE
, &overload
, tf_warning_or_error
);
702 /* If no viable functions are found, o is a. */
703 if (!o
|| o
== error_mark_node
)
707 o
= a
; /* This is most likely about to fail anyway. */
709 tree o_type
= TREE_TYPE (o
);
710 if (o_type
&& !VOID_TYPE_P (o_type
))
711 o_type
= complete_type_or_else (o_type
, o
);
714 return error_mark_node
;
716 if (TREE_CODE (o_type
) != RECORD_TYPE
)
718 error_at (loc
, "awaitable type %qT is not a structure",
720 return error_mark_node
;
723 /* Check for required awaitable members and their types. */
725 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
726 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
727 return error_mark_node
;
729 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
730 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
731 return error_mark_node
;
733 /* The type of the co_await is the return type of the awaitable's
734 await_resume, so we need to look that up. */
736 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
737 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
738 return error_mark_node
;
740 /* To complete the lookups, we need an instance of 'e' which is built from
741 'o' according to [expr.await] 3.4. However, we don't want to materialize
742 'e' here (it might need to be placed in the coroutine frame) so we will
743 make a temp placeholder instead. If 'o' is a parameter or a local var,
744 then we do not need an additional var (parms and local vars are already
745 copied into the frame and will have lifetimes according to their original
747 tree e_proxy
= STRIP_NOPS (o
);
748 if (INDIRECT_REF_P (e_proxy
))
749 e_proxy
= TREE_OPERAND (e_proxy
, 0);
750 if (TREE_CODE (e_proxy
) == PARM_DECL
751 || (TREE_CODE (e_proxy
) == VAR_DECL
&& !DECL_ARTIFICIAL (e_proxy
)))
755 e_proxy
= build_lang_decl (VAR_DECL
, NULL_TREE
, o_type
);
756 DECL_ARTIFICIAL (e_proxy
) = true;
759 /* I suppose we could check that this is contextually convertible to bool. */
760 tree awrd_func
= NULL_TREE
;
762 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
763 &awrd_func
, tf_warning_or_error
);
765 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
766 return error_mark_node
;
768 /* The suspend method may return one of three types:
769 1. void (no special action needed).
770 2. bool (if true, we don't need to suspend).
771 3. a coroutine handle, we execute the handle.resume() call. */
772 tree awsp_func
= NULL_TREE
;
773 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
774 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
776 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
777 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
779 release_tree_vector (args
);
780 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
781 return error_mark_node
;
784 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
785 if (same_type_p (susp_return_type
, void_type_node
))
787 else if (same_type_p (susp_return_type
, boolean_type_node
))
789 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
790 && CLASS_TYPE_P (susp_return_type
))
792 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
793 if (tt
== coro_handle_templ
)
799 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
800 " a coroutine handle");
801 return error_mark_node
;
804 /* Finally, the type of e.await_resume() is the co_await's type. */
805 tree awrs_func
= NULL_TREE
;
807 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
808 &awrs_func
, tf_warning_or_error
);
810 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
811 return error_mark_node
;
813 /* We now have three call expressions, in terms of the promise, handle and
814 'e' proxies. Save them in the await expression for later expansion. */
816 tree awaiter_calls
= make_tree_vec (3);
817 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
818 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
819 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
821 tree await_expr
= build5_loc (loc
, CO_AWAIT_EXPR
,
822 TREE_TYPE (TREE_TYPE (awrs_func
)),
823 a
, e_proxy
, o
, awaiter_calls
,
824 build_int_cst (integer_type_node
,
825 (int) suspend_kind
));
826 return convert_from_reference (await_expr
);
830 finish_co_await_expr (location_t kw
, tree expr
)
832 if (!expr
|| error_operand_p (expr
))
833 return error_mark_node
;
835 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
837 return error_mark_node
;
839 /* The current function has now become a coroutine, if it wasn't already. */
840 DECL_COROUTINE_P (current_function_decl
) = 1;
842 if (processing_template_decl
)
844 current_function_returns_value
= 1;
846 if (check_for_bare_parameter_packs (expr
))
847 return error_mark_node
;
849 /* If we don't know the promise type, we can't proceed. */
850 tree functype
= TREE_TYPE (current_function_decl
);
851 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
852 return build5_loc (kw
, CO_AWAIT_EXPR
, unknown_type_node
, expr
,
853 NULL_TREE
, NULL_TREE
, NULL_TREE
, integer_zero_node
);
856 /* We must be able to look up the "await_transform" method in the scope of
857 the promise type, and obtain its return type. */
858 if (!coro_promise_type_found_p (current_function_decl
, kw
))
859 return error_mark_node
;
862 The incoming cast expression might be transformed by a promise
863 'await_transform()'. */
865 = lookup_promise_method (current_function_decl
,
866 coro_await_transform_identifier
, kw
,
868 if (at_meth
== error_mark_node
)
869 return error_mark_node
;
874 /* try to build a = p.await_transform (e). */
875 tree at_fn
= NULL_TREE
;
876 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
877 a
= build_new_method_call (get_coroutine_promise_proxy (
878 current_function_decl
),
879 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
880 &at_fn
, tf_warning_or_error
);
882 /* As I read the section.
883 We saw an await_transform method, so it's mandatory that we replace
884 expr with p.await_transform (expr), therefore if the method call fails
885 (presumably, we don't have suitable arguments) then this part of the
887 if (!at_fn
|| a
== error_mark_node
)
888 return error_mark_node
;
891 /* Now we want to build co_await a. */
892 tree op
= build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
893 if (op
!= error_mark_node
)
895 TREE_SIDE_EFFECTS (op
) = 1;
896 SET_EXPR_LOCATION (op
, kw
);
902 /* Take the EXPR given and attempt to build:
903 co_await p.yield_value (expr);
904 per [expr.yield] para 1. */
907 finish_co_yield_expr (location_t kw
, tree expr
)
909 if (!expr
|| error_operand_p (expr
))
910 return error_mark_node
;
912 /* Check the general requirements and simple syntax errors. */
913 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
915 return error_mark_node
;
917 /* The current function has now become a coroutine, if it wasn't already. */
918 DECL_COROUTINE_P (current_function_decl
) = 1;
920 if (processing_template_decl
)
922 current_function_returns_value
= 1;
924 if (check_for_bare_parameter_packs (expr
))
925 return error_mark_node
;
927 tree functype
= TREE_TYPE (current_function_decl
);
928 /* If we don't know the promise type, we can't proceed. */
929 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
930 return build2_loc (kw
, CO_YIELD_EXPR
, unknown_type_node
, expr
,
934 if (!coro_promise_type_found_p (current_function_decl
, kw
))
935 /* We must be able to look up the "yield_value" method in the scope of
936 the promise type, and obtain its return type. */
937 return error_mark_node
;
939 /* The incoming expr is "e" per [expr.yield] para 1, lookup and build a
940 call for p.yield_value(e). */
941 tree y_meth
= lookup_promise_method (current_function_decl
,
942 coro_yield_value_identifier
, kw
,
944 if (!y_meth
|| y_meth
== error_mark_node
)
945 return error_mark_node
;
947 tree yield_fn
= NULL_TREE
;
948 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
949 tree yield_call
= build_new_method_call (
950 get_coroutine_promise_proxy (current_function_decl
), y_meth
, &args
,
951 NULL_TREE
, LOOKUP_NORMAL
, &yield_fn
, tf_warning_or_error
);
953 if (!yield_fn
|| yield_call
== error_mark_node
)
954 return error_mark_node
;
956 /* So now we have the type of p.yield_value (e).
957 Now we want to build co_await p.yield_value (e).
958 Noting that for co_yield, there is no evaluation of any potential
959 promise transform_await(). */
961 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
962 if (op
!= error_mark_node
)
964 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
965 TREE_SIDE_EFFECTS (op
) = 1;
971 /* Check that it's valid to have a co_return keyword here.
972 If it is, then check and build the p.return_{void(),value(expr)}.
973 These are built against the promise proxy, but saved for expand time. */
976 finish_co_return_stmt (location_t kw
, tree expr
)
978 if (expr
== error_mark_node
)
979 return error_mark_node
;
981 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
983 return error_mark_node
;
985 /* The current function has now become a coroutine, if it wasn't
987 DECL_COROUTINE_P (current_function_decl
) = 1;
989 if (processing_template_decl
)
991 current_function_returns_value
= 1;
993 if (check_for_bare_parameter_packs (expr
))
994 return error_mark_node
;
996 tree functype
= TREE_TYPE (current_function_decl
);
997 /* If we don't know the promise type, we can't proceed, return the
998 expression as it is. */
999 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1002 = build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, NULL_TREE
);
1003 expr
= maybe_cleanup_point_expr_void (expr
);
1004 expr
= add_stmt (expr
);
1009 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1010 return error_mark_node
;
1012 if (error_operand_p (expr
))
1013 return error_mark_node
;
1015 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1016 whether the promise type has a suitable return_void/return_value. */
1017 TREE_NO_WARNING (current_function_decl
) = true;
1019 if (!processing_template_decl
&& warn_sequence_point
)
1020 verify_sequence_points (expr
);
1022 /* If the promise object doesn't have the correct return call then
1023 there's a mis-match between the co_return <expr> and this. */
1024 tree co_ret_call
= NULL_TREE
;
1025 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
1028 = lookup_promise_method (current_function_decl
,
1029 coro_return_void_identifier
, kw
,
1031 if (!crv_meth
|| crv_meth
== error_mark_node
)
1032 return error_mark_node
;
1034 co_ret_call
= build_new_method_call (
1035 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, NULL
,
1036 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1041 = lookup_promise_method (current_function_decl
,
1042 coro_return_value_identifier
, kw
,
1044 if (!crv_meth
|| crv_meth
== error_mark_node
)
1045 return error_mark_node
;
1047 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1048 co_ret_call
= build_new_method_call (
1049 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, &args
,
1050 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1053 /* Makes no sense for a co-routine really. */
1054 if (TREE_THIS_VOLATILE (current_function_decl
))
1056 "function declared %<noreturn%> has a"
1057 " %<co_return%> statement");
1059 if (!co_ret_call
|| co_ret_call
== error_mark_node
)
1060 return error_mark_node
;
1062 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
1063 expr
= maybe_cleanup_point_expr_void (expr
);
1064 expr
= add_stmt (expr
);
1068 /* We need to validate the arguments to __builtin_coro_promise, since the
1069 second two must be constant, and the builtins machinery doesn't seem to
1070 deal with that properly. */
1073 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
1075 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1077 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1078 switch (DECL_FUNCTION_CODE (fn
))
1083 case BUILT_IN_CORO_PROMISE
:
1085 /* Argument 0 is already checked by the normal built-in machinery
1086 Argument 1 must be a constant of size type. It probably makes
1087 little sense if it's not a power of 2, but that isn't specified
1089 tree arg
= CALL_EXPR_ARG (call
, 1);
1090 location_t loc
= EXPR_LOCATION (arg
);
1092 /* We expect alignof expressions in templates. */
1093 if (TREE_CODE (arg
) == NON_DEPENDENT_EXPR
1094 && TREE_CODE (TREE_OPERAND (arg
, 0)) == ALIGNOF_EXPR
)
1096 else if (!TREE_CONSTANT (arg
))
1098 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1099 " must be a constant");
1100 return error_mark_node
;
1102 /* Argument 2 is the direction - to / from handle address to promise
1104 arg
= CALL_EXPR_ARG (call
, 2);
1105 loc
= EXPR_LOCATION (arg
);
1106 if (!TREE_CONSTANT (arg
))
1108 error_at (loc
, "the direction argument to"
1109 " %<__builtin_coro_promise%> must be a constant");
1110 return error_mark_node
;
1118 /* ================= Morph and Expand. =================
1120 The entry point here is morph_fn_to_coro () which is called from
1121 finish_function () when we have completed any template expansion.
1123 This is preceded by helper functions that implement the phases below.
1125 The process proceeds in four phases.
1128 The user's function body is wrapped in the initial and final suspend
1129 points and we begin building the coroutine frame.
1130 We build empty decls for the actor and destroyer functions at this
1132 When exceptions are enabled, the user's function body will also be
1133 wrapped in a try-catch block with the catch invoking the promise
1134 class 'unhandled_exception' method.
1137 The user's function body is analyzed to determine the suspend points,
1138 if any, and to capture local variables that might persist across such
1139 suspensions. In most cases, it is not necessary to capture compiler
1140 temporaries, since the tree-lowering nests the suspensions correctly.
1141 However, in the case of a captured reference, there is a lifetime
1142 extension to the end of the full expression - which can mean across a
1143 suspend point in which case it must be promoted to a frame variable.
1145 At the conclusion of analysis, we have a conservative frame layout and
1146 maps of the local variables to their frame entry points.
1148 C Build the ramp function.
1149 Carry out the allocation for the coroutine frame (NOTE; the actual size
1150 computation is deferred until late in the middle end to allow for future
1151 optimizations that will be allowed to elide unused frame entries).
1152 We build the return object.
1154 D Build and expand the actor and destroyer function bodies.
1155 The destroyer is a trivial shim that sets a bit to indicate that the
1156 destroy dispatcher should be used and then calls into the actor.
1158 The actor function is the implementation of the user's state machine.
1159 The current suspend point is noted in an index.
1160 Each suspend point is encoded as a pair of internal functions, one in
1161 the relevant dispatcher, and one representing the suspend point.
1163 During this process, the user's local variables and the proxies for the
1164 self-handle and the promise class instance are re-written to their
1165 coroutine frame equivalents.
1167 The complete bodies for the ramp, actor and destroy function are passed
1168 back to finish_function for folding and gimplification. */
1170 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1173 coro_build_expr_stmt (tree expr
, location_t loc
)
1175 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1179 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1181 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1182 return coro_build_expr_stmt (t
, loc
);
1185 /* Helpers for label creation:
1186 1. Create a named label in the specified context. */
1189 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1191 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1193 DECL_CONTEXT (lab
) = ctx
;
1194 DECL_ARTIFICIAL (lab
) = true;
1195 DECL_IGNORED_P (lab
) = true;
1196 TREE_USED (lab
) = true;
1200 /* 2. Create a named label in the specified context. */
1203 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1205 tree lab_id
= get_identifier (name
);
1206 tree lab
= define_label (loc
, lab_id
);
1207 DECL_CONTEXT (lab
) = ctx
;
1208 DECL_ARTIFICIAL (lab
) = true;
1209 TREE_USED (lab
) = true;
1213 struct proxy_replace
1219 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1221 proxy_replace
*data
= (proxy_replace
*) d
;
1223 if (*here
== data
->from
)
1233 /* Support for expansion of co_return statements. */
1235 struct coro_ret_data
1242 /* If this is a coreturn statement (or one wrapped in a cleanup) then
1243 return the list of statements to replace it. */
1246 coro_maybe_expand_co_return (tree co_ret_expr
, coro_ret_data
*data
)
1248 /* Look inside <(void) (expr)> cleanup */
1249 if (TREE_CODE (co_ret_expr
) == CLEANUP_POINT_EXPR
)
1250 co_ret_expr
= TREE_OPERAND (co_ret_expr
, 0);
1252 if (TREE_CODE (co_ret_expr
) != CO_RETURN_EXPR
)
1255 location_t loc
= EXPR_LOCATION (co_ret_expr
);
1256 tree expr
= TREE_OPERAND (co_ret_expr
, 0);
1257 tree call
= TREE_OPERAND (co_ret_expr
, 1);
1258 tree stmt_list
= NULL
;
1259 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
1261 /* [stmt.return.coroutine], 2.2
1262 If expr is present and void, it is placed immediately before
1263 the call for return_void; */
1264 expr
= maybe_cleanup_point_expr_void (expr
);
1265 append_to_statement_list (expr
, &stmt_list
);
1268 /* Now replace the promise proxy with its real value. */
1269 proxy_replace p_data
;
1270 p_data
.from
= data
->promise_proxy
;
1271 p_data
.to
= data
->real_promise
;
1272 cp_walk_tree (&call
, replace_proxy
, &p_data
, NULL
);
1274 /* The types of p.return_void and p.return_value are not explicitly stated
1275 at least in n4835, it is expected that they will return void. */
1276 call
= maybe_cleanup_point_expr_void (call
);
1277 append_to_statement_list (call
, &stmt_list
);
1278 tree r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->fs_label
);
1279 append_to_statement_list (r
, &stmt_list
);
1283 /* Callback that rewrites co_return as per [stmt.return.coroutine]
1285 { p.return_void (); goto final_suspend; }
1286 - for co_return [void expr];
1287 { expr; p.return_void(); goto final_suspend;}
1288 - for co_return [non void expr];
1289 { p.return_value(expr); goto final_suspend; } */
1292 co_return_expander (tree
*stmt
, int *do_subtree
, void *d
)
1294 coro_ret_data
*data
= (coro_ret_data
*) d
;
1296 /* To avoid nesting statement lists, walk them and insert as needed. */
1297 if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1299 tree_stmt_iterator i
;
1300 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1302 tree
*new_stmt
= tsi_stmt_ptr (i
);
1303 tree replace
= coro_maybe_expand_co_return (*new_stmt
, data
);
1304 /* If we got something, it will be list and we want to splice
1306 if (replace
!= NULL_TREE
)
1308 /* Splice it in ... */
1309 tsi_link_before (&i
, replace
, TSI_SAME_STMT
);
1310 /* ... and delete what we expanded. */
1312 /* Maybe, even likely, we replaced the last in the list. */
1316 else /* Continue the walk. */
1317 cp_walk_tree (new_stmt
, co_return_expander
, d
, NULL
);
1319 *do_subtree
= 0; /* Done subtrees. */
1323 /* We might have a single co_return statement, in which case, we do
1324 have to replace it with a list. */
1325 tree replace
= coro_maybe_expand_co_return (*stmt
, data
);
1326 if (replace
!= NULL_TREE
)
1329 *do_subtree
= 0; /* Done here. */
1335 /* Walk the original function body, rewriting co_returns. */
1338 expand_co_returns (tree
*fnbody
, tree promise_proxy
, tree promise
,
1341 coro_ret_data data
= {promise_proxy
, promise
, fs_label
};
1342 cp_walk_tree (fnbody
, co_return_expander
, &data
, NULL
);
1346 /* Support for expansion of co_await statements. */
1350 tree actor_fn
; /* Decl for context. */
1351 tree coro_fp
; /* Frame pointer var. */
1352 tree resume_idx
; /* This is the index var in the frame. */
1353 tree i_a_r_c
; /* initial suspend await_resume() was called if true. */
1354 tree self_h
; /* This is a handle to the current coro (frame var). */
1355 tree cleanup
; /* This is where to go once we complete local destroy. */
1356 tree cororet
; /* This is where to go if we suspend. */
1357 tree corocont
; /* This is where to go if we continue. */
1358 tree conthand
; /* This is the handle for a continuation. */
1359 unsigned index
; /* This is our current resume index. */
1362 /* Lighweight search for the first await expression in tree-walk order.
1364 The first await expression found in STMT.
1365 NULL_TREE if there are none.
1366 So can be used to determine if the statement needs to be processed for
1370 co_await_find_in_subtree (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
1372 tree
**p
= (tree
**) d
;
1373 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1381 /* Starting with a statment:
1383 stmt => some tree containing one or more await expressions.
1385 We replace the statement with:
1387 initialise awaitable
1393 revised statement with one await expression rewritten to its
1394 await_resume() return value.
1397 We then recurse into the initializer and the revised statement
1398 repeating this replacement until there are no more await expressions
1402 expand_one_await_expression (tree
*stmt
, tree
*await_expr
, void *d
)
1404 coro_aw_data
*data
= (coro_aw_data
*) d
;
1406 tree saved_statement
= *stmt
;
1407 tree saved_co_await
= *await_expr
;
1409 tree actor
= data
->actor_fn
;
1410 location_t loc
= EXPR_LOCATION (*stmt
);
1411 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1412 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1413 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1415 tree source
= TREE_OPERAND (saved_co_await
, 4);
1417 (source
&& TREE_INT_CST_LOW (source
) == (int) INITIAL_SUSPEND_POINT
);
1418 bool is_final
= (source
1419 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1420 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1421 int resume_point
= data
->index
;
1422 size_t bufsize
= sizeof ("destroy.") + 10;
1423 char *buf
= (char *) alloca (bufsize
);
1424 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1425 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1426 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1427 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1428 tree empty_list
= build_empty_stmt (loc
);
1430 tree dtor
= NULL_TREE
;
1431 tree await_type
= TREE_TYPE (var
);
1433 dtor
= build_special_member_call (var
, complete_dtor_identifier
, NULL
,
1434 await_type
, LOOKUP_NORMAL
,
1435 tf_warning_or_error
);
1437 tree stmt_list
= NULL
;
1438 tree t_expr
= STRIP_NOPS (expr
);
1440 tree
*await_init
= NULL
;
1445 /* Initialize the var from the provided 'o' expression. */
1446 r
= build2 (INIT_EXPR
, await_type
, var
, expr
);
1447 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1448 append_to_statement_list_force (r
, &stmt_list
);
1449 /* We have an initializer, which might itself contain await exprs. */
1450 await_init
= tsi_stmt_ptr (tsi_last (stmt_list
));
1453 /* Use the await_ready() call to test if we need to suspend. */
1454 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1455 ready_cond
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, ready_cond
);
1457 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1459 tree body_list
= NULL
;
1460 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1461 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1463 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1464 append_to_statement_list (r
, &body_list
);
1466 /* Find out what we have to do with the awaiter's suspend method.
1468 (5.1) If the result of await-ready is false, the coroutine is considered
1470 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1471 await-suspend.resume() is evaluated.
1472 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1473 and the coroutine is resumed if the result is false.
1474 (5.1.3) Otherwise, await-suspend is evaluated. */
1476 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1477 tree susp_type
= TREE_TYPE (suspend
);
1479 bool is_cont
= false;
1480 /* NOTE: final suspend can't resume; the "resume" label in that case
1481 corresponds to implicit destruction. */
1482 if (VOID_TYPE_P (susp_type
))
1484 /* We just call await_suspend() and hit the yield. */
1485 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1486 append_to_statement_list (suspend
, &body_list
);
1488 else if (TREE_CODE (susp_type
) == BOOLEAN_TYPE
)
1490 /* Boolean return, continue if the call returns false. */
1491 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1493 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1494 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1495 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1497 append_to_statement_list (r
, &body_list
);
1501 r
= build1_loc (loc
, CONVERT_EXPR
, void_coro_handle_type
, suspend
);
1502 r
= build2_loc (loc
, INIT_EXPR
, void_coro_handle_type
, data
->conthand
, r
);
1503 r
= build1 (CONVERT_EXPR
, void_type_node
, r
);
1504 append_to_statement_list (r
, &body_list
);
1508 tree d_l
= build_address (destroy_label
);
1509 tree r_l
= build_address (resume_label
);
1510 tree susp
= build_address (data
->cororet
);
1511 tree cont
= build_address (data
->corocont
);
1512 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1514 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1516 tree sw
= begin_switch_stmt ();
1517 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1518 DECL_ARTIFICIAL (cond
) = 1;
1519 DECL_IGNORED_P (cond
) = 1;
1520 layout_decl (cond
, 0);
1522 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1523 susp_idx
, final_susp
, r_l
, d_l
,
1525 r
= build2 (INIT_EXPR
, integer_type_node
, cond
, r
);
1526 finish_switch_cond (r
, sw
);
1527 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1528 create_anon_label_with_ctx (loc
, actor
));
1529 add_stmt (r
); /* case 0: */
1530 /* Implement the suspend, a scope exit without clean ups. */
1531 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1,
1532 is_cont
? cont
: susp
);
1533 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1534 add_stmt (r
); /* goto ret; */
1535 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1536 create_anon_label_with_ctx (loc
, actor
));
1537 add_stmt (r
); /* case 1: */
1538 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1539 add_stmt (r
); /* goto resume; */
1540 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1541 create_anon_label_with_ctx (loc
, actor
));
1542 add_stmt (r
); /* default:; */
1543 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1544 add_stmt (r
); /* goto destroy; */
1546 /* part of finish switch. */
1547 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1549 tree scope
= SWITCH_STMT_SCOPE (sw
);
1550 SWITCH_STMT_SCOPE (sw
) = NULL
;
1551 r
= do_poplevel (scope
);
1552 append_to_statement_list (r
, &body_list
);
1554 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1555 append_to_statement_list (destroy_label
, &body_list
);
1557 append_to_statement_list (dtor
, &body_list
);
1558 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1559 append_to_statement_list (r
, &body_list
);
1561 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1564 append_to_statement_list (r
, &stmt_list
);
1567 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1568 append_to_statement_list (resume_label
, &stmt_list
);
1572 /* Note that we are about to execute the await_resume() for the initial
1573 await expression. */
1574 r
= build2_loc (loc
, MODIFY_EXPR
, boolean_type_node
, data
->i_a_r_c
,
1576 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1577 append_to_statement_list (r
, &stmt_list
);
1580 /* This will produce the value (if one is provided) from the co_await
1582 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1583 if (REFERENCE_REF_P (resume_call
))
1584 /* Sink to await_resume call_expr. */
1585 resume_call
= TREE_OPERAND (resume_call
, 0);
1587 *await_expr
= resume_call
; /* Replace the co_await expr with its result. */
1588 append_to_statement_list_force (saved_statement
, &stmt_list
);
1589 /* Get a pointer to the revised statment. */
1590 tree
*revised
= tsi_stmt_ptr (tsi_last (stmt_list
));
1592 append_to_statement_list (dtor
, &stmt_list
);
1595 /* Replace the original statement with the expansion. */
1598 /* Now, if the awaitable had an initializer, expand any awaits that might
1599 be embedded in it. */
1602 cp_walk_tree (await_init
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1603 expand_one_await_expression (await_init
, aw_expr_ptr
, d
);
1605 /* Expand any more await expressions in the the original statement. */
1606 if (cp_walk_tree (revised
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1607 expand_one_await_expression (revised
, aw_expr_ptr
, d
);
1612 /* Check to see if a statement contains at least one await expression, if
1613 so, then process that. */
1616 process_one_statement (tree
*stmt
, void *d
)
1619 if (cp_walk_tree (stmt
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1620 expand_one_await_expression (stmt
, aw_expr_ptr
, d
);
1625 await_statement_expander (tree
*stmt
, int *do_subtree
, void *d
)
1627 tree res
= NULL_TREE
;
1629 /* Process a statement at a time. */
1630 if (STATEMENT_CLASS_P (*stmt
) || TREE_CODE (*stmt
) == BIND_EXPR
)
1631 return NULL_TREE
; /* Just process the sub-trees. */
1632 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1634 tree_stmt_iterator i
;
1635 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1637 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_expander
,
1642 *do_subtree
= 0; /* Done subtrees. */
1644 else if (EXPR_P (*stmt
))
1646 process_one_statement (stmt
, d
);
1647 *do_subtree
= 0; /* Done subtrees. */
1650 /* Continue statement walk, where required. */
1654 /* Suspend point hash_map. */
1656 struct suspend_point_info
1658 /* coro frame field type. */
1659 tree awaitable_type
;
1660 /* coro frame field name. */
1661 tree await_field_id
;
1664 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1666 struct await_xform_data
1668 tree actor_fn
; /* Decl for context. */
1676 /* When we built the await expressions, we didn't know the coro frame
1677 layout, therefore no idea where to find the promise or where to put
1678 the awaitables. Now we know these things, fill them in. */
1681 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1683 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1684 location_t loc
= EXPR_LOCATION (await_expr
);
1687 error_at (loc
, "no suspend point info for %qD", await_expr
);
1688 return error_mark_node
;
1691 /* So, on entry, we have:
1692 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1693 We no longer need a [it had diagnostic value, maybe?]
1694 We need to replace the promise proxy in all elements
1695 We need to replace the e_proxy in the awr_call. */
1697 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1699 /* If we have a frame var for the awaitable, get a reference to it. */
1701 if (si
->await_field_id
)
1704 = lookup_member (coro_frame_type
, si
->await_field_id
,
1705 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
1706 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
,
1708 tf_warning_or_error
);
1710 /* Replace references to the instance proxy with the frame entry now
1712 data
.from
= TREE_OPERAND (await_expr
, 1);
1714 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1716 /* .. and replace. */
1717 TREE_OPERAND (await_expr
, 1) = as
;
1720 /* Now do the self_handle. */
1721 data
.from
= xform
->self_h_proxy
;
1722 data
.to
= xform
->real_self_h
;
1723 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1725 /* Now do the promise. */
1726 data
.from
= xform
->promise_proxy
;
1727 data
.to
= xform
->real_promise
;
1728 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1733 /* A wrapper for the transform_await_expr function so that it can be a
1734 callback from cp_walk_tree. */
1737 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1739 /* Set actor function as new DECL_CONTEXT of label_decl. */
1740 struct await_xform_data
*xform
= (struct await_xform_data
*) d
;
1741 if (TREE_CODE (*stmt
) == LABEL_DECL
1742 && DECL_CONTEXT (*stmt
) != xform
->actor_fn
)
1743 DECL_CONTEXT (*stmt
) = xform
->actor_fn
;
1745 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
&& TREE_CODE (*stmt
) != CO_YIELD_EXPR
)
1748 tree await_expr
= *stmt
;
1749 *stmt
= transform_await_expr (await_expr
, xform
);
1750 if (*stmt
== error_mark_node
)
1755 /* This caches information that we determine about function params,
1756 their uses and copies in the coroutine frame. */
1760 tree field_id
; /* The name of the copy in the coroutine frame. */
1761 vec
<tree
*> *body_uses
; /* Worklist of uses, void if there are none. */
1762 tree frame_type
; /* The type used to represent this parm in the frame. */
1763 tree orig_type
; /* The original type of the parm (not as passed). */
1764 bool by_ref
; /* Was passed by reference. */
1765 bool rv_ref
; /* Was an rvalue reference. */
1766 bool pt_ref
; /* Was a pointer to object. */
1767 bool trivial_dtor
; /* The frame type has a trivial DTOR. */
1768 bool this_ptr
; /* Is 'this' */
1771 struct local_var_info
1776 bool is_lambda_capture
;
1780 /* For figuring out what local variable usage we have. */
1781 struct local_vars_transform
1785 tree coro_frame_type
;
1787 hash_map
<tree
, local_var_info
> *local_var_uses
;
1791 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
1793 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
1795 /* For each var in this bind expr (that has a frame id, which means it was
1796 accessed), build a frame reference for each and then walk the bind expr
1797 statements, substituting the frame ref for the original var. */
1799 if (TREE_CODE (*stmt
) == BIND_EXPR
)
1802 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1803 lvar
= DECL_CHAIN (lvar
))
1806 local_var_info
&local_var
1807 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
1808 gcc_checking_assert (existed
);
1810 /* Re-write the variable's context to be in the actor func. */
1811 DECL_CONTEXT (lvar
) = lvd
->context
;
1813 /* we need to walk some of the decl trees, which might contain
1814 references to vars replaced at a higher level. */
1815 cp_walk_tree (&DECL_INITIAL (lvar
), transform_local_var_uses
, d
,
1817 cp_walk_tree (&DECL_SIZE (lvar
), transform_local_var_uses
, d
, NULL
);
1818 cp_walk_tree (&DECL_SIZE_UNIT (lvar
), transform_local_var_uses
, d
,
1821 /* For capture proxies, this could include the decl value expr. */
1822 if (local_var
.is_lambda_capture
)
1824 tree ve
= DECL_VALUE_EXPR (lvar
);
1825 cp_walk_tree (&ve
, transform_local_var_uses
, d
, NULL
);
1826 continue; /* No frame entry for this. */
1829 /* TODO: implement selective generation of fields when vars are
1831 if (local_var
.field_id
== NULL_TREE
)
1832 continue; /* Wasn't used. */
1835 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
1836 /*protect=*/1, /*want_type=*/0,
1837 tf_warning_or_error
);
1838 tree fld_idx
= build3_loc (lvd
->loc
, COMPONENT_REF
, TREE_TYPE (lvar
),
1839 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
1840 local_var
.field_idx
= fld_idx
;
1842 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
1844 /* Now we have processed and removed references to the original vars,
1845 we can drop those from the bind - leaving capture proxies alone. */
1846 for (tree
*pvar
= &BIND_EXPR_VARS (*stmt
); *pvar
!= NULL
;)
1849 local_var_info
&local_var
1850 = lvd
->local_var_uses
->get_or_insert (*pvar
, &existed
);
1851 gcc_checking_assert (existed
);
1853 /* Leave lambda closure captures alone, we replace the *this
1854 pointer with the frame version and let the normal process
1855 deal with the rest. */
1856 if (local_var
.is_lambda_capture
)
1858 pvar
= &DECL_CHAIN (*pvar
);
1862 /* It's not used, but we can let the optimizer deal with that. */
1863 if (local_var
.field_id
== NULL_TREE
)
1865 pvar
= &DECL_CHAIN (*pvar
);
1869 /* Discard this one, we replaced it. */
1870 *pvar
= DECL_CHAIN (*pvar
);
1873 *do_subtree
= 0; /* We've done the body already. */
1877 tree var_decl
= *stmt
;
1878 /* Look inside cleanups, we don't want to wrap a statement list in a
1880 bool needs_cleanup
= true;
1881 if (TREE_CODE (var_decl
) == CLEANUP_POINT_EXPR
)
1882 var_decl
= TREE_OPERAND (var_decl
, 0);
1884 needs_cleanup
= false;
1886 /* Look inside the decl_expr for the actual var. */
1887 bool decl_expr_p
= TREE_CODE (var_decl
) == DECL_EXPR
;
1888 if (decl_expr_p
&& TREE_CODE (DECL_EXPR_DECL (var_decl
)) == VAR_DECL
)
1889 var_decl
= DECL_EXPR_DECL (var_decl
);
1890 else if (TREE_CODE (var_decl
) != VAR_DECL
)
1893 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1894 for the promise and coroutine handle(s), to global vars or to compiler
1895 temporaries. Skip past these, we will handle them later. */
1896 local_var_info
*local_var_i
= lvd
->local_var_uses
->get (var_decl
);
1897 if (local_var_i
== NULL
)
1900 if (local_var_i
->is_lambda_capture
)
1903 /* This is our revised 'local' i.e. a frame slot. */
1904 tree revised
= local_var_i
->field_idx
;
1905 gcc_checking_assert (DECL_CONTEXT (var_decl
) == lvd
->context
);
1907 if (decl_expr_p
&& DECL_INITIAL (var_decl
))
1909 location_t loc
= DECL_SOURCE_LOCATION (var_decl
);
1911 = cp_build_modify_expr (loc
, revised
, INIT_EXPR
,
1912 DECL_INITIAL (var_decl
), tf_warning_or_error
);
1914 r
= coro_build_cvt_void_expr_stmt (r
, EXPR_LOCATION (*stmt
));
1921 *do_subtree
= 0; /* We've accounted for the nested use. */
1925 /* The actor transform. */
1928 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
1929 tree orig
, hash_map
<tree
, param_info
> *param_uses
,
1930 hash_map
<tree
, local_var_info
> *local_var_uses
,
1931 vec
<tree
, va_gc
> *param_dtor_list
, tree initial_await
,
1932 tree final_await
, unsigned body_count
, tree frame_size
)
1934 verify_stmt_tree (fnbody
);
1935 /* Some things we inherit from the original function. */
1936 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
1937 tree handle_type
= get_coroutine_handle_type (orig
);
1938 tree self_h_proxy
= get_coroutine_self_handle_proxy (orig
);
1939 tree promise_type
= get_coroutine_promise_type (orig
);
1940 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
1941 tree act_des_fn_type
1942 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
1943 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
1945 /* One param, the coro frame pointer. */
1946 tree actor_fp
= DECL_ARGUMENTS (actor
);
1948 /* A void return. */
1949 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
1950 DECL_ARTIFICIAL (resdecl
) = 1;
1951 DECL_IGNORED_P (resdecl
) = 1;
1952 DECL_RESULT (actor
) = resdecl
;
1953 DECL_COROUTINE_P (actor
) = 1;
1955 /* We have a definition here. */
1956 TREE_STATIC (actor
) = 1;
1958 tree actor_outer
= push_stmt_list ();
1959 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
1960 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
1962 /* ??? Can we dispense with the enclosing bind if the function body does
1963 not start with a bind_expr? (i.e. there's no contained scopes). */
1964 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
1965 tree top_block
= make_node (BLOCK
);
1966 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
1968 tree continuation
= build_lang_decl (VAR_DECL
,
1969 get_identifier ("actor.continue"),
1970 void_coro_handle_type
);
1971 DECL_ARTIFICIAL (continuation
) = 1;
1972 DECL_IGNORED_P (continuation
) = 1;
1973 DECL_CONTEXT (continuation
) = actor
;
1974 BIND_EXPR_VARS (actor_bind
) = continuation
;
1976 /* Update the block associated with the outer scope of the orig fn. */
1977 tree first
= expr_first (fnbody
);
1978 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
1980 /* We will discard this, since it's connected to the original scope
1982 tree block
= BIND_EXPR_BLOCK (first
);
1983 if (block
) /* For this to be missing is probably a bug. */
1985 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
1986 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
1987 BLOCK_SUPERCONTEXT (block
) = top_block
;
1988 BLOCK_SUBBLOCKS (top_block
) = block
;
1992 add_stmt (actor_bind
);
1993 tree actor_body
= push_stmt_list ();
1995 /* The entry point for the actor code from the ramp. */
1996 tree actor_begin_label
1997 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
1998 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
2000 /* Declare the continuation handle. */
2001 add_decl_expr (continuation
);
2003 /* Re-write param references in the body, no code should be generated
2005 if (DECL_ARGUMENTS (orig
))
2008 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
2011 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
2012 if (!parm
.body_uses
)
2013 continue; /* Wasn't used in the orignal function body. */
2015 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
2016 /*protect=*/1, /*want_type=*/0,
2017 tf_warning_or_error
);
2018 tree fld_idx
= build3_loc (loc
, COMPONENT_REF
, parm
.frame_type
,
2019 actor_frame
, fld_ref
, NULL_TREE
);
2021 /* We keep these in the frame as a regular pointer, so convert that
2022 back to the type expected. */
2024 fld_idx
= build1_loc (loc
, CONVERT_EXPR
, TREE_TYPE (arg
), fld_idx
);
2026 /* We expect an rvalue ref. here. */
2028 fld_idx
= convert_to_reference (DECL_ARG_TYPE (arg
), fld_idx
,
2029 CONV_STATIC
, LOOKUP_NORMAL
,
2030 NULL_TREE
, tf_warning_or_error
);
2034 FOR_EACH_VEC_ELT (*parm
.body_uses
, i
, puse
)
2039 /* Re-write local vars, similarly. */
2040 local_vars_transform xform_vars_data
2041 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
2042 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
2044 tree resume_idx_name
= get_identifier ("__resume_at");
2045 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2046 tf_warning_or_error
);
2047 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
2048 rat_field
, NULL_TREE
);
2051 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
2054 = create_named_label_with_ctx (loc
, "actor.continue.ret", actor
);
2056 tree lsb_if
= begin_if_stmt ();
2057 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
2058 build_int_cst (short_unsigned_type_node
, 1));
2059 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
2060 build_int_cst (short_unsigned_type_node
, 0));
2061 finish_if_stmt_cond (chkb0
, lsb_if
);
2063 tree destroy_dispatcher
= begin_switch_stmt ();
2064 finish_switch_cond (rat
, destroy_dispatcher
);
2065 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2066 create_anon_label_with_ctx (loc
, actor
));
2068 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2069 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2072 short unsigned lab_num
= 3;
2073 for (unsigned destr_pt
= 0; destr_pt
< body_count
+ 2; destr_pt
++)
2075 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2076 b
= build_case_label (l_num
, NULL_TREE
,
2077 create_anon_label_with_ctx (loc
, actor
));
2079 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2081 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2083 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
2088 /* Insert the prototype dispatcher. */
2089 finish_switch_stmt (destroy_dispatcher
);
2091 finish_then_clause (lsb_if
);
2093 tree dispatcher
= begin_switch_stmt ();
2094 finish_switch_cond (rat
, dispatcher
);
2095 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
2096 create_anon_label_with_ctx (loc
, actor
));
2098 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
2101 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2102 create_anon_label_with_ctx (loc
, actor
));
2104 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2105 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2109 /* The final resume should be made to hit the default (trap, UB) entry. */
2110 for (unsigned resu_pt
= 0; resu_pt
< body_count
+ 1; resu_pt
++)
2112 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2113 b
= build_case_label (l_num
, NULL_TREE
,
2114 create_anon_label_with_ctx (loc
, actor
));
2116 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2118 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2120 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
2125 /* Insert the prototype dispatcher. */
2126 finish_switch_stmt (dispatcher
);
2128 finish_if_stmt (lsb_if
);
2130 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
2133 /* actor's version of the promise. */
2134 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
2135 tf_warning_or_error
);
2136 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
, false,
2137 tf_warning_or_error
);
2139 /* actor's coroutine 'self handle'. */
2140 tree ash_m
= lookup_member (coro_frame_type
, get_identifier ("__self_h"), 1,
2141 0, tf_warning_or_error
);
2142 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
2143 false, tf_warning_or_error
);
2144 /* So construct the self-handle from the frame address. */
2145 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
2146 0, tf_warning_or_error
);
2148 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2149 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2150 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2151 NULL
, tf_warning_or_error
);
2152 r
= build2 (INIT_EXPR
, handle_type
, ash
, hfa
);
2153 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2155 release_tree_vector (args
);
2157 /* Now we know the real promise, and enough about the frame layout to
2158 decide where to put things. */
2160 await_xform_data xform
2161 = {actor
, actor_frame
, promise_proxy
, ap
, self_h_proxy
, ash
};
2163 /* Get a reference to the initial suspend var in the frame. */
2164 transform_await_expr (initial_await
, &xform
);
2165 tree initial_await_stmt
= coro_build_expr_stmt (initial_await
, loc
);
2167 /* co_return branches to the final_suspend label, so declare that now. */
2168 tree fs_label
= create_named_label_with_ctx (loc
, "final.suspend", actor
);
2170 /* Expand co_returns in the saved function body */
2171 fnbody
= expand_co_returns (&fnbody
, promise_proxy
, ap
, fs_label
);
2173 /* n4849 adds specific behaviour to treat exceptions thrown by the
2174 await_resume () of the initial suspend expression. In order to
2175 implement this, we need to treat the initial_suspend expression
2176 as if it were part of the user-authored function body. This
2177 only applies if exceptions are enabled. */
2178 if (flag_exceptions
)
2180 tree outer
= fnbody
;
2181 if (TREE_CODE (outer
) == BIND_EXPR
)
2182 outer
= BIND_EXPR_BODY (outer
);
2183 gcc_checking_assert (TREE_CODE (outer
) == TRY_BLOCK
);
2184 tree sl
= TRY_STMTS (outer
);
2185 if (TREE_CODE (sl
) == STATEMENT_LIST
)
2187 tree_stmt_iterator si
= tsi_start (sl
);
2188 tsi_link_before (&si
, initial_await_stmt
, TSI_NEW_STMT
);
2192 tree new_try
= NULL_TREE
;
2193 append_to_statement_list (initial_await_stmt
, &new_try
);
2194 append_to_statement_list (sl
, &new_try
);
2195 TRY_STMTS (outer
) = new_try
;
2199 add_stmt (initial_await_stmt
);
2201 /* Transform the await expressions in the function body. Only do each
2203 hash_set
<tree
> pset
;
2204 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2206 /* Add in our function body with the co_returns rewritten to final form. */
2209 /* Final suspend starts here. */
2210 r
= build_stmt (loc
, LABEL_EXPR
, fs_label
);
2213 /* Set the actor pointer to null, so that 'done' will work.
2214 Resume from here is UB anyway - although a 'ready' await will
2215 branch to the final resume, and fall through to the destroy. */
2217 = lookup_member (coro_frame_type
, get_identifier ("__resume"),
2218 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2219 tree res_x
= build_class_member_access_expr (actor_frame
, resume_m
, NULL_TREE
,
2220 false, tf_warning_or_error
);
2221 r
= build1 (CONVERT_EXPR
, act_des_fn_ptr
, integer_zero_node
);
2222 r
= build2 (INIT_EXPR
, act_des_fn_ptr
, res_x
, r
);
2223 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2226 /* Get a reference to the final suspend var in the frame. */
2227 transform_await_expr (final_await
, &xform
);
2228 r
= coro_build_expr_stmt (final_await
, loc
);
2231 /* now do the tail of the function. */
2232 tree del_promise_label
2233 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2234 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2237 /* Destructors for the things we built explicitly. */
2238 r
= build_special_member_call (ap
, complete_dtor_identifier
, NULL
,
2239 promise_type
, LOOKUP_NORMAL
,
2240 tf_warning_or_error
);
2243 tree del_frame_label
2244 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2245 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2248 /* Here deallocate the frame (if we allocated it), which we will have at
2251 = lookup_member (coro_frame_type
, get_identifier ("__frame_needs_free"), 1,
2252 0, tf_warning_or_error
);
2253 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2254 false, tf_warning_or_error
);
2256 tree need_free_if
= begin_if_stmt ();
2257 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2258 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2259 finish_if_stmt_cond (cmp
, need_free_if
);
2260 if (param_dtor_list
!= NULL
)
2264 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2267 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2268 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2269 false, tf_warning_or_error
);
2270 tree t
= TREE_TYPE (a
);
2273 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2274 LOOKUP_NORMAL
, tf_warning_or_error
);
2279 /* n4849 [dcl.fct.def.coroutine] / 12
2280 The deallocation function’s name is looked up in the scope of the promise
2281 type. If this lookup fails, the deallocation function’s name is looked up
2282 in the global scope. If deallocation function lookup finds both a usual
2283 deallocation function with only a pointer parameter and a usual
2284 deallocation function with both a pointer parameter and a size parameter,
2285 then the selected deallocation function shall be the one with two
2286 parameters. Otherwise, the selected deallocation function shall be the
2287 function with one parameter. If no usual deallocation function is found
2288 the program is ill-formed. The selected deallocation function shall be
2289 called with the address of the block of storage to be reclaimed as its
2290 first argument. If a deallocation function with a parameter of type
2291 std::size_t is used, the size of the block is passed as the corresponding
2294 tree del_coro_fr
= NULL_TREE
;
2295 tree frame_arg
= build1 (CONVERT_EXPR
, ptr_type_node
, actor_fp
);
2297 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2298 tree fns
= lookup_promise_method (orig
, delname
, loc
, /*musthave=*/false);
2299 if (fns
&& BASELINK_P (fns
))
2301 /* Look for sized version first, since this takes precedence. */
2302 vec
<tree
, va_gc
> *args
= make_tree_vector ();
2303 vec_safe_push (args
, frame_arg
);
2304 vec_safe_push (args
, frame_size
);
2305 tree dummy_promise
= build_dummy_object (promise_type
);
2307 /* It's OK to fail for this one... */
2308 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2309 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2312 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2314 release_tree_vector (args
);
2315 args
= make_tree_vector_single (frame_arg
);
2316 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2317 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2321 /* But one of them must succeed, or the program is ill-formed. */
2322 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2324 error_at (loc
, "%qE is provided by %qT but is not usable with"
2325 " the function signature %qD", delname
, promise_type
, orig
);
2326 del_coro_fr
= error_mark_node
;
2331 del_coro_fr
= build_op_delete_call (DELETE_EXPR
, frame_arg
, frame_size
,
2332 /*global_p=*/true, /*placement=*/NULL
,
2334 tf_warning_or_error
);
2335 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2336 del_coro_fr
= error_mark_node
;
2339 del_coro_fr
= coro_build_cvt_void_expr_stmt (del_coro_fr
, loc
);
2340 add_stmt (del_coro_fr
);
2341 finish_then_clause (need_free_if
);
2342 tree scope
= IF_SCOPE (need_free_if
);
2343 IF_SCOPE (need_free_if
) = NULL
;
2344 r
= do_poplevel (scope
);
2348 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2349 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2350 r
= maybe_cleanup_point_expr_void (r
);
2353 /* This is the suspend return point. */
2354 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2357 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2358 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2359 r
= maybe_cleanup_point_expr_void (r
);
2362 /* This is the 'continuation' return point. For such a case we have a coro
2363 handle (from the await_suspend() call) and we want handle.resume() to
2364 execute as a tailcall allowing arbitrary chaining of coroutines. */
2365 r
= build_stmt (loc
, LABEL_EXPR
, continue_label
);
2368 /* We want to force a tail-call even for O0/1, so this expands the resume
2369 call into its underlying implementation. */
2370 tree addr
= lookup_member (void_coro_handle_type
, coro_address_identifier
,
2371 1, 0, tf_warning_or_error
);
2372 addr
= build_new_method_call (continuation
, addr
, NULL
, NULL_TREE
,
2373 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
2374 tree resume
= build_call_expr_loc
2375 (loc
, builtin_decl_explicit (BUILT_IN_CORO_RESUME
), 1, addr
);
2377 /* In order to support an arbitrary number of coroutine continuations,
2378 we must tail call them. However, some targets do not support indirect
2379 tail calls to arbitrary callees. See PR94359. */
2380 CALL_EXPR_TAILCALL (resume
) = true;
2381 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
2384 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2385 gcc_checking_assert (maybe_cleanup_point_expr_void (r
) == r
);
2388 /* We will need to know which resume point number should be encoded. */
2390 = lookup_member (coro_frame_type
, resume_idx_name
,
2391 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2392 tree resume_pt_number
2393 = build_class_member_access_expr (actor_frame
, res_idx_m
, NULL_TREE
, false,
2394 tf_warning_or_error
);
2396 /* Boolean value to flag that the initial suspend expression's
2397 await_resume () has been called, and therefore we are in the user's
2398 function body for the purposes of handing exceptions. */
2400 = lookup_member (coro_frame_type
, get_identifier ("__i_a_r_c"),
2401 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2403 = build_class_member_access_expr (actor_frame
, i_a_r_c_m
, NULL_TREE
,
2404 false, tf_warning_or_error
);
2406 /* We've now rewritten the tree and added the initial and final
2407 co_awaits. Now pass over the tree and expand the co_awaits. */
2409 coro_aw_data data
= {actor
, actor_fp
, resume_pt_number
, i_a_r_c
,
2410 ash
, del_promise_label
, ret_label
,
2411 continue_label
, continuation
, 2};
2412 cp_walk_tree (&actor_body
, await_statement_expander
, &data
, NULL
);
2414 actor_body
= pop_stmt_list (actor_body
);
2415 BIND_EXPR_BODY (actor_bind
) = actor_body
;
2417 finish_compound_stmt (stmt
);
2418 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2419 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2422 /* The prototype 'destroy' function :
2423 frame->__resume_at |= 1;
2427 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2430 /* One param, the coro frame pointer. */
2431 tree destr_fp
= DECL_ARGUMENTS (destroy
);
2433 /* A void return. */
2434 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2435 DECL_ARTIFICIAL (resdecl
) = 1;
2436 DECL_IGNORED_P (resdecl
) = 1;
2437 DECL_RESULT (destroy
) = resdecl
;
2439 /* We have a definition here. */
2440 TREE_STATIC (destroy
) = 1;
2441 DECL_COROUTINE_P (destroy
) = 1;
2443 tree destr_outer
= push_stmt_list ();
2444 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2445 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2447 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2449 tree resume_idx_name
= get_identifier ("__resume_at");
2450 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2451 tf_warning_or_error
);
2452 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, destr_frame
,
2453 rat_field
, NULL_TREE
);
2455 /* _resume_at |= 1 */
2456 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2457 build_int_cst (short_unsigned_type_node
, 1));
2458 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2459 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2462 /* So .. call the actor .. */
2463 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2464 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2468 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2469 r
= maybe_cleanup_point_expr_void (r
);
2472 finish_compound_stmt (dstr_stmt
);
2473 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2476 /* Helper that returns an identifier for an appended extension to the
2477 current un-mangled function name. */
2480 get_fn_local_identifier (tree orig
, const char *append
)
2482 /* Figure out the bits we need to generate names for the outlined things
2483 For consistency, this needs to behave the same way as
2484 ASM_FORMAT_PRIVATE_NAME does. */
2485 tree nm
= DECL_NAME (orig
);
2486 const char *sep
, *pfx
= "";
2487 #ifndef NO_DOT_IN_LABEL
2490 #ifndef NO_DOLLAR_IN_LABEL
2499 if (DECL_ASSEMBLER_NAME (orig
))
2500 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2502 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2503 && DECL_TI_ARGS (orig
))
2505 tree tpl_args
= DECL_TI_ARGS (orig
);
2506 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2507 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2509 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2510 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2512 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2515 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2517 return get_identifier (an
);
2521 build_init_or_final_await (location_t loc
, bool is_final
)
2523 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2524 : coro_initial_suspend_identifier
;
2525 tree setup_meth
= lookup_promise_method (current_function_decl
, suspend_alt
,
2526 loc
, /*musthave=*/true);
2527 if (!setup_meth
|| setup_meth
== error_mark_node
)
2528 return error_mark_node
;
2530 tree s_fn
= NULL_TREE
;
2531 tree setup_call
= build_new_method_call (
2532 get_coroutine_promise_proxy (current_function_decl
), setup_meth
, NULL
,
2533 NULL_TREE
, LOOKUP_NORMAL
, &s_fn
, tf_warning_or_error
);
2535 if (!s_fn
|| setup_call
== error_mark_node
)
2536 return error_mark_node
;
2538 /* So build the co_await for this */
2539 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2540 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2541 : INITIAL_SUSPEND_POINT
));
2544 /* Callback to record the essential data for each await point found in the
2548 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
)
2551 suspend_point_info
&s
2552 = suspend_points
->get_or_insert (await_expr
, &seen
);
2555 error_at (EXPR_LOCATION (await_expr
), "duplicate info for %qE",
2559 s
.awaitable_type
= aw_type
;
2560 s
.await_field_id
= aw_nam
;
2564 /* Small helper for the repetitive task of adding a new field to the coro
2568 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
2571 tree id
= get_identifier (name
);
2572 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
2573 DECL_CHAIN (decl
) = *field_list
;
2578 /* This data set is used when analyzing statements for await expressions. */
2579 struct susp_frame_data
2581 /* Function-wide. */
2582 tree
*field_list
; /* The current coroutine frame field list. */
2583 tree handle_type
; /* The self-handle type for this coroutine. */
2584 vec
<tree
, va_gc
> *block_stack
; /* Track block scopes. */
2585 vec
<tree
, va_gc
> *bind_stack
; /* Track current bind expr. */
2586 unsigned await_number
; /* Which await in the function. */
2587 unsigned cond_number
; /* Which replaced condition in the fn. */
2588 /* Temporary values for one statement or expression being analyzed. */
2589 hash_set
<tree
> captured_temps
; /* The suspend captured these temps. */
2590 vec
<tree
, va_gc
> *to_replace
; /* The VAR decls to replace. */
2591 hash_set
<tree
> *truth_aoif_to_expand
; /* The set of TRUTH exprs to expand. */
2592 unsigned saw_awaits
; /* Count of awaits in this statement */
2593 bool captures_temporary
; /* This expr captures temps by ref. */
2594 bool needs_truth_if_exp
; /* We must expand a truth_if expression. */
2597 /* Walk the sub-tree looking for call expressions that both capture
2598 references and have compiler-temporaries as parms. */
2601 captures_temporary (tree
*stmt
, int *do_subtree
, void *d
)
2603 /* Stop recursing if we see an await expression, the subtrees
2604 of that will be handled when it is processed. */
2605 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
|| TREE_CODE (*stmt
) == CO_YIELD_EXPR
)
2611 /* We're only interested in calls. */
2612 if (TREE_CODE (*stmt
) != CALL_EXPR
)
2615 /* Does this call capture references?
2616 Strip the ADDRESS_EXPR to get the fn decl and inspect it. */
2617 tree fn
= TREE_OPERAND (CALL_EXPR_FN (*stmt
), 0);
2618 bool is_meth
= TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
;
2619 tree arg
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2620 unsigned offset
= 3;
2621 for (unsigned anum
= 0; arg
!= NULL
; arg
= TREE_CHAIN (arg
), anum
++)
2623 tree parm_type
= TREE_VALUE (arg
);
2624 if (anum
== 0 && is_meth
&& INDIRECT_TYPE_P (parm_type
))
2626 /* Account for 'this' when the fn is a method. Unless it
2627 belongs to a CTOR or DTOR. */
2628 if (DECL_CONSTRUCTOR_P (fn
) || DECL_DESTRUCTOR_P (fn
))
2631 else if (!TYPE_REF_P (parm_type
))
2632 /* If it's not a reference, we don't care. */
2635 /* Fetch the value presented to the fn. */
2636 tree parm
= TREE_OPERAND (*stmt
, anum
+ offset
);
2638 while (TREE_CODE (parm
) == NOP_EXPR
)
2639 parm
= TREE_OPERAND (parm
, 0);
2641 /* We only care if we're taking the addr of a temporary. */
2642 if (TREE_CODE (parm
) != ADDR_EXPR
)
2645 parm
= TREE_OPERAND (parm
, 0);
2647 /* In case of component_ref, we need to capture the object of base
2648 class as if it is temporary object. There are two possibilities:
2649 (*base).field and base->field. */
2650 while (TREE_CODE (parm
) == COMPONENT_REF
)
2652 parm
= TREE_OPERAND (parm
, 0);
2653 if (TREE_CODE (parm
) == INDIRECT_REF
)
2654 parm
= TREE_OPERAND (parm
, 0);
2658 /* This isn't a temporary. */
2659 if ((TREE_CODE (parm
) == VAR_DECL
&& !DECL_ARTIFICIAL (parm
))
2660 || TREE_CODE (parm
) == PARM_DECL
2661 || TREE_CODE (parm
) == NON_LVALUE_EXPR
)
2664 if (TREE_CODE (parm
) == TARGET_EXPR
)
2666 /* We're taking the address of a temporary and using it as a ref. */
2667 tree tvar
= TREE_OPERAND (parm
, 0);
2668 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2670 susp_frame_data
*data
= (susp_frame_data
*) d
;
2671 data
->captures_temporary
= true;
2672 /* Record this one so we don't duplicate, and on the first
2673 occurrence note the target expr to be replaced. */
2674 if (!data
->captured_temps
.add (tvar
))
2675 vec_safe_push (data
->to_replace
, parm
);
2676 /* Now see if the initializer contains any more cases. */
2677 hash_set
<tree
> visited
;
2678 tree res
= cp_walk_tree (&TREE_OPERAND (parm
, 1),
2679 captures_temporary
, d
, &visited
);
2682 /* Otherwise, we're done with sub-trees for this. */
2684 else if (TREE_CODE (parm
) == CO_AWAIT_EXPR
)
2686 /* CO_AWAIT expressions behave in a similar manner to target
2687 expressions when the await_resume call is contained in one. */
2688 tree awr
= TREE_OPERAND (parm
, 3); /* call vector. */
2689 awr
= TREE_VEC_ELT (awr
, 2); /* resume call. */
2690 if (TREE_CODE (awr
) == TARGET_EXPR
)
2692 tree tvar
= TREE_OPERAND (awr
, 0);
2693 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2695 susp_frame_data
*data
= (susp_frame_data
*) d
;
2696 data
->captures_temporary
= true;
2697 /* Use this as a place-holder. */
2698 if (!data
->captured_temps
.add (tvar
))
2699 vec_safe_push (data
->to_replace
, parm
);
2701 /* We will walk the sub-trees of this co_await separately. */
2706 /* As far as it's necessary, we've walked the subtrees of the call
2712 /* If this is an await, then register it and decide on what coro
2713 frame storage is needed.
2714 If this is a co_yield (which embeds an await), drop the yield
2715 and record the await (the yield was kept for diagnostics only). */
2718 register_awaits (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
2720 susp_frame_data
*data
= (susp_frame_data
*) d
;
2722 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
&& TREE_CODE (*stmt
) != CO_YIELD_EXPR
)
2725 tree aw_expr
= *stmt
;
2726 location_t aw_loc
= EXPR_LOCATION (aw_expr
); /* location of the co_xxxx. */
2727 /* co_yield is syntactic sugar, re-write it to co_await. */
2728 if (TREE_CODE (aw_expr
) == CO_YIELD_EXPR
)
2730 aw_expr
= TREE_OPERAND (aw_expr
, 1);
2734 /* If the awaitable is a parm or a local variable, then we already have
2735 a frame copy, so don't make a new one. */
2736 tree aw
= TREE_OPERAND (aw_expr
, 1);
2737 tree aw_field_type
= TREE_TYPE (aw
);
2738 tree aw_field_nam
= NULL_TREE
;
2739 if (INDIRECT_REF_P (aw
))
2740 aw
= TREE_OPERAND (aw
, 0);
2741 if (TREE_CODE (aw
) == PARM_DECL
2742 || (TREE_CODE (aw
) == VAR_DECL
&& !DECL_ARTIFICIAL (aw
)))
2743 ; /* Don't make an additional copy. */
2746 /* The required field has the same type as the proxy stored in the
2748 char *nam
= xasprintf ("__aw_s.%d", data
->await_number
);
2749 aw_field_nam
= coro_make_frame_entry (data
->field_list
, nam
,
2750 aw_field_type
, aw_loc
);
2754 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
);
2756 /* Count how many awaits the current expression contains. */
2758 /* Each await suspend context is unique, this is a function-wide value. */
2759 data
->await_number
++;
2761 /* We now need to know if to take special action on lifetime extension
2762 of temporaries captured by reference. This can only happen if such
2763 a case appears in the initializer for the awaitable. The callback
2764 records captured temporaries including subtrees of initializers. */
2765 hash_set
<tree
> visited
;
2766 tree res
= cp_walk_tree (&TREE_OPERAND (aw_expr
, 2), captures_temporary
, d
,
2771 /* The gimplifier correctly extends the lifetime of temporaries captured
2772 by reference (per. [class.temporary] (6.9) "A temporary object bound
2773 to a reference parameter in a function call persists until the completion
2774 of the full-expression containing the call"). However, that is not
2775 sufficient to work across a suspension - and we need to promote such
2776 temporaries to be regular vars that will then get a coro frame slot.
2777 We don't want to incur the effort of checking for this unless we have
2778 an await expression in the current full expression. */
2780 /* This takes the statement which contains one or more temporaries that have
2781 been 'captured' by reference in the initializer(s) of co_await(s).
2782 The statement is replaced by a bind expression that has actual variables
2783 to replace the temporaries. These variables will be added to the coro-
2784 frame in the same manner as user-authored ones. */
2787 replace_statement_captures (tree
*stmt
, void *d
)
2789 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2790 location_t sloc
= EXPR_LOCATION (*stmt
);
2792 = build3_loc (sloc
, BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2794 /* Any cleanup point expression might no longer be necessary, since we
2795 are removing one or more temporaries. */
2796 tree aw_statement_current
= *stmt
;
2797 if (TREE_CODE (aw_statement_current
) == CLEANUP_POINT_EXPR
)
2798 aw_statement_current
= TREE_OPERAND (aw_statement_current
, 0);
2800 /* Collected the scope vars we need move the temps to regular. */
2801 tree aw_bind_body
= push_stmt_list ();
2802 tree varlist
= NULL_TREE
;
2804 while (!awpts
->to_replace
->is_empty ())
2806 tree to_replace
= awpts
->to_replace
->pop ();
2808 if (TREE_CODE (to_replace
) == CO_AWAIT_EXPR
)
2810 orig_temp
= TREE_OPERAND (to_replace
, 3);
2811 orig_temp
= TREE_VEC_ELT (orig_temp
, 2);
2812 orig_temp
= TREE_OPERAND (orig_temp
, 0);
2815 orig_temp
= TREE_OPERAND (to_replace
, 0);
2817 tree var_type
= TREE_TYPE (orig_temp
);
2818 gcc_checking_assert (same_type_p (TREE_TYPE (to_replace
), var_type
));
2819 /* Build a variable to hold the captured value, this will be included
2820 in the frame along with any user-authored locals. */
2821 char *nam
= xasprintf ("aw_%d.tmp.%d", awpts
->await_number
, ++vnum
);
2822 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
2824 /* If we have better location than the whole expression use that, else
2825 fall back to the expression loc. */
2826 DECL_CONTEXT (newvar
) = DECL_CONTEXT (orig_temp
);
2827 if (DECL_SOURCE_LOCATION (orig_temp
))
2828 sloc
= DECL_SOURCE_LOCATION (orig_temp
);
2830 sloc
= EXPR_LOCATION (*stmt
);
2831 DECL_SOURCE_LOCATION (newvar
) = sloc
;
2832 DECL_CHAIN (newvar
) = varlist
;
2833 varlist
= newvar
; /* Chain it onto the list for the bind expr. */
2834 /* Declare and initialize it in the new bind scope. */
2835 add_decl_expr (newvar
);
2836 tree new_s
= build2_loc (sloc
, INIT_EXPR
, var_type
, newvar
, to_replace
);
2837 new_s
= coro_build_cvt_void_expr_stmt (new_s
, sloc
);
2840 /* Replace all instances of that temp in the original expr. */
2841 proxy_replace pr
= {to_replace
, newvar
};
2842 cp_walk_tree (&aw_statement_current
, replace_proxy
, &pr
, NULL
);
2845 /* What's left should be the original statement with any co_await captured
2846 temporaries broken out. Other temporaries might remain so see if we
2847 need to wrap the revised statement in a cleanup. */
2848 aw_statement_current
= maybe_cleanup_point_expr_void (aw_statement_current
);
2849 add_stmt (aw_statement_current
);
2851 BIND_EXPR_BODY (aw_bind
) = pop_stmt_list (aw_bind_body
);
2852 awpts
->captured_temps
.empty ();
2854 BIND_EXPR_VARS (aw_bind
) = nreverse (varlist
);
2855 tree b_block
= make_node (BLOCK
);
2856 if (!awpts
->block_stack
->is_empty ())
2858 tree s_block
= awpts
->block_stack
->last ();
2861 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
2862 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
2863 BLOCK_SUBBLOCKS (s_block
) = b_block
;
2866 BIND_EXPR_BLOCK (aw_bind
) = b_block
;
2870 /* This is called for single statements from the co-await statement walker.
2871 It checks to see if the statement contains any co-awaits and, if so,
2872 whether any of these 'capture' a temporary by reference. */
2875 maybe_promote_captured_temps (tree
*stmt
, void *d
)
2877 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2878 hash_set
<tree
> visited
;
2879 awpts
->saw_awaits
= 0;
2881 /* When register_awaits sees an await, it walks the initializer for
2882 that await looking for temporaries captured by reference and notes
2883 them in awpts->captured_temps. */
2885 if (tree res
= cp_walk_tree (stmt
, register_awaits
, d
, &visited
))
2886 return res
; /* We saw some reason to abort the tree walk. */
2888 /* We only need to take any action here if the statement contained any
2889 awaits and any of those had temporaries captured by reference in their
2892 if (awpts
->saw_awaits
> 0 && !awpts
->captured_temps
.is_empty ())
2893 replace_statement_captures (stmt
, d
);
2898 /* Lightweight callback to determine two key factors:
2899 1) If the statement/expression contains any await expressions.
2900 2) If the statement/expression potentially requires a re-write to handle
2901 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
2902 so that the await expressions are not processed in the case of the
2904 CO_YIELD expressions are re-written to their underlying co_await. */
2907 analyze_expression_awaits (tree
*stmt
, int *do_subtree
, void *d
)
2909 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2911 switch (TREE_CODE (*stmt
))
2913 default: return NULL_TREE
;
2915 /* co_yield is syntactic sugar, re-write it to co_await. */
2916 *stmt
= TREE_OPERAND (*stmt
, 1);
2919 awpts
->saw_awaits
++;
2921 case TRUTH_ANDIF_EXPR
:
2922 case TRUTH_ORIF_EXPR
:
2924 /* We don't need special action for awaits in the always-executed
2925 arm of a TRUTH_IF. */
2926 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 0),
2927 analyze_expression_awaits
, d
, NULL
))
2929 /* However, if there are await expressions on the conditionally
2930 executed branch, we must expand the TRUTH_IF to ensure that the
2931 expanded await expression control-flow is fully contained in the
2932 conditionally executed code. */
2933 unsigned aw_count
= awpts
->saw_awaits
;
2934 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 1),
2935 analyze_expression_awaits
, d
, NULL
))
2937 if (awpts
->saw_awaits
> aw_count
)
2939 awpts
->truth_aoif_to_expand
->add (*stmt
);
2940 awpts
->needs_truth_if_exp
= true;
2942 /* We've done the sub-trees here. */
2948 return NULL_TREE
; /* Recurse until done. */
2952 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
2953 the conditional branch expand this to:
2955 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
2956 A) bool t = always exec expr
2958 B) t = conditionally exec expr
2959 c) EXPR' = EXPR with TAOIE replaced by t.
2961 Then repeat this for A, B and C. */
2963 struct truth_if_transform
{
2966 hash_set
<tree
> *truth_aoif_to_expand
;
2970 expand_one_truth_if (tree
*expr
, int *do_subtree
, void *d
)
2972 truth_if_transform
*xform
= (truth_if_transform
*) d
;
2974 bool needs_not
= false;
2975 switch (TREE_CODE (*expr
))
2978 case TRUTH_ORIF_EXPR
:
2981 case TRUTH_ANDIF_EXPR
:
2983 if (!xform
->truth_aoif_to_expand
->contains (*expr
))
2986 location_t sloc
= EXPR_LOCATION (*expr
);
2987 tree type
= TREE_TYPE (xform
->scratch_var
);
2988 gcc_checking_assert (TREE_CODE (type
) == BOOLEAN_TYPE
);
2989 tree new_list
= push_stmt_list ();
2990 /* Init our scratch with the unconditionally-evaluated expr. */
2991 tree new_s
= build2_loc (sloc
, INIT_EXPR
, boolean_type_node
,
2993 TREE_OPERAND (*expr
, 0));
2994 finish_expr_stmt (new_s
);
2995 tree
*pre
= tsi_stmt_ptr (tsi_last (new_list
));
2996 tree if_cond
= xform
->scratch_var
;
2998 if_cond
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, if_cond
);
2999 tree if_stmt
= begin_if_stmt ();
3000 finish_if_stmt_cond (if_cond
, if_stmt
);
3001 /* If we take the if branch, then overwrite scratch with the cond
3003 new_s
= build2 (INIT_EXPR
, boolean_type_node
,
3004 xform
->scratch_var
, TREE_OPERAND (*expr
, 1));
3005 finish_expr_stmt (new_s
);
3006 finish_then_clause (if_stmt
);
3007 finish_if_stmt (if_stmt
);
3008 *expr
= xform
->scratch_var
; /* now contains the result. */
3009 /* So now we've got a statement list expanding one TAOIe. */
3010 add_stmt (*xform
->orig_stmt
);
3011 tree
*post
= tsi_stmt_ptr (tsi_last (new_list
));
3012 *xform
->orig_stmt
= pop_stmt_list (new_list
);
3013 /* Now recurse into the pre, if and post parts. */
3014 truth_if_transform sub_data
= {pre
, xform
->scratch_var
,
3015 xform
->truth_aoif_to_expand
};
3016 if (tree res
= cp_walk_tree (pre
, expand_one_truth_if
, &sub_data
,
3019 sub_data
.orig_stmt
= &THEN_CLAUSE (if_stmt
);
3020 if (tree res
= cp_walk_tree (&THEN_CLAUSE (if_stmt
),
3021 expand_one_truth_if
, &sub_data
, NULL
))
3023 sub_data
.orig_stmt
= post
;
3024 if (tree res
= cp_walk_tree (post
, expand_one_truth_if
, &sub_data
,
3027 /* We've done the sub-trees here. */
3035 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3036 name is made up from NAM_ROOT, NAM_VERS. */
3039 add_var_to_bind (tree
& bind
, tree var_type
,
3040 const char *nam_root
, unsigned nam_vers
)
3043 tree b_vars
= BIND_EXPR_VARS (bind
);
3044 /* Build a variable to hold the condition, this will be included in the
3045 frame as a local var. */
3046 char *nam
= xasprintf ("%s.%d", nam_root
, nam_vers
);
3047 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
3049 DECL_CHAIN (newvar
) = b_vars
;
3050 BIND_EXPR_VARS (bind
) = newvar
;
3054 /* Helper to build and add if (!cond) break; */
3057 coro_build_add_if_not_cond_break (tree cond
)
3059 tree if_stmt
= begin_if_stmt ();
3060 tree invert
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3061 finish_if_stmt_cond (invert
, if_stmt
);
3062 finish_break_stmt ();
3063 finish_then_clause (if_stmt
);
3064 finish_if_stmt (if_stmt
);
3067 /* Tree walk callback to analyze, register and pre-process statements that
3068 contain await expressions. */
3071 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
3073 tree res
= NULL_TREE
;
3074 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3076 /* Process a statement at a time. */
3077 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3079 /* For conditional expressions, we might wish to add an artificial var
3080 to their containing bind expr. */
3081 vec_safe_push (awpts
->bind_stack
, *stmt
);
3082 /* We might need to insert a new bind expression, and want to link it
3083 into the correct scope, so keep a note of the current block scope. */
3084 tree blk
= BIND_EXPR_BLOCK (*stmt
);
3085 vec_safe_push (awpts
->block_stack
, blk
);
3086 res
= cp_walk_tree (&BIND_EXPR_BODY (*stmt
), await_statement_walker
,
3088 awpts
->block_stack
->pop ();
3089 awpts
->bind_stack
->pop ();
3090 *do_subtree
= 0; /* Done subtrees. */
3093 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
3095 tree_stmt_iterator i
;
3096 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
3098 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_walker
,
3103 *do_subtree
= 0; /* Done subtrees. */
3107 /* We have something to be handled as a single statement. */
3108 hash_set
<tree
> visited
;
3109 awpts
->saw_awaits
= 0;
3110 hash_set
<tree
> truth_aoif_to_expand
;
3111 awpts
->truth_aoif_to_expand
= &truth_aoif_to_expand
;
3112 awpts
->needs_truth_if_exp
= false;
3114 if (STATEMENT_CLASS_P (*stmt
))
3115 switch (TREE_CODE (*stmt
))
3117 /* Unless it's a special case, just walk the subtrees as usual. */
3118 default: return NULL_TREE
;
3120 /* When we have a conditional expression, which contains one or more
3121 await expressions, we have to break the condition out into a
3122 regular statement so that the control flow introduced by the await
3123 transforms can be implemented. */
3126 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3127 bool cond = cond with awaits.
3128 if (cond) then stmt1 else stmt2. */
3129 tree if_stmt
= *stmt
;
3130 /* We treat the condition as if it was a stand-alone statement,
3131 to see if there are any await expressions which will be analysed
3133 if ((res
= cp_walk_tree (&IF_COND (if_stmt
),
3134 analyze_expression_awaits
, d
, &visited
)))
3136 if (!awpts
->saw_awaits
)
3137 return NULL_TREE
; /* Nothing special to do here. */
3139 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3140 tree
& bind_expr
= awpts
->bind_stack
->last ();
3141 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3142 "ifcd", awpts
->cond_number
++);
3143 tree insert_list
= push_stmt_list ();
3144 tree cond_inner
= IF_COND (if_stmt
);
3145 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3146 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3147 add_decl_expr (newvar
);
3148 location_t sloc
= EXPR_LOCATION (IF_COND (if_stmt
));
3149 /* We want to initialize the new variable with the expression
3150 that contains the await(s) and potentially also needs to
3151 have truth_if expressions expanded. */
3152 tree new_s
= build2_loc (sloc
, MODIFY_EXPR
, boolean_type_node
,
3153 newvar
, cond_inner
);
3154 finish_expr_stmt (new_s
);
3155 if (awpts
->needs_truth_if_exp
)
3157 tree
*sp
= tsi_stmt_ptr (tsi_last (insert_list
));
3158 truth_if_transform xf
= {sp
, newvar
, &truth_aoif_to_expand
};
3159 if ((res
= cp_walk_tree (sp
, expand_one_truth_if
, &xf
, NULL
)))
3162 IF_COND (if_stmt
) = newvar
;
3164 *stmt
= pop_stmt_list (insert_list
);
3165 /* So now walk the new statement list. */
3166 res
= cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3167 *do_subtree
= 0; /* Done subtrees. */
3173 /* We turn 'while (cond with awaits) stmt' into
3175 if (!(cond with awaits))
3179 tree while_stmt
= *stmt
;
3180 if ((res
= cp_walk_tree (&WHILE_COND (while_stmt
),
3181 analyze_expression_awaits
, d
, &visited
)))
3183 if (!awpts
->saw_awaits
)
3184 return NULL_TREE
; /* Nothing special to do here. */
3186 tree insert_list
= push_stmt_list ();
3187 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt
));
3188 /* The original while body. */
3189 add_stmt (WHILE_BODY (while_stmt
));
3190 /* The new while body. */
3191 WHILE_BODY (while_stmt
) = pop_stmt_list (insert_list
);
3192 WHILE_COND (while_stmt
) = boolean_true_node
;
3193 /* So now walk the new statement list. */
3194 res
= cp_walk_tree (&WHILE_BODY (while_stmt
),
3195 await_statement_walker
, d
, NULL
);
3196 *do_subtree
= 0; /* Done subtrees. */
3202 /* We turn do stmt while (cond with awaits) into:
3205 if (!(cond with awaits))
3208 tree do_stmt
= *stmt
;
3209 if ((res
= cp_walk_tree (&DO_COND (do_stmt
),
3210 analyze_expression_awaits
, d
, &visited
)))
3212 if (!awpts
->saw_awaits
)
3213 return NULL_TREE
; /* Nothing special to do here. */
3215 tree insert_list
= push_stmt_list ();
3216 /* The original do stmt body. */
3217 add_stmt (DO_BODY (do_stmt
));
3218 coro_build_add_if_not_cond_break (DO_COND (do_stmt
));
3219 /* The new while body. */
3220 DO_BODY (do_stmt
) = pop_stmt_list (insert_list
);
3221 DO_COND (do_stmt
) = boolean_true_node
;
3222 /* So now walk the new statement list. */
3223 res
= cp_walk_tree (&DO_BODY (do_stmt
), await_statement_walker
,
3225 *do_subtree
= 0; /* Done subtrees. */
3232 /* We turn 'switch (cond with awaits) stmt' into
3233 switch_type cond = cond with awaits
3234 switch (cond) stmt. */
3235 tree sw_stmt
= *stmt
;
3236 if ((res
= cp_walk_tree (&SWITCH_STMT_COND (sw_stmt
),
3237 analyze_expression_awaits
, d
, &visited
)))
3239 if (!awpts
->saw_awaits
)
3240 return NULL_TREE
; /* Nothing special to do here. */
3242 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3243 /* Build a variable to hold the condition, this will be
3244 included in the frame as a local var. */
3245 tree
& bind_expr
= awpts
->bind_stack
->last ();
3246 tree sw_type
= SWITCH_STMT_TYPE (sw_stmt
);
3247 tree newvar
= add_var_to_bind (bind_expr
, sw_type
, "swch",
3248 awpts
->cond_number
++);
3249 tree insert_list
= push_stmt_list ();
3250 add_decl_expr (newvar
);
3252 tree cond_inner
= SWITCH_STMT_COND (sw_stmt
);
3253 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3254 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3255 location_t sloc
= EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt
));
3256 tree new_s
= build2_loc (sloc
, INIT_EXPR
, sw_type
, newvar
,
3258 finish_expr_stmt (new_s
);
3259 SWITCH_STMT_COND (sw_stmt
) = newvar
;
3260 /* Now add the switch statement with the condition re-
3261 written to use the local var. */
3263 *stmt
= pop_stmt_list (insert_list
);
3264 /* Process the expanded list. */
3265 res
= cp_walk_tree (stmt
, await_statement_walker
,
3267 *do_subtree
= 0; /* Done subtrees. */
3272 else if (EXPR_P (*stmt
))
3274 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
, d
, &visited
)))
3276 *do_subtree
= 0; /* Done subtrees. */
3277 if (!awpts
->saw_awaits
)
3278 return NULL_TREE
; /* Nothing special to do here. */
3280 /* Unless we need to expand any truth-and/or-if expressions, then the
3281 remaining action is to check for temporaries to await expressions
3282 captured by refence. */
3283 if (!awpts
->needs_truth_if_exp
)
3284 return maybe_promote_captured_temps (stmt
, d
);
3286 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3287 tree
& bind_expr
= awpts
->bind_stack
->last ();
3288 /* Build a variable to hold the condition, this will be
3289 included in the frame as a local var. */
3290 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3291 "taoi", awpts
->cond_number
++);
3292 tree insert_list
= push_stmt_list ();
3293 add_decl_expr (newvar
);
3295 tree
*sp
= tsi_stmt_ptr (tsi_last (insert_list
));
3296 *stmt
= pop_stmt_list (insert_list
);
3298 truth_if_transform xf
= {sp
, newvar
, &truth_aoif_to_expand
};
3299 if ((res
= cp_walk_tree (sp
, expand_one_truth_if
, &xf
, NULL
)))
3301 /* Process the expanded trees. */
3302 return cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3305 /* Continue recursion, if needed. */
3309 /* For figuring out what param usage we have. */
3311 struct param_frame_data
3314 hash_map
<tree
, param_info
> *param_uses
;
3315 hash_set
<tree
*> *visited
;
3321 register_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
3323 param_frame_data
*data
= (param_frame_data
*) d
;
3325 /* For lambda closure content, we have to look specifically. */
3326 if (TREE_CODE (*stmt
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (*stmt
))
3328 tree t
= DECL_VALUE_EXPR (*stmt
);
3329 return cp_walk_tree (&t
, register_param_uses
, d
, NULL
);
3332 if (TREE_CODE (*stmt
) != PARM_DECL
)
3335 /* If we already saw the containing expression, then we're done. */
3336 if (data
->visited
->add (stmt
))
3340 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
3341 gcc_checking_assert (existed
);
3343 if (!parm
.body_uses
)
3345 vec_alloc (parm
.body_uses
, 4);
3346 parm
.body_uses
->quick_push (stmt
);
3347 data
->param_seen
= true;
3350 parm
.body_uses
->safe_push (stmt
);
3355 /* For figuring out what local variable usage we have. */
3357 struct local_vars_frame_data
3360 hash_map
<tree
, local_var_info
> *local_var_uses
;
3361 unsigned int nest_depth
, bind_indx
;
3364 bool local_var_seen
;
3368 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
3370 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
3372 /* As we enter a bind expression - record the vars there and then recurse.
3373 As we exit drop the nest depth.
3374 The bind index is a growing count of how many bind indices we've seen.
3375 We build a space in the frame for each local var. */
3377 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3382 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
3383 lvar
= DECL_CHAIN (lvar
))
3386 local_var_info
&local_var
3387 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
3388 gcc_checking_assert (!existed
);
3389 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
3390 tree lvtype
= TREE_TYPE (lvar
);
3391 local_var
.frame_type
= lvtype
;
3392 local_var
.field_idx
= local_var
.field_id
= NULL_TREE
;
3393 lvd
->local_var_seen
= true;
3394 /* If this var is a lambda capture proxy, we want to leave it alone,
3395 and later rewrite the DECL_VALUE_EXPR to indirect through the
3396 frame copy of the pointer to the lambda closure object. */
3397 local_var
.is_lambda_capture
= is_capture_proxy (lvar
);
3398 if (local_var
.is_lambda_capture
)
3401 /* Make names depth+index unique, so that we can support nested
3402 scopes with identically named locals. */
3403 tree lvname
= DECL_NAME (lvar
);
3405 if (lvname
!= NULL_TREE
)
3406 buf
= xasprintf ("__lv.%u.%u.%s", lvd
->bind_indx
, lvd
->nest_depth
,
3407 IDENTIFIER_POINTER (lvname
));
3409 buf
= xasprintf ("__lv.%u.%u.D%u", lvd
->bind_indx
, lvd
->nest_depth
,
3411 /* TODO: Figure out if we should build a local type that has any
3412 excess alignment or size from the original decl. */
3414 = coro_make_frame_entry (lvd
->field_list
, buf
, lvtype
, lvd
->loc
);
3416 /* We don't walk any of the local var sub-trees, they won't contain
3419 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
3420 *do_subtree
= 0; /* We've done this. */
3426 /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
3427 for either actor or destroy functions. */
3430 act_des_fn (tree orig
, tree fn_type
, tree coro_frame_ptr
, const char* name
)
3432 tree fn_name
= get_fn_local_identifier (orig
, name
);
3433 tree fn
= build_lang_decl (FUNCTION_DECL
, fn_name
, fn_type
);
3434 DECL_CONTEXT (fn
) = DECL_CONTEXT (orig
);
3435 DECL_INITIAL (fn
) = error_mark_node
;
3436 tree id
= get_identifier ("frame_ptr");
3437 tree fp
= build_lang_decl (PARM_DECL
, id
, coro_frame_ptr
);
3438 DECL_CONTEXT (fp
) = fn
;
3439 DECL_ARG_TYPE (fp
) = type_passed_as (coro_frame_ptr
);
3440 DECL_ARGUMENTS (fn
) = fp
;
3444 /* Return a bind expression if we see one, else NULL_TREE. */
3446 bind_expr_find_in_subtree (tree
*stmt
, int *, void *)
3448 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3453 /* Return the first bind expression that the sub-tree given by STMT
3457 coro_body_contains_bind_expr_p (tree
*stmt
)
3459 hash_set
<tree
> visited
;
3460 return cp_walk_tree (stmt
, bind_expr_find_in_subtree
, NULL
, &visited
);
3464 a) Check that the function and promise type are valid for a
3466 b) Carry out the initial morph to create the skeleton of the
3467 coroutine ramp function and the rewritten body.
3471 1. We only hit this code once all dependencies are resolved.
3472 2. The function body will be either a bind expr or a statement list
3473 3. That cfun and current_function_decl are valid for the case we're
3475 4. 'input_location' will be of the final brace for the function.
3477 We do something like this:
3478 declare a dummy coro frame.
3480 using handle_type = coro::coroutine_handle<coro1::promise_type>;
3481 void (*__resume)(_R_frame *);
3482 void (*__destroy)(_R_frame *);
3483 coro1::promise_type __p;
3484 bool frame_needs_free; free the coro frame mem if set.
3485 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
3487 handle_type self_handle;
3488 (maybe) parameter copies.
3489 coro1::suspend_never_prt __is;
3490 coro1::suspend_always_prt __fs;
3491 (maybe) local variables saved
3492 (maybe) trailing space.
3496 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
3498 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
3500 if (!coro_function_valid_p (orig
))
3503 /* The ramp function does return a value. */
3504 current_function_returns_value
= 1;
3506 /* We can't validly get here with an empty statement list, since there's no
3507 way for the FE to decide it's a coroutine in the absence of any code. */
3508 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
3509 if (fnbody
== NULL_TREE
)
3512 /* We don't have the locus of the opening brace - it's filled in later (and
3513 there doesn't really seem to be any easy way to get at it).
3514 The closing brace is assumed to be input_location. */
3515 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
3516 gcc_rich_location
fn_start_loc (fn_start
);
3518 /* Initial processing of the function-body.
3519 If we have no expressions or just an error then punt. */
3520 tree body_start
= expr_first (fnbody
);
3521 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
3523 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3524 append_to_statement_list (DECL_SAVED_TREE (orig
), &fnbody
);
3528 /* So, we've tied off the original body. Now start the replacement.
3529 If we encounter a fatal error we might return a now-empty body.
3530 TODO: determine if it would help to restore the original.
3531 determine if looking for more errors in coro_function_valid_p()
3532 and stashing types is a better solution. */
3534 tree newbody
= push_stmt_list ();
3535 DECL_SAVED_TREE (orig
) = newbody
;
3537 /* If our original body is noexcept, then that's what we apply to our
3538 generated functions. Remember that we're NOEXCEPT and fish out the
3539 contained list (we tied off to the top level already). */
3540 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
3543 /* Simplified abstract from begin_eh_spec_block, since we already
3544 know the outcome. */
3545 fnbody
= TREE_OPERAND (body_start
, 0); /* Stash the original... */
3546 add_stmt (body_start
); /* ... and start the new. */
3547 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
3550 /* We can be presented with a function that currently has no outer bind
3551 expression. We will insert bind scopes in expanding await expressions,
3552 and therefore need a top level to the tree, so synthesize an outer bind
3553 expression and scope. */
3554 tree check_bind
= expr_first (fnbody
);
3555 if (check_bind
&& TREE_CODE (check_bind
) != BIND_EXPR
)
3557 tree update_body
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3558 tree blk
= make_node (BLOCK
);
3559 gcc_checking_assert (!coro_body_contains_bind_expr_p (&fnbody
));
3560 BIND_EXPR_BLOCK (update_body
) = blk
;
3561 if (TREE_CODE (fnbody
) == STATEMENT_LIST
)
3562 BIND_EXPR_BODY (update_body
) = fnbody
;
3565 tree tlist
= NULL_TREE
;
3566 append_to_statement_list_force (fnbody
, &tlist
);
3567 BIND_EXPR_BODY (update_body
) = tlist
;
3569 tree new_body_list
= NULL_TREE
;
3570 append_to_statement_list_force (update_body
, &new_body_list
);
3571 fnbody
= new_body_list
;
3574 /* Create the coro frame type, as far as it can be known at this stage.
3575 1. Types we already know. */
3577 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
3578 gcc_assert (!VOID_TYPE_P (fn_return_type
));
3579 tree handle_type
= get_coroutine_handle_type (orig
);
3580 tree promise_type
= get_coroutine_promise_type (orig
);
3582 /* 2. Types we need to define or look up. */
3584 /* We need to know, and inspect, each suspend point in the function
3585 in several places. It's convenient to place this map out of line
3586 since it's used from tree walk callbacks. */
3587 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
3589 /* Initial and final suspend types are special in that the co_awaits for
3590 them are synthetic. We need to find the type for each awaiter from
3591 the coroutine promise. */
3592 tree initial_await
= build_init_or_final_await (fn_start
, false);
3593 if (initial_await
== error_mark_node
)
3595 /* The type of the frame var for this is the type of its temp proxy. */
3596 tree initial_suspend_type
= TREE_TYPE (TREE_OPERAND (initial_await
, 1));
3598 tree final_await
= build_init_or_final_await (fn_start
, true);
3599 if (final_await
== error_mark_node
)
3602 /* The type of the frame var for this is the type of its temp proxy. */
3603 tree final_suspend_type
= TREE_TYPE (TREE_OPERAND (final_await
, 1));
3605 tree fr_name
= get_fn_local_identifier (orig
, "frame");
3606 tree coro_frame_type
= xref_tag (record_type
, fr_name
, ts_current
, false);
3607 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
3608 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
3609 tree act_des_fn_type
3610 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
3611 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
3613 /* Declare the actor and destroyer function. */
3614 tree actor
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "actor");
3615 tree destroy
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "destroy");
3617 /* Build our dummy coro frame layout. */
3618 coro_frame_type
= begin_class_definition (coro_frame_type
);
3620 tree field_list
= NULL_TREE
;
3622 = coro_make_frame_entry (&field_list
, "__resume", act_des_fn_ptr
, fn_start
);
3623 tree destroy_name
= coro_make_frame_entry (&field_list
, "__destroy",
3624 act_des_fn_ptr
, fn_start
);
3626 = coro_make_frame_entry (&field_list
, "__p", promise_type
, fn_start
);
3627 tree fnf_name
= coro_make_frame_entry (&field_list
, "__frame_needs_free",
3628 boolean_type_node
, fn_start
);
3629 tree iarc_name
= coro_make_frame_entry (&field_list
, "__i_a_r_c",
3630 boolean_type_node
, fn_start
);
3631 tree resume_idx_name
3632 = coro_make_frame_entry (&field_list
, "__resume_at",
3633 short_unsigned_type_node
, fn_start
);
3635 /* We need a handle to this coroutine, which is passed to every
3636 await_suspend(). There's no point in creating it over and over. */
3637 (void) coro_make_frame_entry (&field_list
, "__self_h", handle_type
, fn_start
);
3639 /* Now add in fields for function params (if there are any).
3640 We do not attempt elision of copies at this stage, we do analyse the
3641 uses and build worklists to replace those when the state machine is
3644 hash_map
<tree
, param_info
> *param_uses
= NULL
;
3645 if (DECL_ARGUMENTS (orig
))
3647 /* Build a hash map with an entry for each param.
3648 The key is the param tree.
3649 Then we have an entry for the frame field name.
3650 Then a cache for the field ref when we come to use it.
3651 Then a tree list of the uses.
3652 The second two entries start out empty - and only get populated
3653 when we see uses. */
3654 param_uses
= new hash_map
<tree
, param_info
>;
3656 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3657 arg
= DECL_CHAIN (arg
))
3660 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3661 gcc_checking_assert (!existed
);
3662 parm
.body_uses
= NULL
;
3663 tree actual_type
= TREE_TYPE (arg
);
3664 actual_type
= complete_type_or_else (actual_type
, orig
);
3665 if (actual_type
== NULL_TREE
)
3666 actual_type
= error_mark_node
;
3667 parm
.orig_type
= actual_type
;
3668 parm
.by_ref
= parm
.rv_ref
= parm
.pt_ref
= false;
3669 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
3670 && TYPE_REF_IS_RVALUE (DECL_ARG_TYPE (arg
)))
3673 actual_type
= TREE_TYPE (actual_type
);
3674 parm
.frame_type
= actual_type
;
3676 else if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
3678 /* If the user passes by reference, then we will save the
3679 pointer to the original. As noted in
3680 [dcl.fct.def.coroutine] / 13, if the lifetime of the
3681 referenced item ends and then the coroutine is resumed,
3682 we have UB; well, the user asked for it. */
3683 actual_type
= build_pointer_type (TREE_TYPE (actual_type
));
3684 parm
.frame_type
= actual_type
;
3687 else if (TYPE_REF_P (DECL_ARG_TYPE (arg
)))
3690 parm
.frame_type
= actual_type
;
3693 parm
.frame_type
= actual_type
;
3694 parm
.this_ptr
= is_this_parameter (arg
);
3695 parm
.trivial_dtor
= TYPE_HAS_TRIVIAL_DESTRUCTOR (parm
.frame_type
);
3696 tree pname
= DECL_NAME (arg
);
3697 char *buf
= xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname
));
3698 parm
.field_id
= coro_make_frame_entry
3699 (&field_list
, buf
, actual_type
, DECL_SOURCE_LOCATION (arg
));
3703 /* We want to record every instance of param's use, so don't include
3704 a 'visited' hash_set on the tree walk, but only record a containing
3706 hash_set
<tree
*> visited
;
3707 param_frame_data param_data
3708 = {&field_list
, param_uses
, &visited
, fn_start
, false};
3709 cp_walk_tree (&fnbody
, register_param_uses
, ¶m_data
, NULL
);
3712 /* Initial suspend is mandated. */
3713 tree init_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.is",
3714 initial_suspend_type
, fn_start
);
3716 register_await_info (initial_await
, initial_suspend_type
, init_susp_name
);
3718 /* Now insert the data for any body await points, at this time we also need
3719 to promote any temporaries that are captured by reference (to regular
3720 vars) they will get added to the coro frame along with other locals. */
3721 susp_frame_data body_aw_points
3722 = {&field_list
, handle_type
, NULL
, NULL
, 0, 0,
3723 hash_set
<tree
> (), NULL
, NULL
, 0, false, false};
3724 body_aw_points
.block_stack
= make_tree_vector ();
3725 body_aw_points
.bind_stack
= make_tree_vector ();
3726 body_aw_points
.to_replace
= make_tree_vector ();
3727 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
3729 /* Final suspend is mandated. */
3730 tree fin_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.fs",
3731 final_suspend_type
, fn_start
);
3733 register_await_info (final_await
, final_suspend_type
, fin_susp_name
);
3735 /* 4. Now make space for local vars, this is conservative again, and we
3736 would expect to delete unused entries later. */
3737 hash_map
<tree
, local_var_info
> local_var_uses
;
3738 local_vars_frame_data local_vars_data
3739 = {&field_list
, &local_var_uses
, 0, 0, fn_start
, false, false};
3740 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
3742 /* Tie off the struct for now, so that we can build offsets to the
3744 TYPE_FIELDS (coro_frame_type
) = field_list
;
3745 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
3746 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
3747 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
3749 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
3752 /* Now build the ramp function pieces. */
3753 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3754 add_stmt (ramp_bind
);
3755 tree ramp_body
= push_stmt_list ();
3756 tree empty_list
= build_empty_stmt (fn_start
);
3758 tree coro_fp
= build_lang_decl (VAR_DECL
, get_identifier ("coro.frameptr"),
3760 tree varlist
= coro_fp
;
3762 /* Collected the scope vars we need ... only one for now. */
3763 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
3765 /* We're now going to create a new top level scope block for the ramp
3767 tree top_block
= make_node (BLOCK
);
3769 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
3770 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
3771 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
3773 /* The decl_expr for the coro frame pointer, initialize to zero so that we
3774 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
3775 directly apparently). This avoids a "used uninitialized" warning. */
3776 tree r
= build_stmt (fn_start
, DECL_EXPR
, coro_fp
);
3777 tree zeroinit
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3778 r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, zeroinit
);
3779 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3782 /* The CO_FRAME internal function is a mechanism to allow the middle end
3783 to adjust the allocation in response to optimisations. We provide the
3784 current conservative estimate of the frame size (as per the current)
3786 tree frame_size
= TYPE_SIZE_UNIT (coro_frame_type
);
3788 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
3789 frame_size
, coro_fp
);
3791 /* n4849 [dcl.fct.def.coroutine] / 10 (part1)
3792 The unqualified-id get_return_object_on_allocation_failure is looked up
3793 in the scope of the promise type by class member access lookup. */
3796 = lookup_promise_method (orig
, coro_gro_on_allocation_fail_identifier
,
3797 fn_start
, /*musthave=*/false);
3799 tree grooaf
= NULL_TREE
;
3800 tree dummy_promise
= build_dummy_object (get_coroutine_promise_type (orig
));
3802 /* We don't require this, so lookup_promise_method can return NULL... */
3803 if (grooaf_meth
&& BASELINK_P (grooaf_meth
))
3805 /* ... but, if the lookup succeeds, then the function must be
3807 build_new_method_call () wants a valid pointer to (an empty) args
3808 list in this case. */
3809 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3810 grooaf
= build_new_method_call (dummy_promise
, grooaf_meth
, &args
,
3811 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
3812 tf_warning_or_error
);
3813 release_tree_vector (args
);
3816 /* Allocate the frame, this has several possibilities:
3817 n4849 [dcl.fct.def.coroutine] / 9 (part 1)
3818 The allocation function’s name is looked up in the scope of the promise
3819 type. It's not a failure for it to be absent see part 4, below. */
3820 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
3821 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
3822 /*musthave=*/false);
3823 tree new_fn
= NULL_TREE
;
3824 if (fns
&& BASELINK_P (fns
))
3826 /* n4849 [dcl.fct.def.coroutine] / 9 (part 2)
3827 If the lookup finds an allocation function in the scope of the promise
3828 type, overload resolution is performed on a function call created by
3829 assembling an argument list. The first argument is the amount of space
3830 requested, and has type std::size_t. The succeeding arguments are
3831 those of the original function. */
3832 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3833 vec_safe_push (args
, resizeable
); /* Space needed. */
3834 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3835 arg
= DECL_CHAIN (arg
))
3836 vec_safe_push (args
, arg
);
3838 /* We might need to check that the provided function is nothrow. */
3840 /* Failure is OK for the first attempt. */
3841 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
, NULL
,
3842 LOOKUP_NORMAL
, &func
, tf_none
);
3843 release_tree_vector (args
);
3845 if (!new_fn
|| new_fn
== error_mark_node
)
3847 /* n4849 [dcl.fct.def.coroutine] / 9 (part 3)
3848 If no viable function is found, overload resolution is performed
3849 again on a function call created by passing just the amount of
3850 space required as an argument of type std::size_t. */
3851 args
= make_tree_vector ();
3852 vec_safe_push (args
, resizeable
); /* Space needed. */
3853 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
,
3854 NULL_TREE
, LOOKUP_NORMAL
, &func
,
3856 release_tree_vector (args
);
3859 /* However, if the initial lookup succeeded, then one of these two
3860 options must be available. */
3861 if (!new_fn
|| new_fn
== error_mark_node
)
3863 error_at (fn_start
, "%qE is provided by %qT but is not usable with"
3864 " the function signature %qD", nwname
, promise_type
, orig
);
3865 new_fn
= error_mark_node
;
3867 else if (grooaf
&& !TYPE_NOTHROW_P (TREE_TYPE (func
)))
3868 error_at (fn_start
, "%qE is provided by %qT but %qE is not marked"
3869 " %<throw()%> or %<noexcept%>", grooaf
, promise_type
, nwname
);
3873 /* n4849 [dcl.fct.def.coroutine] / 9 (part 4)
3874 If this lookup fails, the allocation function’s name is looked up in
3875 the global scope. */
3877 vec
<tree
, va_gc
> *args
;
3878 /* build_operator_new_call () will insert size needed as element 0 of
3879 this, and we might need to append the std::nothrow constant. */
3880 vec_alloc (args
, 2);
3884 /* n4849 [dcl.fct.def.coroutine] / 10 (part 2)
3885 If any declarations (of the get return on allocation fail) are
3886 found, then the result of a call to an allocation function used
3887 to obtain storage for the coroutine state is assumed to return
3888 nullptr if it fails to obtain storage and, if a global allocation
3889 function is selected, the ::operator new(size_t, nothrow_t) form
3890 is used. The allocation function used in this case shall have a
3891 non-throwing noexcept-specification. So we need std::nothrow. */
3892 tree std_nt
= lookup_qualified_name (std_node
,
3893 get_identifier ("nothrow"),
3894 0, /*complain=*/true, false);
3895 vec_safe_push (args
, std_nt
);
3898 /* If we get to this point, we must succeed in looking up the global
3899 operator new for the params provided. Extract a simplified version
3900 of the machinery from build_operator_new_call. This can update the
3903 new_fn
= build_operator_new_call (nwname
, &args
, &frame_size
, &cookie
,
3905 /*size_check=*/NULL
, /*fn=*/NULL
,
3906 tf_warning_or_error
);
3907 resizeable
= build_call_expr_internal_loc
3908 (fn_start
, IFN_CO_FRAME
, size_type_node
, 2, frame_size
, coro_fp
);
3909 CALL_EXPR_ARG (new_fn
, 0) = resizeable
;
3911 release_tree_vector (args
);
3914 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
3915 r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, allocated
);
3916 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3919 /* If the user provided a method to return an object on alloc fail, then
3920 check the returned pointer and call the func if it's null.
3921 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
3925 /* n4849 [dcl.fct.def.coroutine] / 10 (part 3)
3926 If the allocation function returns nullptr,the coroutine returns
3927 control to the caller of the coroutine and the return value is
3928 obtained by a call to T::get_return_object_on_allocation_failure(),
3929 where T is the promise type. */
3931 = create_named_label_with_ctx (fn_start
, "coro.frame.active",
3933 tree early_ret_list
= NULL
;
3934 /* init the retval using the user's func. */
3935 r
= build2 (INIT_EXPR
, TREE_TYPE (DECL_RESULT (orig
)), DECL_RESULT (orig
),
3937 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3938 append_to_statement_list (r
, &early_ret_list
);
3939 /* We know it's the correct type. */
3940 r
= DECL_RESULT (orig
);
3941 r
= build_stmt (fn_start
, RETURN_EXPR
, r
);
3942 TREE_NO_WARNING (r
) |= 1;
3943 r
= maybe_cleanup_point_expr_void (r
);
3944 append_to_statement_list (r
, &early_ret_list
);
3946 tree goto_st
= NULL
;
3947 r
= build1 (GOTO_EXPR
, void_type_node
, cfra_label
);
3948 append_to_statement_list (r
, &goto_st
);
3950 tree ckk
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3951 tree ckz
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, ckk
);
3952 r
= build3 (COND_EXPR
, void_type_node
, ckz
, early_ret_list
, empty_list
);
3955 cfra_label
= build_stmt (fn_start
, LABEL_EXPR
, cfra_label
);
3956 add_stmt (cfra_label
);
3959 /* deref the frame pointer, to use in member access code. */
3960 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
3962 /* For now, once allocation has succeeded we always assume that this needs
3963 destruction, there's no impl. for frame allocation elision. */
3965 = lookup_member (coro_frame_type
, fnf_name
, 1, 0, tf_warning_or_error
);
3966 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
3967 false, tf_warning_or_error
);
3968 r
= build2 (INIT_EXPR
, boolean_type_node
, fnf_x
, boolean_true_node
);
3969 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3972 /* Put the resumer and destroyer functions in. */
3974 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
3976 = lookup_member (coro_frame_type
, resume_name
,
3977 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
3978 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
3979 false, tf_warning_or_error
);
3980 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, resume_x
, actor_addr
);
3981 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3984 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
3986 = lookup_member (coro_frame_type
, destroy_name
,
3987 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
3989 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
3990 tf_warning_or_error
);
3991 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, destroy_x
, destroy_addr
);
3992 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3995 /* n4849 [dcl.fct.def.coroutine] /13
3996 When a coroutine is invoked, a copy is created for each coroutine
3997 parameter. Each such copy is an object with automatic storage duration
3998 that is direct-initialized from an lvalue referring to the corresponding
3999 parameter if the parameter is an lvalue reference, and from an xvalue
4000 referring to it otherwise. A reference to a parameter in the function-
4001 body of the coroutine and in the call to the coroutine promise
4002 constructor is replaced by a reference to its copy. */
4004 vec
<tree
, va_gc
> *promise_args
= NULL
; /* So that we can adjust refs. */
4006 /* The initialization and destruction of each parameter copy occurs in the
4007 context of the called coroutine. Initializations of parameter copies are
4008 sequenced before the call to the coroutine promise constructor and
4009 indeterminately sequenced with respect to each other. The lifetime of
4010 parameter copies ends immediately after the lifetime of the coroutine
4011 promise object ends. */
4013 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
4015 if (DECL_ARGUMENTS (orig
))
4017 promise_args
= make_tree_vector ();
4018 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4019 arg
= DECL_CHAIN (arg
))
4022 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4024 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
4025 /*protect=*/1, /*want_type=*/0,
4026 tf_warning_or_error
);
4028 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
4029 false, tf_warning_or_error
);
4031 /* Add this to the promise CTOR arguments list, accounting for
4032 refs and this ptr. */
4035 /* We pass a reference to *this to the param preview. */
4036 tree tt
= TREE_TYPE (arg
);
4037 gcc_checking_assert (POINTER_TYPE_P (tt
));
4038 tree ct
= TREE_TYPE (tt
);
4039 tree this_ref
= build1 (INDIRECT_REF
, ct
, arg
);
4040 tree rt
= cp_build_reference_type (ct
, false);
4041 this_ref
= convert_to_reference (rt
, this_ref
, CONV_STATIC
,
4042 LOOKUP_NORMAL
, NULL_TREE
,
4043 tf_warning_or_error
);
4044 vec_safe_push (promise_args
, this_ref
);
4046 else if (parm
.by_ref
)
4047 vec_safe_push (promise_args
, fld_idx
);
4048 else if (parm
.rv_ref
)
4049 vec_safe_push (promise_args
, rvalue (fld_idx
));
4051 vec_safe_push (promise_args
, arg
);
4053 if (TYPE_NEEDS_CONSTRUCTING (parm
.frame_type
))
4055 vec
<tree
, va_gc
> *p_in
;
4057 && classtype_has_non_deleted_move_ctor (parm
.frame_type
)
4058 && !classtype_has_non_deleted_copy_ctor (parm
.frame_type
))
4059 p_in
= make_tree_vector_single (rvalue (arg
));
4061 p_in
= make_tree_vector_single (arg
);
4062 /* Construct in place or move as relevant. */
4063 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
4064 &p_in
, parm
.frame_type
,
4066 tf_warning_or_error
);
4067 release_tree_vector (p_in
);
4072 r
= convert_from_reference (arg
);
4073 else if (!same_type_p (parm
.frame_type
, DECL_ARG_TYPE (arg
)))
4074 r
= build1_loc (DECL_SOURCE_LOCATION (arg
), CONVERT_EXPR
,
4075 parm
.frame_type
, arg
);
4078 r
= build_modify_expr (fn_start
, fld_idx
, parm
.frame_type
,
4079 INIT_EXPR
, DECL_SOURCE_LOCATION (arg
), r
,
4082 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4084 if (!parm
.trivial_dtor
)
4086 if (param_dtor_list
== NULL
)
4087 param_dtor_list
= make_tree_vector ();
4088 vec_safe_push (param_dtor_list
, parm
.field_id
);
4093 /* Set up the promise. */
4095 = lookup_member (coro_frame_type
, promise_name
,
4096 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4098 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
4099 false, tf_warning_or_error
);
4101 if (TYPE_NEEDS_CONSTRUCTING (promise_type
))
4103 /* Do a placement new constructor for the promise type (we never call
4104 the new operator, just the constructor on the object in place in the
4107 First try to find a constructor with the same parameter list as the
4108 original function (if it has params), failing that find a constructor
4109 with no parameter list. */
4111 if (DECL_ARGUMENTS (orig
))
4113 r
= build_special_member_call (p
, complete_ctor_identifier
,
4114 &promise_args
, promise_type
,
4115 LOOKUP_NORMAL
, tf_none
);
4116 release_tree_vector (promise_args
);
4121 if (r
== NULL_TREE
|| r
== error_mark_node
)
4122 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
4123 promise_type
, LOOKUP_NORMAL
,
4124 tf_warning_or_error
);
4126 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4130 /* Set up a new bind context for the GRO. */
4131 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4132 /* Make and connect the scope blocks. */
4133 tree gro_block
= make_node (BLOCK
);
4134 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
4135 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
4136 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
4137 add_stmt (gro_context_bind
);
4139 tree gro_meth
= lookup_promise_method (orig
,
4140 coro_get_return_object_identifier
,
4141 fn_start
, /*musthave=*/true );
4143 = build_new_method_call (p
, gro_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
4144 tf_warning_or_error
);
4145 /* Without a return object we haven't got much clue what's going on. */
4146 if (get_ro
== error_mark_node
)
4148 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4149 DECL_SAVED_TREE (orig
) = newbody
;
4153 tree gro_context_body
= push_stmt_list ();
4154 tree gro
= build_lang_decl (VAR_DECL
, get_identifier ("coro.gro"),
4155 TREE_TYPE (get_ro
));
4156 DECL_CONTEXT (gro
) = current_scope ();
4157 add_decl_expr (gro
);
4158 tree gro_bind_vars
= gro
;
4160 /* We have to sequence the call to get_return_object before initial
4162 r
= build2_loc (fn_start
, INIT_EXPR
, TREE_TYPE (gro
), gro
, get_ro
);
4163 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4166 /* Initialize the resume_idx_name to 0, meaning "not started". */
4168 = lookup_member (coro_frame_type
, resume_idx_name
,
4169 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4171 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
4172 tf_warning_or_error
);
4173 r
= build_int_cst (short_unsigned_type_node
, 0);
4174 r
= build2_loc (fn_start
, INIT_EXPR
, short_unsigned_type_node
, resume_idx
, r
);
4175 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4178 /* Initialize 'initial-await-resume-called' as per
4179 [dcl.fct.def.coroutine] / 5.3 */
4181 = lookup_member (coro_frame_type
, iarc_name
, 1, 0, tf_warning_or_error
);
4182 tree i_a_r_c
= build_class_member_access_expr (deref_fp
, i_a_r_c_m
,
4184 tf_warning_or_error
);
4185 r
= build2 (INIT_EXPR
, boolean_type_node
, i_a_r_c
, boolean_false_node
);
4186 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4189 /* So .. call the actor .. */
4190 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
4191 r
= maybe_cleanup_point_expr_void (r
);
4194 /* Switch to using 'input_location' as the loc, since we're now more
4195 logically doing things related to the end of the function. */
4197 /* The ramp is done, we just need the return value. */
4198 if (!same_type_p (TREE_TYPE (get_ro
), fn_return_type
))
4200 /* construct the return value with a single GRO param. */
4201 vec
<tree
, va_gc
> *args
= make_tree_vector_single (gro
);
4202 r
= build_special_member_call (NULL_TREE
,
4203 complete_ctor_identifier
, &args
,
4204 fn_return_type
, LOOKUP_NORMAL
,
4205 tf_warning_or_error
);
4206 r
= build_cplus_new (fn_return_type
, r
, tf_warning_or_error
);
4209 r
= rvalue (gro
); /* The GRO is the return value. */
4211 finish_return_stmt (r
);
4213 /* Finish up the ramp function. */
4214 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
4215 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
4216 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4218 /* We know the "real" promise and have a frame layout with a slot for each
4219 suspend point, so we can build an actor function (which contains the
4220 functionality for both 'resume' and 'destroy').
4222 wrap the function body in a try {} catch (...) {} block, if exceptions
4225 /* First make a new block for the body - that will be embedded in the
4226 re-written function. */
4227 tree first
= expr_first (fnbody
);
4228 bool orig_fn_has_outer_bind
= false;
4229 tree replace_blk
= NULL_TREE
;
4230 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
4232 orig_fn_has_outer_bind
= true;
4233 tree block
= BIND_EXPR_BLOCK (first
);
4234 replace_blk
= make_node (BLOCK
);
4235 if (block
) /* missing block is probably an error. */
4237 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
4238 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
4239 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
4240 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
4241 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
4242 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
4244 BIND_EXPR_BLOCK (first
) = replace_blk
;
4247 /* actor's version of the promise. */
4248 tree actor_frame
= build1_loc (fn_start
, INDIRECT_REF
, coro_frame_type
,
4249 DECL_ARGUMENTS (actor
));
4250 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
4251 tf_warning_or_error
);
4252 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
,
4253 false, tf_warning_or_error
);
4255 /* Now we've built the promise etc, process fnbody for co_returns.
4256 We want the call to return_void () below and it has no params so
4257 we can create it once here.
4258 Calls to return_value () will have to be checked and created as
4261 tree return_void
= NULL_TREE
;
4263 = lookup_promise_method (orig
, coro_return_void_identifier
, fn_start
,
4264 /*musthave=*/false);
4265 if (rvm
&& rvm
!= error_mark_node
)
4267 = build_new_method_call (ap
, rvm
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
4268 tf_warning_or_error
);
4270 /* [stmt.return.coroutine] (2.2 : 3) if p.return_void() is a valid
4271 expression, flowing off the end of a coroutine is equivalent to
4272 co_return; otherwise UB.
4273 We just inject the call to p.return_void() here, and fall through to
4274 the final_suspend: label (eliding the goto). If the function body has
4275 a co_return, then this statement will be unreachable and DCEd. */
4276 if (return_void
!= NULL_TREE
)
4278 tree append
= push_stmt_list ();
4280 add_stmt (return_void
);
4281 fnbody
= pop_stmt_list(append
);
4284 if (flag_exceptions
)
4287 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
4288 fn_start
, /*musthave=*/true);
4289 /* Build promise.unhandled_exception(); */
4291 = build_new_method_call (ap
, ueh_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
4292 NULL
, tf_warning_or_error
);
4294 /* The try block is just the original function, there's no real
4295 need to call any function to do this. */
4296 fnbody
= build_stmt (fn_start
, TRY_BLOCK
, fnbody
, NULL_TREE
);
4297 TRY_HANDLERS (fnbody
) = push_stmt_list ();
4298 /* Mimic what the parser does for the catch. */
4299 tree handler
= begin_handler ();
4300 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
4302 /* Get the initial await resume called value. */
4303 tree i_a_r_c
= build_class_member_access_expr (actor_frame
, i_a_r_c_m
,
4305 tf_warning_or_error
);
4306 tree not_iarc_if
= begin_if_stmt ();
4307 tree not_iarc
= build1_loc (fn_start
, TRUTH_NOT_EXPR
,
4308 boolean_type_node
, i_a_r_c
);
4309 finish_if_stmt_cond (not_iarc
, not_iarc_if
);
4310 /* If the initial await resume called value is false, rethrow... */
4311 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
4312 TREE_NO_WARNING (rethrow
) = true;
4313 finish_expr_stmt (rethrow
);
4314 finish_then_clause (not_iarc_if
);
4315 tree iarc_scope
= IF_SCOPE (not_iarc_if
);
4316 IF_SCOPE (not_iarc_if
) = NULL
;
4317 not_iarc_if
= do_poplevel (iarc_scope
);
4318 add_stmt (not_iarc_if
);
4319 /* ... else call the promise unhandled exception method. */
4320 ueh
= maybe_cleanup_point_expr_void (ueh
);
4322 finish_handler (handler
);
4323 TRY_HANDLERS (fnbody
) = pop_stmt_list (TRY_HANDLERS (fnbody
));
4324 /* If the function starts with a BIND_EXPR, then we need to create
4325 one here to contain the try-catch and to link up the scopes. */
4326 if (orig_fn_has_outer_bind
)
4328 fnbody
= build3 (BIND_EXPR
, void_type_node
, NULL
, fnbody
, NULL
);
4329 /* Make and connect the scope blocks. */
4330 tree tcb_block
= make_node (BLOCK
);
4331 /* .. and connect it here. */
4332 BLOCK_SUPERCONTEXT (replace_blk
) = tcb_block
;
4333 BLOCK_SUBBLOCKS (tcb_block
) = replace_blk
;
4334 BIND_EXPR_BLOCK (fnbody
) = tcb_block
;
4339 /* We still try to look for the promise method and warn if it's not
4342 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
4343 fn_start
, /*musthave=*/false);
4344 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
4345 warning_at (fn_start
, 0, "no member named %qE in %qT",
4346 coro_unhandled_exception_identifier
,
4347 get_coroutine_promise_type (orig
));
4349 /* Else we don't check and don't care if the method is missing. */
4351 /* Start to build the final functions.
4353 We push_deferring_access_checks to avoid these routines being seen as
4354 nested by the middle end; we are doing the outlining here. */
4356 push_deferring_access_checks (dk_no_check
);
4358 /* Build the actor... */
4359 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
, param_uses
,
4360 &local_var_uses
, param_dtor_list
, initial_await
, final_await
,
4361 body_aw_points
.await_number
, frame_size
);
4364 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
4366 pop_deferring_access_checks ();
4368 DECL_SAVED_TREE (orig
) = newbody
;
4369 /* Link our new functions into the list. */
4370 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
4371 TREE_CHAIN (actor
) = destroy
;
4372 TREE_CHAIN (orig
) = actor
;
4375 *destroyer
= destroy
;
4377 delete suspend_points
;
4378 suspend_points
= NULL
;
4382 #include "gt-cp-coroutines.h"