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 tree return_void
; /* The expression for p.return_void() if it exists. */
92 location_t first_coro_keyword
; /* The location of the keyword that made this
93 function into a coroutine. */
94 /* Flags to avoid repeated errors for per-function issues. */
95 bool coro_ret_type_error_emitted
;
96 bool coro_promise_error_emitted
;
97 bool coro_co_return_error_emitted
;
100 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
102 typedef tree compare_type
; /* We only compare the function decl. */
103 static inline hashval_t
hash (coroutine_info
*);
104 static inline hashval_t
hash (const compare_type
&);
105 static inline bool equal (coroutine_info
*, coroutine_info
*);
106 static inline bool equal (coroutine_info
*, const compare_type
&);
109 /* This table holds all the collected coroutine state for coroutines in
110 the current translation unit. */
112 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
114 /* We will initialize state lazily. */
115 static bool coro_initialized
= false;
117 /* Return a hash value for the entry pointed to by INFO.
118 The compare type is a tree, but the only trees we are going use are
119 function decls. We use the DECL_UID as the hash value since that is
120 stable across PCH. */
123 coroutine_info_hasher::hash (coroutine_info
*info
)
125 return DECL_UID (info
->function_decl
);
128 /* Return a hash value for the compare value COMP. */
131 coroutine_info_hasher::hash (const compare_type
& comp
)
133 return DECL_UID (comp
);
136 /* Return true if the entries pointed to by LHS and RHS are for the
140 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
142 return lhs
->function_decl
== rhs
->function_decl
;
146 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
148 return lhs
->function_decl
== rhs
;
151 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
152 entry does not yet exist. */
155 get_or_insert_coroutine_info (tree fn_decl
)
157 gcc_checking_assert (coroutine_info_table
!= NULL
);
159 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
160 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
164 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
165 (*slot
)->function_decl
= fn_decl
;
171 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
174 get_coroutine_info (tree fn_decl
)
176 if (coroutine_info_table
== NULL
)
179 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
180 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
186 /* We will lazily create all the identifiers that are used by coroutines
187 on the first attempt to lookup the traits. */
189 /* Identifiers that are used by all coroutines. */
191 static GTY(()) tree coro_traits_identifier
;
192 static GTY(()) tree coro_handle_identifier
;
193 static GTY(()) tree coro_promise_type_identifier
;
195 /* Required promise method name identifiers. */
197 static GTY(()) tree coro_await_transform_identifier
;
198 static GTY(()) tree coro_initial_suspend_identifier
;
199 static GTY(()) tree coro_final_suspend_identifier
;
200 static GTY(()) tree coro_return_void_identifier
;
201 static GTY(()) tree coro_return_value_identifier
;
202 static GTY(()) tree coro_yield_value_identifier
;
203 static GTY(()) tree coro_resume_identifier
;
204 static GTY(()) tree coro_address_identifier
;
205 static GTY(()) tree coro_from_address_identifier
;
206 static GTY(()) tree coro_get_return_object_identifier
;
207 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
208 static GTY(()) tree coro_unhandled_exception_identifier
;
210 /* Awaitable methods. */
212 static GTY(()) tree coro_await_ready_identifier
;
213 static GTY(()) tree coro_await_suspend_identifier
;
214 static GTY(()) tree coro_await_resume_identifier
;
216 /* Create the identifiers used by the coroutines library interfaces. */
219 coro_init_identifiers ()
221 coro_traits_identifier
= get_identifier ("coroutine_traits");
222 coro_handle_identifier
= get_identifier ("coroutine_handle");
223 coro_promise_type_identifier
= get_identifier ("promise_type");
225 coro_await_transform_identifier
= get_identifier ("await_transform");
226 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
227 coro_final_suspend_identifier
= get_identifier ("final_suspend");
228 coro_return_void_identifier
= get_identifier ("return_void");
229 coro_return_value_identifier
= get_identifier ("return_value");
230 coro_yield_value_identifier
= get_identifier ("yield_value");
231 coro_resume_identifier
= get_identifier ("resume");
232 coro_address_identifier
= get_identifier ("address");
233 coro_from_address_identifier
= get_identifier ("from_address");
234 coro_get_return_object_identifier
= get_identifier ("get_return_object");
235 coro_gro_on_allocation_fail_identifier
=
236 get_identifier ("get_return_object_on_allocation_failure");
237 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
239 coro_await_ready_identifier
= get_identifier ("await_ready");
240 coro_await_suspend_identifier
= get_identifier ("await_suspend");
241 coro_await_resume_identifier
= get_identifier ("await_resume");
244 /* Trees we only need to set up once. */
246 static GTY(()) tree coro_traits_templ
;
247 static GTY(()) tree coro_handle_templ
;
248 static GTY(()) tree void_coro_handle_type
;
250 /* ================= Parse, Semantics and Type checking ================= */
252 /* This initial set of routines are helper for the parsing and template
255 At the completion of this, we will have completed trees for each of the
256 keywords, but making use of proxy variables for the self-handle and the
257 promise class instance. */
259 /* [coroutine.traits]
260 Lookup the coroutine_traits template decl. */
263 find_coro_traits_template_decl (location_t kw
)
265 /* If we are missing fundamental information, such as the traits, (or the
266 declaration found is not a type template), then don't emit an error for
267 every keyword in a TU, just do it once. */
268 static bool traits_error_emitted
= false;
270 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
272 /*complain=*/!traits_error_emitted
);
273 if (traits_decl
== error_mark_node
274 || !DECL_TYPE_TEMPLATE_P (traits_decl
))
276 if (!traits_error_emitted
)
278 gcc_rich_location
richloc (kw
);
279 error_at (&richloc
, "coroutines require a traits template; cannot"
280 " find %<%E::%E%>", std_node
, coro_traits_identifier
);
281 inform (&richloc
, "perhaps %<#include <coroutine>%> is missing");
282 traits_error_emitted
= true;
290 /* Instantiate Coroutine traits for the function signature. */
293 instantiate_coro_traits (tree fndecl
, location_t kw
)
295 /* [coroutine.traits.primary]
296 So now build up a type list for the template <typename _R, typename...>.
297 The types are the function's arg types and _R is the function return
300 tree functyp
= TREE_TYPE (fndecl
);
301 tree arg
= DECL_ARGUMENTS (fndecl
);
302 tree arg_node
= TYPE_ARG_TYPES (functyp
);
303 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
306 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
308 if (is_this_parameter (arg
)
309 || DECL_NAME (arg
) == closure_identifier
)
311 /* We pass a reference to *this to the param preview. */
312 tree ct
= TREE_TYPE (TREE_TYPE (arg
));
313 TREE_VEC_ELT (argtypes
, p
++) = cp_build_reference_type (ct
, false);
316 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
318 arg_node
= TREE_CHAIN (arg_node
);
319 arg
= DECL_CHAIN (arg
);
322 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
323 SET_ARGUMENT_PACK_ARGS (argtypepack
, argtypes
);
325 tree targ
= make_tree_vec (2);
326 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
327 TREE_VEC_ELT (targ
, 1) = argtypepack
;
330 = lookup_template_class (coro_traits_templ
, targ
,
331 /*in_decl=*/NULL_TREE
, /*context=*/NULL_TREE
,
332 /*entering scope=*/false, tf_warning_or_error
);
334 if (traits_class
== error_mark_node
)
336 error_at (kw
, "cannot instantiate %<coroutine traits%>");
343 /* [coroutine.handle] */
346 find_coro_handle_template_decl (location_t kw
)
348 /* As for the coroutine traits, this error is per TU, so only emit
350 static bool coro_handle_error_emitted
= false;
351 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
353 !coro_handle_error_emitted
);
354 if (handle_decl
== error_mark_node
355 || !DECL_CLASS_TEMPLATE_P (handle_decl
))
357 if (!coro_handle_error_emitted
)
358 error_at (kw
, "coroutines require a handle class template;"
359 " cannot find %<%E::%E%>", std_node
, coro_handle_identifier
);
360 coro_handle_error_emitted
= true;
367 /* Instantiate the handle template for a given promise type. */
370 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
372 /* So now build up a type list for the template, one entry, the promise. */
373 tree targ
= make_tree_vec (1);
374 TREE_VEC_ELT (targ
, 0) = promise_type
;
376 = lookup_template_class (coro_handle_identifier
, targ
,
377 /* in_decl=*/NULL_TREE
,
378 /* context=*/std_node
,
379 /* entering scope=*/false, tf_warning_or_error
);
381 if (handle_type
== error_mark_node
)
383 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
384 " promise type %qT", promise_type
);
391 /* Look for the promise_type in the instantiated traits. */
394 find_promise_type (tree traits_class
)
397 = lookup_member (traits_class
, coro_promise_type_identifier
,
398 /* protect=*/1, /*want_type=*/true, tf_warning_or_error
);
402 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
404 /* NULL_TREE on fail. */
409 coro_promise_type_found_p (tree fndecl
, location_t loc
)
411 gcc_assert (fndecl
!= NULL_TREE
);
413 if (!coro_initialized
)
415 /* Trees we only need to create once.
416 Set up the identifiers we will use. */
417 coro_init_identifiers ();
419 /* Coroutine traits template. */
420 coro_traits_templ
= find_coro_traits_template_decl (loc
);
421 if (coro_traits_templ
== NULL_TREE
)
424 /* coroutine_handle<> template. */
425 coro_handle_templ
= find_coro_handle_template_decl (loc
);
426 if (coro_handle_templ
== NULL_TREE
)
429 /* We can also instantiate the void coroutine_handle<> */
430 void_coro_handle_type
=
431 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
432 if (void_coro_handle_type
== NULL_TREE
)
435 /* A table to hold the state, per coroutine decl. */
436 gcc_checking_assert (coroutine_info_table
== NULL
);
437 coroutine_info_table
=
438 hash_table
<coroutine_info_hasher
>::create_ggc (11);
440 if (coroutine_info_table
== NULL
)
443 coro_initialized
= true;
446 /* Save the coroutine data on the side to avoid the overhead on every
447 function decl tree. */
449 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
450 /* Without this, we cannot really proceed. */
451 gcc_checking_assert (coro_info
);
453 /* If we don't already have a current promise type, try to look it up. */
454 if (coro_info
->promise_type
== NULL_TREE
)
456 /* Get the coroutine traits template class instance for the function
457 signature we have - coroutine_traits <R, ...> */
459 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
461 /* Find the promise type for that. */
462 coro_info
->promise_type
= find_promise_type (templ_class
);
464 /* If we don't find it, punt on the rest. */
465 if (coro_info
->promise_type
== NULL_TREE
)
467 if (!coro_info
->coro_promise_error_emitted
)
468 error_at (loc
, "unable to find the promise type for"
470 coro_info
->coro_promise_error_emitted
= true;
474 /* Test for errors in the promise type that can be determined now. */
475 tree has_ret_void
= lookup_member (coro_info
->promise_type
,
476 coro_return_void_identifier
,
477 /*protect=*/1, /*want_type=*/0,
479 tree has_ret_val
= lookup_member (coro_info
->promise_type
,
480 coro_return_value_identifier
,
481 /*protect=*/1, /*want_type=*/0,
483 if (has_ret_void
&& has_ret_val
)
485 location_t ploc
= DECL_SOURCE_LOCATION (fndecl
);
486 if (!coro_info
->coro_co_return_error_emitted
)
487 error_at (ploc
, "the coroutine promise type %qT declares both"
488 " %<return_value%> and %<return_void%>",
489 coro_info
->promise_type
);
490 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void
)),
491 "%<return_void%> declared here");
492 inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_val
)),
493 "%<return_value%> declared here");
494 coro_info
->coro_co_return_error_emitted
= true;
498 /* Try to find the handle type for the promise. */
500 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
501 if (handle_type
== NULL_TREE
)
504 /* Complete this, we're going to use it. */
505 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
507 /* Diagnostic would be emitted by complete_type_or_else. */
508 if (!coro_info
->handle_type
)
511 /* Build a proxy for a handle to "self" as the param to
512 await_suspend() calls. */
513 coro_info
->self_h_proxy
514 = build_lang_decl (VAR_DECL
, get_identifier ("self_h.proxy"),
515 coro_info
->handle_type
);
517 /* Build a proxy for the promise so that we can perform lookups. */
518 coro_info
->promise_proxy
519 = build_lang_decl (VAR_DECL
, get_identifier ("promise.proxy"),
520 coro_info
->promise_type
);
522 /* Note where we first saw a coroutine keyword. */
523 coro_info
->first_coro_keyword
= loc
;
529 /* These functions assumes that the caller has verified that the state for
530 the decl has been initialized, we try to minimize work here. */
533 get_coroutine_promise_type (tree decl
)
535 if (coroutine_info
*info
= get_coroutine_info (decl
))
536 return info
->promise_type
;
542 get_coroutine_handle_type (tree decl
)
544 if (coroutine_info
*info
= get_coroutine_info (decl
))
545 return info
->handle_type
;
551 get_coroutine_self_handle_proxy (tree decl
)
553 if (coroutine_info
*info
= get_coroutine_info (decl
))
554 return info
->self_h_proxy
;
560 get_coroutine_promise_proxy (tree decl
)
562 if (coroutine_info
*info
= get_coroutine_info (decl
))
563 return info
->promise_proxy
;
569 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
572 tree promise
= get_coroutine_promise_type (fndecl
);
574 = lookup_member (promise
, member_id
,
575 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
576 if (musthave
&& pm_memb
== NULL_TREE
)
578 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
579 return error_mark_node
;
584 /* Build an expression of the form p.method (args) where the p is a promise
585 object for the current coroutine.
586 OBJECT is the promise object instance to use, it may be NULL, in which case
587 we will use the promise_proxy instance for this coroutine.
588 ARGS may be NULL, for empty parm lists. */
591 coro_build_promise_expression (tree fn
, tree promise_obj
, tree member_id
,
592 location_t loc
, vec
<tree
, va_gc
> **args
,
595 tree meth
= lookup_promise_method (fn
, member_id
, loc
, musthave
);
596 if (meth
== error_mark_node
)
597 return error_mark_node
;
599 /* If we don't find it, and it isn't needed, an empty return is OK. */
604 = promise_obj
? promise_obj
605 : get_coroutine_promise_proxy (current_function_decl
);
607 if (BASELINK_P (meth
))
608 expr
= build_new_method_call (promise
, meth
, args
, NULL_TREE
,
609 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
612 expr
= build_class_member_access_expr (promise
, meth
, NULL_TREE
,
613 true, tf_warning_or_error
);
614 vec
<tree
, va_gc
> *real_args
;
616 real_args
= make_tree_vector ();
619 expr
= build_op_call (expr
, &real_args
, tf_warning_or_error
);
624 /* Caching get for the expression p.return_void (). */
627 get_coroutine_return_void_expr (tree decl
, location_t loc
, bool musthave
)
629 if (coroutine_info
*info
= get_coroutine_info (decl
))
631 /* If we don't have it try to build it. */
632 if (!info
->return_void
)
634 = coro_build_promise_expression (current_function_decl
, NULL
,
635 coro_return_void_identifier
,
636 loc
, NULL
, musthave
);
637 /* Don't return an error if it's an optional call. */
638 if (!musthave
&& info
->return_void
== error_mark_node
)
640 return info
->return_void
;
642 return musthave
? error_mark_node
: NULL_TREE
;
645 /* Lookup an Awaitable member, which should be await_ready, await_suspend
649 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
652 = lookup_member (await_type
, member_id
,
653 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
654 if (aw_memb
== NULL_TREE
)
656 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
657 return error_mark_node
;
662 /* Here we check the constraints that are common to all keywords (since the
663 presence of a coroutine keyword makes the function into a coroutine). */
666 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
669 if (fndecl
== NULL_TREE
)
671 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
675 /* This is arranged in order of prohibitions in the std. */
676 if (DECL_MAIN_P (fndecl
))
678 /* [basic.start.main] 3. The function main shall not be a coroutine. */
679 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
684 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
686 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
687 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
689 cp_function_chain
->invalid_constexpr
= true;
693 if (FNDECL_USED_AUTO (fndecl
))
695 /* [dcl.spec.auto] 15. A function declared with a return type that uses
696 a placeholder type shall not be a coroutine. */
698 "%qs cannot be used in a function with a deduced return type",
703 if (varargs_function_p (fndecl
))
705 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
706 coroutine shall not terminate with an ellipsis that is not part
707 of a parameter-declaration. */
709 "%qs cannot be used in a varargs function", kw_name
);
713 if (DECL_CONSTRUCTOR_P (fndecl
))
715 /* [class.ctor] 7. a constructor shall not be a coroutine. */
716 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
720 if (DECL_DESTRUCTOR_P (fndecl
))
722 /* [class.dtor] 21. a destructor shall not be a coroutine. */
723 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
730 /* Here we check the constraints that are not per keyword. */
733 coro_function_valid_p (tree fndecl
)
735 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
737 /* For cases where fundamental information cannot be found, e.g. the
738 coroutine traits are missing, we need to punt early. */
739 if (!coro_promise_type_found_p (fndecl
, f_loc
))
742 /* Since we think the function is a coroutine, that implies we parsed
743 a keyword that triggered this. Keywords check promise validity for
744 their context and thus the promise type should be known at this point. */
745 if (get_coroutine_handle_type (fndecl
) == NULL_TREE
746 || get_coroutine_promise_type (fndecl
) == NULL_TREE
)
749 if (current_function_returns_value
|| current_function_returns_null
)
751 /* TODO: record or extract positions of returns (and the first coro
752 keyword) so that we can add notes to the diagnostic about where
753 the bad keyword is and what made the function into a coro. */
754 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
755 " did you mean %<co_return%>?");
762 enum suspend_point_kind
{
763 CO_AWAIT_SUSPEND_POINT
= 0,
764 CO_YIELD_SUSPEND_POINT
,
765 INITIAL_SUSPEND_POINT
,
769 /* Helper function to build a named variable for the temps we use for each
770 await point. The root of the name is determined by SUSPEND_KIND, and
771 the variable is of type V_TYPE. The awaitable number is reset each time
772 we encounter a final suspend. */
775 get_awaitable_var (suspend_point_kind suspend_kind
, tree v_type
)
779 switch (suspend_kind
)
781 default: buf
= xasprintf ("Aw%d", awn
++); break;
782 case CO_YIELD_SUSPEND_POINT
: buf
= xasprintf ("Yd%d", awn
++); break;
783 case INITIAL_SUSPEND_POINT
: buf
= xasprintf ("Is"); break;
784 case FINAL_SUSPEND_POINT
: buf
= xasprintf ("Fs"); awn
= 0; break;
786 tree ret
= get_identifier (buf
);
788 ret
= build_lang_decl (VAR_DECL
, ret
, v_type
);
789 DECL_ARTIFICIAL (ret
) = true;
793 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
794 It is also used to build the initial and final suspend points.
796 'a', 'o' and 'e' are used as per the description in the section noted.
798 A, the original yield/await expr, is found at source location LOC.
800 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
801 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
804 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
806 /* Try and overload of operator co_await, .... */
808 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
810 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
811 NULL_TREE
, NULL
, tf_warning_or_error
);
812 /* If no viable functions are found, o is a. */
813 if (!o
|| o
== error_mark_node
)
817 o
= a
; /* This is most likely about to fail anyway. */
819 tree o_type
= TREE_TYPE (o
);
820 if (o_type
&& !VOID_TYPE_P (o_type
))
821 o_type
= complete_type_or_else (o_type
, o
);
824 return error_mark_node
;
826 if (TREE_CODE (o_type
) != RECORD_TYPE
)
828 error_at (loc
, "awaitable type %qT is not a structure",
830 return error_mark_node
;
833 /* Check for required awaitable members and their types. */
835 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
836 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
837 return error_mark_node
;
839 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
840 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
841 return error_mark_node
;
843 /* The type of the co_await is the return type of the awaitable's
844 await_resume, so we need to look that up. */
846 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
847 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
848 return error_mark_node
;
850 /* To complete the lookups, we need an instance of 'e' which is built from
851 'o' according to [expr.await] 3.4.
853 If we need to materialize this as a temporary, then that will have to be
854 'promoted' to a coroutine frame var. However, if the awaitable is a
855 user variable, parameter or comes from a scope outside this function,
856 then we must use it directly - or we will see unnecessary copies.
858 If o is a variable, find the underlying var. */
859 tree e_proxy
= STRIP_NOPS (o
);
860 if (INDIRECT_REF_P (e_proxy
))
861 e_proxy
= TREE_OPERAND (e_proxy
, 0);
862 while (TREE_CODE (e_proxy
) == COMPONENT_REF
)
864 e_proxy
= TREE_OPERAND (e_proxy
, 0);
865 if (INDIRECT_REF_P (e_proxy
))
866 e_proxy
= TREE_OPERAND (e_proxy
, 0);
867 if (TREE_CODE (e_proxy
) == CALL_EXPR
)
869 /* We could have operator-> here too. */
870 tree op
= TREE_OPERAND (CALL_EXPR_FN (e_proxy
), 0);
871 if (DECL_OVERLOADED_OPERATOR_P (op
)
872 && DECL_OVERLOADED_OPERATOR_IS (op
, COMPONENT_REF
))
874 e_proxy
= CALL_EXPR_ARG (e_proxy
, 0);
875 STRIP_NOPS (e_proxy
);
876 gcc_checking_assert (TREE_CODE (e_proxy
) == ADDR_EXPR
);
877 e_proxy
= TREE_OPERAND (e_proxy
, 0);
880 STRIP_NOPS (e_proxy
);
883 /* Only build a temporary if we need it. */
884 if (TREE_CODE (e_proxy
) == PARM_DECL
885 || (VAR_P (e_proxy
) && !is_local_temp (e_proxy
)))
888 o
= NULL_TREE
; /* The var is already present. */
890 else if (CLASS_TYPE_P (o_type
) || TYPE_NEEDS_CONSTRUCTING (o_type
))
892 e_proxy
= get_awaitable_var (suspend_kind
, o_type
);
893 releasing_vec
arg (make_tree_vector_single (rvalue (o
)));
894 o
= build_special_member_call (e_proxy
, complete_ctor_identifier
,
895 &arg
, o_type
, LOOKUP_NORMAL
,
896 tf_warning_or_error
);
900 e_proxy
= get_awaitable_var (suspend_kind
, o_type
);
901 o
= build2 (INIT_EXPR
, o_type
, e_proxy
, rvalue (o
));
904 /* I suppose we could check that this is contextually convertible to bool. */
905 tree awrd_func
= NULL_TREE
;
907 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
908 &awrd_func
, tf_warning_or_error
);
910 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
911 return error_mark_node
;
913 /* The suspend method may return one of three types:
914 1. void (no special action needed).
915 2. bool (if true, we don't need to suspend).
916 3. a coroutine handle, we execute the handle.resume() call. */
917 tree awsp_func
= NULL_TREE
;
918 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
919 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
921 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
922 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
924 release_tree_vector (args
);
925 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
926 return error_mark_node
;
929 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
930 if (same_type_p (susp_return_type
, void_type_node
))
932 else if (same_type_p (susp_return_type
, boolean_type_node
))
934 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
935 && CLASS_TYPE_P (susp_return_type
))
937 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
938 if (tt
== coro_handle_templ
)
944 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
945 " a coroutine handle");
946 return error_mark_node
;
949 /* Finally, the type of e.await_resume() is the co_await's type. */
950 tree awrs_func
= NULL_TREE
;
952 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
953 &awrs_func
, tf_warning_or_error
);
955 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
956 return error_mark_node
;
958 /* We now have three call expressions, in terms of the promise, handle and
959 'e' proxies. Save them in the await expression for later expansion. */
961 tree awaiter_calls
= make_tree_vec (3);
962 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
963 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
965 if (TREE_CODE (awrs_call
) == TARGET_EXPR
)
968 awrs_call
= TREE_OPERAND (awrs_call
, 1);
970 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
972 tree await_expr
= build5_loc (loc
, CO_AWAIT_EXPR
,
973 TREE_TYPE (TREE_TYPE (awrs_func
)),
974 a
, e_proxy
, o
, awaiter_calls
,
975 build_int_cst (integer_type_node
,
976 (int) suspend_kind
));
979 TREE_OPERAND (te
, 1) = await_expr
;
982 tree t
= convert_from_reference (await_expr
);
987 finish_co_await_expr (location_t kw
, tree expr
)
989 if (!expr
|| error_operand_p (expr
))
990 return error_mark_node
;
992 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
994 return error_mark_node
;
996 /* The current function has now become a coroutine, if it wasn't already. */
997 DECL_COROUTINE_P (current_function_decl
) = 1;
999 /* This function will appear to have no return statement, even if it
1000 is declared to return non-void (most likely). This is correct - we
1001 synthesize the return for the ramp in the compiler. So suppress any
1002 extraneous warnings during substitution. */
1003 TREE_NO_WARNING (current_function_decl
) = true;
1005 /* If we don't know the promise type, we can't proceed, build the
1006 co_await with the expression unchanged. */
1007 tree functype
= TREE_TYPE (current_function_decl
);
1008 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1009 return build5_loc (kw
, CO_AWAIT_EXPR
, unknown_type_node
, expr
,
1010 NULL_TREE
, NULL_TREE
, NULL_TREE
, integer_zero_node
);
1012 /* We must be able to look up the "await_transform" method in the scope of
1013 the promise type, and obtain its return type. */
1014 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1015 return error_mark_node
;
1018 The incoming cast expression might be transformed by a promise
1019 'await_transform()'. */
1021 = lookup_promise_method (current_function_decl
,
1022 coro_await_transform_identifier
, kw
,
1023 /*musthave=*/false);
1024 if (at_meth
== error_mark_node
)
1025 return error_mark_node
;
1030 /* try to build a = p.await_transform (e). */
1031 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1032 a
= build_new_method_call (get_coroutine_promise_proxy (
1033 current_function_decl
),
1034 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
1035 NULL
, tf_warning_or_error
);
1037 /* As I read the section.
1038 We saw an await_transform method, so it's mandatory that we replace
1039 expr with p.await_transform (expr), therefore if the method call fails
1040 (presumably, we don't have suitable arguments) then this part of the
1042 if (a
== error_mark_node
)
1043 return error_mark_node
;
1046 /* Now we want to build co_await a. */
1047 tree op
= build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
1048 if (op
!= error_mark_node
)
1050 TREE_SIDE_EFFECTS (op
) = 1;
1051 SET_EXPR_LOCATION (op
, kw
);
1057 /* Take the EXPR given and attempt to build:
1058 co_await p.yield_value (expr);
1059 per [expr.yield] para 1. */
1062 finish_co_yield_expr (location_t kw
, tree expr
)
1064 if (!expr
|| error_operand_p (expr
))
1065 return error_mark_node
;
1067 /* Check the general requirements and simple syntax errors. */
1068 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1070 return error_mark_node
;
1072 /* The current function has now become a coroutine, if it wasn't already. */
1073 DECL_COROUTINE_P (current_function_decl
) = 1;
1075 /* This function will appear to have no return statement, even if it
1076 is declared to return non-void (most likely). This is correct - we
1077 synthesize the return for the ramp in the compiler. So suppress any
1078 extraneous warnings during substitution. */
1079 TREE_NO_WARNING (current_function_decl
) = true;
1081 /* If we don't know the promise type, we can't proceed, build the
1082 co_await with the expression unchanged. */
1083 tree functype
= TREE_TYPE (current_function_decl
);
1084 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1085 return build2_loc (kw
, CO_YIELD_EXPR
, unknown_type_node
, expr
, NULL_TREE
);
1087 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1088 /* We must be able to look up the "yield_value" method in the scope of
1089 the promise type, and obtain its return type. */
1090 return error_mark_node
;
1093 Let e be the operand of the yield-expression and p be an lvalue naming
1094 the promise object of the enclosing coroutine, then the yield-expression
1095 is equivalent to the expression co_await p.yield_value(e).
1096 build p.yield_value(e): */
1097 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1099 = coro_build_promise_expression (current_function_decl
, NULL
,
1100 coro_yield_value_identifier
, kw
,
1101 &args
, /*musthave=*/true);
1102 release_tree_vector (args
);
1104 /* Now build co_await p.yield_value (e).
1105 Noting that for co_yield, there is no evaluation of any potential
1106 promise transform_await(), so we call build_co_await directly. */
1108 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
1109 if (op
!= error_mark_node
)
1111 if (REFERENCE_REF_P (op
))
1112 op
= TREE_OPERAND (op
, 0);
1113 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1114 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1115 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1116 if (TREE_CODE (op
) == TARGET_EXPR
)
1118 tree t
= TREE_OPERAND (op
, 1);
1119 t
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (t
), expr
, t
);
1120 TREE_OPERAND (op
, 1) = t
;
1123 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
1124 TREE_SIDE_EFFECTS (op
) = 1;
1125 op
= convert_from_reference (op
);
1131 /* Check and build a co_return statement.
1132 First that it's valid to have a co_return keyword here.
1133 If it is, then check and build the p.return_{void(),value(expr)}.
1134 These are built against a proxy for the promise, which will be filled
1135 in with the actual frame version when the function is transformed. */
1138 finish_co_return_stmt (location_t kw
, tree expr
)
1141 STRIP_ANY_LOCATION_WRAPPER (expr
);
1143 if (error_operand_p (expr
))
1144 return error_mark_node
;
1146 /* If it fails the following test, the function is not permitted to be a
1147 coroutine, so the co_return statement is erroneous. */
1148 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1150 return error_mark_node
;
1152 /* The current function has now become a coroutine, if it wasn't
1154 DECL_COROUTINE_P (current_function_decl
) = 1;
1156 /* This function will appear to have no return statement, even if it
1157 is declared to return non-void (most likely). This is correct - we
1158 synthesize the return for the ramp in the compiler. So suppress any
1159 extraneous warnings during substitution. */
1160 TREE_NO_WARNING (current_function_decl
) = true;
1162 if (processing_template_decl
1163 && check_for_bare_parameter_packs (expr
))
1164 return error_mark_node
;
1166 /* If we don't know the promise type, we can't proceed, build the
1167 co_return with the expression unchanged. */
1168 tree functype
= TREE_TYPE (current_function_decl
);
1169 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1171 /* co_return expressions are always void type, regardless of the
1173 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
,
1175 expr
= maybe_cleanup_point_expr_void (expr
);
1176 return add_stmt (expr
);
1179 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1180 return error_mark_node
;
1182 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1183 whether the promise type has a suitable return_void/return_value. */
1184 TREE_NO_WARNING (current_function_decl
) = true;
1186 if (!processing_template_decl
&& warn_sequence_point
)
1187 verify_sequence_points (expr
);
1191 /* If we had an id-expression obfuscated by force_paren_expr, we need
1192 to undo it so we can try to treat it as an rvalue below. */
1193 expr
= maybe_undo_parenthesized_ref (expr
);
1195 if (processing_template_decl
)
1196 expr
= build_non_dependent_expr (expr
);
1198 if (error_operand_p (expr
))
1199 return error_mark_node
;
1202 /* If the promise object doesn't have the correct return call then
1203 there's a mis-match between the co_return <expr> and this. */
1204 tree co_ret_call
= error_mark_node
;
1205 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
1207 = get_coroutine_return_void_expr (current_function_decl
, kw
, true);
1210 /* [class.copy.elision] / 3.
1211 An implicitly movable entity is a variable of automatic storage
1212 duration that is either a non-volatile object or an rvalue reference
1213 to a non-volatile object type. For such objects in the context of
1214 the co_return, the overload resolution should be carried out first
1215 treating the object as an rvalue, if that fails, then we fall back
1216 to regular overload resolution. */
1219 if (tree moved
= treat_lvalue_as_rvalue_p (expr
, /*return*/true))
1222 releasing_vec args
= make_tree_vector_single (arg
);
1224 = coro_build_promise_expression (current_function_decl
, NULL
,
1225 coro_return_value_identifier
, kw
,
1226 &args
, /*musthave=*/true);
1229 /* Makes no sense for a co-routine really. */
1230 if (TREE_THIS_VOLATILE (current_function_decl
))
1232 "function declared %<noreturn%> has a"
1233 " %<co_return%> statement");
1235 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
1236 expr
= maybe_cleanup_point_expr_void (expr
);
1237 return add_stmt (expr
);
1240 /* We need to validate the arguments to __builtin_coro_promise, since the
1241 second two must be constant, and the builtins machinery doesn't seem to
1242 deal with that properly. */
1245 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
1247 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1249 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1250 switch (DECL_FUNCTION_CODE (fn
))
1255 case BUILT_IN_CORO_PROMISE
:
1257 /* Argument 0 is already checked by the normal built-in machinery
1258 Argument 1 must be a constant of size type. It probably makes
1259 little sense if it's not a power of 2, but that isn't specified
1261 tree arg
= CALL_EXPR_ARG (call
, 1);
1262 location_t loc
= EXPR_LOCATION (arg
);
1264 /* We expect alignof expressions in templates. */
1265 if (TREE_CODE (arg
) == NON_DEPENDENT_EXPR
1266 && TREE_CODE (TREE_OPERAND (arg
, 0)) == ALIGNOF_EXPR
)
1268 else if (!TREE_CONSTANT (arg
))
1270 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1271 " must be a constant");
1272 return error_mark_node
;
1274 /* Argument 2 is the direction - to / from handle address to promise
1276 arg
= CALL_EXPR_ARG (call
, 2);
1277 loc
= EXPR_LOCATION (arg
);
1278 if (!TREE_CONSTANT (arg
))
1280 error_at (loc
, "the direction argument to"
1281 " %<__builtin_coro_promise%> must be a constant");
1282 return error_mark_node
;
1290 /* ================= Morph and Expand. =================
1292 The entry point here is morph_fn_to_coro () which is called from
1293 finish_function () when we have completed any template expansion.
1295 This is preceded by helper functions that implement the phases below.
1297 The process proceeds in four phases.
1300 The user's function body is wrapped in the initial and final suspend
1301 points and we begin building the coroutine frame.
1302 We build empty decls for the actor and destroyer functions at this
1304 When exceptions are enabled, the user's function body will also be
1305 wrapped in a try-catch block with the catch invoking the promise
1306 class 'unhandled_exception' method.
1309 The user's function body is analyzed to determine the suspend points,
1310 if any, and to capture local variables that might persist across such
1311 suspensions. In most cases, it is not necessary to capture compiler
1312 temporaries, since the tree-lowering nests the suspensions correctly.
1313 However, in the case of a captured reference, there is a lifetime
1314 extension to the end of the full expression - which can mean across a
1315 suspend point in which case it must be promoted to a frame variable.
1317 At the conclusion of analysis, we have a conservative frame layout and
1318 maps of the local variables to their frame entry points.
1320 C Build the ramp function.
1321 Carry out the allocation for the coroutine frame (NOTE; the actual size
1322 computation is deferred until late in the middle end to allow for future
1323 optimizations that will be allowed to elide unused frame entries).
1324 We build the return object.
1326 D Build and expand the actor and destroyer function bodies.
1327 The destroyer is a trivial shim that sets a bit to indicate that the
1328 destroy dispatcher should be used and then calls into the actor.
1330 The actor function is the implementation of the user's state machine.
1331 The current suspend point is noted in an index.
1332 Each suspend point is encoded as a pair of internal functions, one in
1333 the relevant dispatcher, and one representing the suspend point.
1335 During this process, the user's local variables and the proxies for the
1336 self-handle and the promise class instance are re-written to their
1337 coroutine frame equivalents.
1339 The complete bodies for the ramp, actor and destroy function are passed
1340 back to finish_function for folding and gimplification. */
1342 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1345 coro_build_expr_stmt (tree expr
, location_t loc
)
1347 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1351 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1353 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1354 return coro_build_expr_stmt (t
, loc
);
1357 /* Helpers for label creation:
1358 1. Create a named label in the specified context. */
1361 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1363 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1365 DECL_CONTEXT (lab
) = ctx
;
1366 DECL_ARTIFICIAL (lab
) = true;
1367 DECL_IGNORED_P (lab
) = true;
1368 TREE_USED (lab
) = true;
1372 /* 2. Create a named label in the specified context. */
1375 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1377 tree lab_id
= get_identifier (name
);
1378 tree lab
= define_label (loc
, lab_id
);
1379 DECL_CONTEXT (lab
) = ctx
;
1380 DECL_ARTIFICIAL (lab
) = true;
1381 TREE_USED (lab
) = true;
1385 struct proxy_replace
1391 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1393 proxy_replace
*data
= (proxy_replace
*) d
;
1395 if (*here
== data
->from
)
1405 /* Support for expansion of co_await statements. */
1409 tree actor_fn
; /* Decl for context. */
1410 tree coro_fp
; /* Frame pointer var. */
1411 tree resume_idx
; /* This is the index var in the frame. */
1412 tree i_a_r_c
; /* initial suspend await_resume() was called if true. */
1413 tree self_h
; /* This is a handle to the current coro (frame var). */
1414 tree cleanup
; /* This is where to go once we complete local destroy. */
1415 tree cororet
; /* This is where to go if we suspend. */
1416 tree corocont
; /* This is where to go if we continue. */
1417 tree conthand
; /* This is the handle for a continuation. */
1418 unsigned index
; /* This is our current resume index. */
1421 /* Lightweight search for the first await expression in tree-walk order.
1423 The first await expression found in STMT.
1424 NULL_TREE if there are none.
1425 So can be used to determine if the statement needs to be processed for
1429 co_await_find_in_subtree (tree
*stmt
, int *, void *d
)
1431 tree
**p
= (tree
**) d
;
1432 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1440 /* Starting with a statement:
1442 stmt => some tree containing one or more await expressions.
1444 We replace the statement with:
1446 initialize awaitable
1452 revised statement with one await expression rewritten to its
1453 await_resume() return value.
1456 We then recurse into the initializer and the revised statement
1457 repeating this replacement until there are no more await expressions
1461 expand_one_await_expression (tree
*stmt
, tree
*await_expr
, void *d
)
1463 coro_aw_data
*data
= (coro_aw_data
*) d
;
1465 tree saved_statement
= *stmt
;
1466 tree saved_co_await
= *await_expr
;
1468 tree actor
= data
->actor_fn
;
1469 location_t loc
= EXPR_LOCATION (*stmt
);
1470 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1471 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1472 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1474 tree source
= TREE_OPERAND (saved_co_await
, 4);
1475 bool is_final
= (source
1476 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1477 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1478 int resume_point
= data
->index
;
1479 size_t bufsize
= sizeof ("destroy.") + 10;
1480 char *buf
= (char *) alloca (bufsize
);
1481 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1482 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1483 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1484 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1485 tree empty_list
= build_empty_stmt (loc
);
1487 tree await_type
= TREE_TYPE (var
);
1488 tree stmt_list
= NULL
;
1490 tree
*await_init
= NULL
;
1493 needs_dtor
= false; /* No need, the var's lifetime is managed elsewhere. */
1496 r
= coro_build_cvt_void_expr_stmt (expr
, loc
);
1497 append_to_statement_list_force (r
, &stmt_list
);
1498 /* We have an initializer, which might itself contain await exprs. */
1499 await_init
= tsi_stmt_ptr (tsi_last (stmt_list
));
1502 /* Use the await_ready() call to test if we need to suspend. */
1503 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1504 ready_cond
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, ready_cond
);
1506 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1508 tree body_list
= NULL
;
1509 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1510 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1512 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1513 append_to_statement_list (r
, &body_list
);
1515 /* Find out what we have to do with the awaiter's suspend method.
1517 (5.1) If the result of await-ready is false, the coroutine is considered
1519 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1520 await-suspend.resume() is evaluated.
1521 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1522 and the coroutine is resumed if the result is false.
1523 (5.1.3) Otherwise, await-suspend is evaluated. */
1525 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1526 tree susp_type
= TREE_TYPE (suspend
);
1528 bool is_cont
= false;
1529 /* NOTE: final suspend can't resume; the "resume" label in that case
1530 corresponds to implicit destruction. */
1531 if (VOID_TYPE_P (susp_type
))
1533 /* We just call await_suspend() and hit the yield. */
1534 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1535 append_to_statement_list (suspend
, &body_list
);
1537 else if (TREE_CODE (susp_type
) == BOOLEAN_TYPE
)
1539 /* Boolean return, continue if the call returns false. */
1540 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1542 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1543 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1544 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1546 append_to_statement_list (r
, &body_list
);
1550 r
= build1_loc (loc
, CONVERT_EXPR
, void_coro_handle_type
, suspend
);
1551 r
= build2_loc (loc
, INIT_EXPR
, void_coro_handle_type
, data
->conthand
, r
);
1552 r
= build1 (CONVERT_EXPR
, void_type_node
, r
);
1553 append_to_statement_list (r
, &body_list
);
1557 tree d_l
= build_address (destroy_label
);
1558 tree r_l
= build_address (resume_label
);
1559 tree susp
= build_address (data
->cororet
);
1560 tree cont
= build_address (data
->corocont
);
1561 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1563 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1565 tree sw
= begin_switch_stmt ();
1566 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1567 DECL_ARTIFICIAL (cond
) = 1;
1568 DECL_IGNORED_P (cond
) = 1;
1569 layout_decl (cond
, 0);
1571 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1572 susp_idx
, final_susp
, r_l
, d_l
,
1574 r
= build2 (INIT_EXPR
, integer_type_node
, cond
, r
);
1575 finish_switch_cond (r
, sw
);
1576 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1577 create_anon_label_with_ctx (loc
, actor
));
1578 add_stmt (r
); /* case 0: */
1579 /* Implement the suspend, a scope exit without clean ups. */
1580 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1,
1581 is_cont
? cont
: susp
);
1582 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1583 add_stmt (r
); /* goto ret; */
1584 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1585 create_anon_label_with_ctx (loc
, actor
));
1586 add_stmt (r
); /* case 1: */
1587 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1588 add_stmt (r
); /* goto resume; */
1589 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1590 create_anon_label_with_ctx (loc
, actor
));
1591 add_stmt (r
); /* default:; */
1592 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1593 add_stmt (r
); /* goto destroy; */
1595 /* part of finish switch. */
1596 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1598 tree scope
= SWITCH_STMT_SCOPE (sw
);
1599 SWITCH_STMT_SCOPE (sw
) = NULL
;
1600 r
= do_poplevel (scope
);
1601 append_to_statement_list (r
, &body_list
);
1603 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1604 append_to_statement_list (destroy_label
, &body_list
);
1607 tree dtor
= build_special_member_call (var
, complete_dtor_identifier
,
1608 NULL
, await_type
, LOOKUP_NORMAL
,
1609 tf_warning_or_error
);
1610 append_to_statement_list (dtor
, &body_list
);
1612 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1613 append_to_statement_list (r
, &body_list
);
1615 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1618 append_to_statement_list (r
, &stmt_list
);
1621 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1622 append_to_statement_list (resume_label
, &stmt_list
);
1624 /* This will produce the value (if one is provided) from the co_await
1626 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1627 if (REFERENCE_REF_P (resume_call
))
1628 /* Sink to await_resume call_expr. */
1629 resume_call
= TREE_OPERAND (resume_call
, 0);
1631 *await_expr
= resume_call
; /* Replace the co_await expr with its result. */
1632 append_to_statement_list_force (saved_statement
, &stmt_list
);
1633 /* Get a pointer to the revised statement. */
1634 tree
*revised
= tsi_stmt_ptr (tsi_last (stmt_list
));
1637 tree dtor
= build_special_member_call (var
, complete_dtor_identifier
,
1638 NULL
, await_type
, LOOKUP_NORMAL
,
1639 tf_warning_or_error
);
1640 append_to_statement_list (dtor
, &stmt_list
);
1644 /* Replace the original statement with the expansion. */
1647 /* Now, if the awaitable had an initializer, expand any awaits that might
1648 be embedded in it. */
1651 cp_walk_tree (await_init
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1652 expand_one_await_expression (await_init
, aw_expr_ptr
, d
);
1654 /* Expand any more await expressions in the the original statement. */
1655 if (cp_walk_tree (revised
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1656 expand_one_await_expression (revised
, aw_expr_ptr
, d
);
1661 /* Check to see if a statement contains at least one await expression, if
1662 so, then process that. */
1665 process_one_statement (tree
*stmt
, void *d
)
1668 if (cp_walk_tree (stmt
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1669 expand_one_await_expression (stmt
, aw_expr_ptr
, d
);
1674 await_statement_expander (tree
*stmt
, int *do_subtree
, void *d
)
1676 tree res
= NULL_TREE
;
1678 /* Process a statement at a time. */
1679 if (STATEMENT_CLASS_P (*stmt
) || TREE_CODE (*stmt
) == BIND_EXPR
)
1680 return NULL_TREE
; /* Just process the sub-trees. */
1681 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1683 tree_stmt_iterator i
;
1684 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1686 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_expander
,
1691 *do_subtree
= 0; /* Done subtrees. */
1693 else if (EXPR_P (*stmt
))
1695 process_one_statement (stmt
, d
);
1696 *do_subtree
= 0; /* Done subtrees. */
1699 /* Continue statement walk, where required. */
1703 /* Suspend point hash_map. */
1705 struct suspend_point_info
1707 /* coro frame field type. */
1708 tree awaitable_type
;
1709 /* coro frame field name. */
1710 tree await_field_id
;
1713 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1715 struct await_xform_data
1717 tree actor_fn
; /* Decl for context. */
1725 /* When we built the await expressions, we didn't know the coro frame
1726 layout, therefore no idea where to find the promise or where to put
1727 the awaitables. Now we know these things, fill them in. */
1730 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1732 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1733 location_t loc
= EXPR_LOCATION (await_expr
);
1736 error_at (loc
, "no suspend point info for %qD", await_expr
);
1737 return error_mark_node
;
1740 /* So, on entry, we have:
1741 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1742 We no longer need a [it had diagnostic value, maybe?]
1743 We need to replace the promise proxy in all elements
1744 We need to replace the e_proxy in the awr_call. */
1746 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1748 /* If we have a frame var for the awaitable, get a reference to it. */
1750 if (si
->await_field_id
)
1753 = lookup_member (coro_frame_type
, si
->await_field_id
,
1754 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
1755 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
,
1757 tf_warning_or_error
);
1759 /* Replace references to the instance proxy with the frame entry now
1761 data
.from
= TREE_OPERAND (await_expr
, 1);
1763 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1765 /* .. and replace. */
1766 TREE_OPERAND (await_expr
, 1) = as
;
1769 /* Now do the self_handle. */
1770 data
.from
= xform
->self_h_proxy
;
1771 data
.to
= xform
->real_self_h
;
1772 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1774 /* Now do the promise. */
1775 data
.from
= xform
->promise_proxy
;
1776 data
.to
= xform
->real_promise
;
1777 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1782 /* A wrapper for the transform_await_expr function so that it can be a
1783 callback from cp_walk_tree. */
1786 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1788 /* Set actor function as new DECL_CONTEXT of label_decl. */
1789 struct await_xform_data
*xform
= (struct await_xform_data
*) d
;
1790 if (TREE_CODE (*stmt
) == LABEL_DECL
1791 && DECL_CONTEXT (*stmt
) != xform
->actor_fn
)
1792 DECL_CONTEXT (*stmt
) = xform
->actor_fn
;
1794 /* We should have already lowered co_yields to their co_await. */
1795 gcc_checking_assert (TREE_CODE (*stmt
) != CO_YIELD_EXPR
);
1796 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
)
1799 tree await_expr
= *stmt
;
1800 *stmt
= transform_await_expr (await_expr
, xform
);
1801 if (*stmt
== error_mark_node
)
1806 /* This caches information that we determine about function params,
1807 their uses and copies in the coroutine frame. */
1811 tree field_id
; /* The name of the copy in the coroutine frame. */
1812 vec
<tree
*> *body_uses
; /* Worklist of uses, void if there are none. */
1813 tree frame_type
; /* The type used to represent this parm in the frame. */
1814 tree orig_type
; /* The original type of the parm (not as passed). */
1815 bool by_ref
; /* Was passed by reference. */
1816 bool pt_ref
; /* Was a pointer to object. */
1817 bool trivial_dtor
; /* The frame type has a trivial DTOR. */
1818 bool this_ptr
; /* Is 'this' */
1819 bool lambda_cobj
; /* Lambda capture object */
1822 struct local_var_info
1827 bool is_lambda_capture
;
1829 bool has_value_expr_p
;
1833 /* For figuring out what local variable usage we have. */
1834 struct local_vars_transform
1838 tree coro_frame_type
;
1840 hash_map
<tree
, local_var_info
> *local_var_uses
;
1844 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
1846 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
1848 /* For each var in this bind expr (that has a frame id, which means it was
1849 accessed), build a frame reference for each and then walk the bind expr
1850 statements, substituting the frame ref for the original var. */
1852 if (TREE_CODE (*stmt
) == BIND_EXPR
)
1855 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1856 lvar
= DECL_CHAIN (lvar
))
1859 local_var_info
&local_var
1860 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
1861 gcc_checking_assert (existed
);
1863 /* Re-write the variable's context to be in the actor func. */
1864 DECL_CONTEXT (lvar
) = lvd
->context
;
1866 /* For capture proxies, this could include the decl value expr. */
1867 if (local_var
.is_lambda_capture
|| local_var
.has_value_expr_p
)
1869 tree ve
= DECL_VALUE_EXPR (lvar
);
1870 cp_walk_tree (&ve
, transform_local_var_uses
, d
, NULL
);
1871 continue; /* No frame entry for this. */
1874 /* TODO: implement selective generation of fields when vars are
1876 if (local_var
.field_id
== NULL_TREE
)
1877 continue; /* Wasn't used. */
1880 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
1881 /*protect=*/1, /*want_type=*/0,
1882 tf_warning_or_error
);
1883 tree fld_idx
= build3_loc (lvd
->loc
, COMPONENT_REF
, TREE_TYPE (lvar
),
1884 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
1885 local_var
.field_idx
= fld_idx
;
1887 /* FIXME: we should be able to do this in the loop above, but (at least
1888 for range for) there are cases where the DECL_INITIAL contains
1890 So, now we've built the revised var in the frame, substitute uses of
1891 it in initializers and the bind expr body. */
1892 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1893 lvar
= DECL_CHAIN (lvar
))
1895 /* we need to walk some of the decl trees, which might contain
1896 references to vars replaced at a higher level. */
1897 cp_walk_tree (&DECL_INITIAL (lvar
), transform_local_var_uses
, d
,
1899 cp_walk_tree (&DECL_SIZE (lvar
), transform_local_var_uses
, d
, NULL
);
1900 cp_walk_tree (&DECL_SIZE_UNIT (lvar
), transform_local_var_uses
, d
,
1903 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
1905 /* Now we have processed and removed references to the original vars,
1906 we can drop those from the bind - leaving capture proxies alone. */
1907 for (tree
*pvar
= &BIND_EXPR_VARS (*stmt
); *pvar
!= NULL
;)
1910 local_var_info
&local_var
1911 = lvd
->local_var_uses
->get_or_insert (*pvar
, &existed
);
1912 gcc_checking_assert (existed
);
1914 /* Leave lambda closure captures alone, we replace the *this
1915 pointer with the frame version and let the normal process
1917 Likewise, variables with their value found elsewhere.
1918 Skip past unused ones too. */
1919 if (local_var
.is_lambda_capture
1920 || local_var
.has_value_expr_p
1921 || local_var
.field_id
== NULL_TREE
)
1923 pvar
= &DECL_CHAIN (*pvar
);
1927 /* Discard this one, we replaced it. */
1928 *pvar
= DECL_CHAIN (*pvar
);
1931 *do_subtree
= 0; /* We've done the body already. */
1935 tree var_decl
= *stmt
;
1936 /* Look inside cleanups, we don't want to wrap a statement list in a
1938 bool needs_cleanup
= true;
1939 if (TREE_CODE (var_decl
) == CLEANUP_POINT_EXPR
)
1940 var_decl
= TREE_OPERAND (var_decl
, 0);
1942 needs_cleanup
= false;
1944 /* Look inside the decl_expr for the actual var. */
1945 bool decl_expr_p
= TREE_CODE (var_decl
) == DECL_EXPR
;
1946 if (decl_expr_p
&& TREE_CODE (DECL_EXPR_DECL (var_decl
)) == VAR_DECL
)
1947 var_decl
= DECL_EXPR_DECL (var_decl
);
1948 else if (TREE_CODE (var_decl
) != VAR_DECL
)
1951 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1952 for the promise and coroutine handle(s), to global vars or to compiler
1953 temporaries. Skip past these, we will handle them later. */
1954 local_var_info
*local_var_i
= lvd
->local_var_uses
->get (var_decl
);
1956 if (local_var_i
== NULL
)
1959 if (local_var_i
->is_lambda_capture
1960 || local_var_i
->is_static
1961 || local_var_i
->has_value_expr_p
)
1964 /* This is our revised 'local' i.e. a frame slot. */
1965 tree revised
= local_var_i
->field_idx
;
1966 gcc_checking_assert (DECL_CONTEXT (var_decl
) == lvd
->context
);
1968 if (decl_expr_p
&& DECL_INITIAL (var_decl
))
1970 location_t loc
= DECL_SOURCE_LOCATION (var_decl
);
1972 = cp_build_modify_expr (loc
, revised
, INIT_EXPR
,
1973 DECL_INITIAL (var_decl
), tf_warning_or_error
);
1975 r
= coro_build_cvt_void_expr_stmt (r
, EXPR_LOCATION (*stmt
));
1982 *do_subtree
= 0; /* We've accounted for the nested use. */
1986 /* The actor transform. */
1989 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
1990 tree orig
, hash_map
<tree
, param_info
> *param_uses
,
1991 hash_map
<tree
, local_var_info
> *local_var_uses
,
1992 vec
<tree
, va_gc
> *param_dtor_list
, tree resume_fn_field
,
1993 unsigned body_count
, tree frame_size
)
1995 verify_stmt_tree (fnbody
);
1996 /* Some things we inherit from the original function. */
1997 tree handle_type
= get_coroutine_handle_type (orig
);
1998 tree self_h_proxy
= get_coroutine_self_handle_proxy (orig
);
1999 tree promise_type
= get_coroutine_promise_type (orig
);
2000 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
2002 /* One param, the coro frame pointer. */
2003 tree actor_fp
= DECL_ARGUMENTS (actor
);
2005 /* A void return. */
2006 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2007 DECL_ARTIFICIAL (resdecl
) = 1;
2008 DECL_IGNORED_P (resdecl
) = 1;
2009 DECL_RESULT (actor
) = resdecl
;
2010 DECL_COROUTINE_P (actor
) = 1;
2012 /* We have a definition here. */
2013 TREE_STATIC (actor
) = 1;
2015 tree actor_outer
= push_stmt_list ();
2016 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2017 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
2019 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2020 tree top_block
= make_node (BLOCK
);
2021 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
2023 tree continuation
= build_lang_decl (VAR_DECL
,
2024 get_identifier ("actor.continue"),
2025 void_coro_handle_type
);
2026 DECL_ARTIFICIAL (continuation
) = 1;
2027 DECL_IGNORED_P (continuation
) = 1;
2028 DECL_CONTEXT (continuation
) = actor
;
2029 BIND_EXPR_VARS (actor_bind
) = continuation
;
2031 /* Link in the block associated with the outer scope of the re-written
2033 tree first
= expr_first (fnbody
);
2034 gcc_checking_assert (first
&& TREE_CODE (first
) == BIND_EXPR
);
2035 tree block
= BIND_EXPR_BLOCK (first
);
2036 gcc_checking_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
2037 gcc_checking_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
2038 BLOCK_SUPERCONTEXT (block
) = top_block
;
2039 BLOCK_SUBBLOCKS (top_block
) = block
;
2041 add_stmt (actor_bind
);
2042 tree actor_body
= push_stmt_list ();
2044 /* The entry point for the actor code from the ramp. */
2045 tree actor_begin_label
2046 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
2047 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
2049 /* Declare the continuation handle. */
2050 add_decl_expr (continuation
);
2052 /* Re-write param references in the body, no code should be generated
2054 if (DECL_ARGUMENTS (orig
))
2057 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
2060 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
2061 if (!parm
.body_uses
)
2062 continue; /* Wasn't used in the original function body. */
2064 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
2065 /*protect=*/1, /*want_type=*/0,
2066 tf_warning_or_error
);
2067 tree fld_idx
= build3_loc (loc
, COMPONENT_REF
, parm
.frame_type
,
2068 actor_frame
, fld_ref
, NULL_TREE
);
2070 /* We keep these in the frame as a regular pointer, so convert that
2071 back to the type expected. */
2073 fld_idx
= build1_loc (loc
, CONVERT_EXPR
, TREE_TYPE (arg
), fld_idx
);
2077 FOR_EACH_VEC_ELT (*parm
.body_uses
, i
, puse
)
2082 /* Re-write local vars, similarly. */
2083 local_vars_transform xform_vars_data
2084 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
2085 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
2087 tree resume_idx_name
= get_identifier ("__resume_at");
2088 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2089 tf_warning_or_error
);
2090 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
2091 rat_field
, NULL_TREE
);
2094 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
2097 = create_named_label_with_ctx (loc
, "actor.continue.ret", actor
);
2099 tree lsb_if
= begin_if_stmt ();
2100 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
2101 build_int_cst (short_unsigned_type_node
, 1));
2102 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
2103 build_int_cst (short_unsigned_type_node
, 0));
2104 finish_if_stmt_cond (chkb0
, lsb_if
);
2106 tree destroy_dispatcher
= begin_switch_stmt ();
2107 finish_switch_cond (rat
, destroy_dispatcher
);
2108 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2109 create_anon_label_with_ctx (loc
, actor
));
2111 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2112 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2115 short unsigned lab_num
= 3;
2116 for (unsigned destr_pt
= 0; destr_pt
< body_count
; destr_pt
++)
2118 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2119 b
= build_case_label (l_num
, NULL_TREE
,
2120 create_anon_label_with_ctx (loc
, actor
));
2122 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2124 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2126 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
2131 /* Insert the prototype dispatcher. */
2132 finish_switch_stmt (destroy_dispatcher
);
2134 finish_then_clause (lsb_if
);
2136 tree dispatcher
= begin_switch_stmt ();
2137 finish_switch_cond (rat
, dispatcher
);
2138 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
2139 create_anon_label_with_ctx (loc
, actor
));
2141 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
2144 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2145 create_anon_label_with_ctx (loc
, actor
));
2147 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2148 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2152 /* The final resume should be made to hit the default (trap, UB) entry
2153 although it will be unreachable via the normal entry point, since that
2154 is set to NULL on reaching final suspend. */
2155 for (unsigned resu_pt
= 0; resu_pt
< body_count
; resu_pt
++)
2157 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2158 b
= build_case_label (l_num
, NULL_TREE
,
2159 create_anon_label_with_ctx (loc
, actor
));
2161 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2163 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2165 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
2170 /* Insert the prototype dispatcher. */
2171 finish_switch_stmt (dispatcher
);
2173 finish_if_stmt (lsb_if
);
2175 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
2178 /* actor's version of the promise. */
2179 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
2180 tf_warning_or_error
);
2181 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
, false,
2182 tf_warning_or_error
);
2184 /* actor's coroutine 'self handle'. */
2185 tree ash_m
= lookup_member (coro_frame_type
, get_identifier ("__self_h"), 1,
2186 0, tf_warning_or_error
);
2187 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
2188 false, tf_warning_or_error
);
2189 /* So construct the self-handle from the frame address. */
2190 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
2191 0, tf_warning_or_error
);
2193 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2194 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2195 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2196 NULL
, tf_warning_or_error
);
2197 r
= build2 (INIT_EXPR
, handle_type
, ash
, hfa
);
2198 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2200 release_tree_vector (args
);
2202 /* Now we know the real promise, and enough about the frame layout to
2203 decide where to put things. */
2205 await_xform_data xform
2206 = {actor
, actor_frame
, promise_proxy
, ap
, self_h_proxy
, ash
};
2208 /* Transform the await expressions in the function body. Only do each
2210 hash_set
<tree
> pset
;
2211 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2213 /* Now replace the promise proxy with its real value. */
2214 proxy_replace p_data
;
2215 p_data
.from
= promise_proxy
;
2217 cp_walk_tree (&fnbody
, replace_proxy
, &p_data
, NULL
);
2219 /* Set the actor pointer to null, so that 'done' will work.
2220 Resume from here is UB anyway - although a 'ready' await will
2221 branch to the final resume, and fall through to the destroy. */
2223 = lookup_member (coro_frame_type
, get_identifier ("__resume"),
2224 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2225 tree res_x
= build_class_member_access_expr (actor_frame
, resume_m
, NULL_TREE
,
2226 false, tf_warning_or_error
);
2227 p_data
.from
= resume_fn_field
;
2229 cp_walk_tree (&fnbody
, replace_proxy
, &p_data
, NULL
);
2231 /* Add in our function body with the co_returns rewritten to final form. */
2234 /* now do the tail of the function. */
2235 tree del_promise_label
2236 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2237 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2240 /* Destructors for the things we built explicitly. */
2241 r
= build_special_member_call (ap
, complete_dtor_identifier
, NULL
,
2242 promise_type
, LOOKUP_NORMAL
,
2243 tf_warning_or_error
);
2246 tree del_frame_label
2247 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2248 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2251 /* Here deallocate the frame (if we allocated it), which we will have at
2254 = lookup_member (coro_frame_type
, get_identifier ("__frame_needs_free"), 1,
2255 0, tf_warning_or_error
);
2256 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2257 false, tf_warning_or_error
);
2259 tree need_free_if
= begin_if_stmt ();
2260 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2261 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2262 finish_if_stmt_cond (cmp
, need_free_if
);
2263 if (param_dtor_list
!= NULL
)
2267 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2270 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2271 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2272 false, tf_warning_or_error
);
2273 tree t
= TREE_TYPE (a
);
2276 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2277 LOOKUP_NORMAL
, tf_warning_or_error
);
2282 /* [dcl.fct.def.coroutine] / 12
2283 The deallocation function’s name is looked up in the scope of the promise
2284 type. If this lookup fails, the deallocation function’s name is looked up
2285 in the global scope. If deallocation function lookup finds both a usual
2286 deallocation function with only a pointer parameter and a usual
2287 deallocation function with both a pointer parameter and a size parameter,
2288 then the selected deallocation function shall be the one with two
2289 parameters. Otherwise, the selected deallocation function shall be the
2290 function with one parameter. If no usual deallocation function is found
2291 the program is ill-formed. The selected deallocation function shall be
2292 called with the address of the block of storage to be reclaimed as its
2293 first argument. If a deallocation function with a parameter of type
2294 std::size_t is used, the size of the block is passed as the corresponding
2297 tree del_coro_fr
= NULL_TREE
;
2298 tree frame_arg
= build1 (CONVERT_EXPR
, ptr_type_node
, actor_fp
);
2300 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2301 tree fns
= lookup_promise_method (orig
, delname
, loc
, /*musthave=*/false);
2302 if (fns
&& BASELINK_P (fns
))
2304 /* Look for sized version first, since this takes precedence. */
2305 vec
<tree
, va_gc
> *args
= make_tree_vector ();
2306 vec_safe_push (args
, frame_arg
);
2307 vec_safe_push (args
, frame_size
);
2308 tree dummy_promise
= build_dummy_object (promise_type
);
2310 /* It's OK to fail for this one... */
2311 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2312 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2315 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2317 release_tree_vector (args
);
2318 args
= make_tree_vector_single (frame_arg
);
2319 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2320 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2324 /* But one of them must succeed, or the program is ill-formed. */
2325 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2327 error_at (loc
, "%qE is provided by %qT but is not usable with"
2328 " the function signature %qD", delname
, promise_type
, orig
);
2329 del_coro_fr
= error_mark_node
;
2334 del_coro_fr
= build_op_delete_call (DELETE_EXPR
, frame_arg
, frame_size
,
2335 /*global_p=*/true, /*placement=*/NULL
,
2337 tf_warning_or_error
);
2338 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2339 del_coro_fr
= error_mark_node
;
2342 del_coro_fr
= coro_build_cvt_void_expr_stmt (del_coro_fr
, loc
);
2343 add_stmt (del_coro_fr
);
2344 finish_then_clause (need_free_if
);
2345 tree scope
= IF_SCOPE (need_free_if
);
2346 IF_SCOPE (need_free_if
) = NULL
;
2347 r
= do_poplevel (scope
);
2351 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2352 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2353 r
= maybe_cleanup_point_expr_void (r
);
2356 /* This is the suspend return point. */
2357 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2360 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2361 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2362 r
= maybe_cleanup_point_expr_void (r
);
2365 /* This is the 'continuation' return point. For such a case we have a coro
2366 handle (from the await_suspend() call) and we want handle.resume() to
2367 execute as a tailcall allowing arbitrary chaining of coroutines. */
2368 r
= build_stmt (loc
, LABEL_EXPR
, continue_label
);
2371 /* We want to force a tail-call even for O0/1, so this expands the resume
2372 call into its underlying implementation. */
2373 tree addr
= lookup_member (void_coro_handle_type
, coro_address_identifier
,
2374 1, 0, tf_warning_or_error
);
2375 addr
= build_new_method_call (continuation
, addr
, NULL
, NULL_TREE
,
2376 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
2377 tree resume
= build_call_expr_loc
2378 (loc
, builtin_decl_explicit (BUILT_IN_CORO_RESUME
), 1, addr
);
2380 /* In order to support an arbitrary number of coroutine continuations,
2381 we must tail call them. However, some targets do not support indirect
2382 tail calls to arbitrary callees. See PR94359. */
2383 CALL_EXPR_TAILCALL (resume
) = true;
2384 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
2387 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2388 gcc_checking_assert (maybe_cleanup_point_expr_void (r
) == r
);
2391 /* We will need to know which resume point number should be encoded. */
2393 = lookup_member (coro_frame_type
, resume_idx_name
,
2394 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2395 tree resume_pt_number
2396 = build_class_member_access_expr (actor_frame
, res_idx_m
, NULL_TREE
, false,
2397 tf_warning_or_error
);
2399 /* We've now rewritten the tree and added the initial and final
2400 co_awaits. Now pass over the tree and expand the co_awaits. */
2402 coro_aw_data data
= {actor
, actor_fp
, resume_pt_number
, NULL_TREE
,
2403 ash
, del_promise_label
, ret_label
,
2404 continue_label
, continuation
, 2};
2405 cp_walk_tree (&actor_body
, await_statement_expander
, &data
, NULL
);
2407 BIND_EXPR_BODY (actor_bind
) = pop_stmt_list (actor_body
);
2408 TREE_SIDE_EFFECTS (actor_bind
) = true;
2410 finish_compound_stmt (stmt
);
2411 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2412 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2415 /* The prototype 'destroy' function :
2416 frame->__resume_at |= 1;
2420 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2423 /* One param, the coro frame pointer. */
2424 tree destr_fp
= DECL_ARGUMENTS (destroy
);
2426 /* A void return. */
2427 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2428 DECL_ARTIFICIAL (resdecl
) = 1;
2429 DECL_IGNORED_P (resdecl
) = 1;
2430 DECL_RESULT (destroy
) = resdecl
;
2432 /* We have a definition here. */
2433 TREE_STATIC (destroy
) = 1;
2434 DECL_COROUTINE_P (destroy
) = 1;
2436 tree destr_outer
= push_stmt_list ();
2437 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2438 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2440 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2442 tree resume_idx_name
= get_identifier ("__resume_at");
2443 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2444 tf_warning_or_error
);
2445 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, destr_frame
,
2446 rat_field
, NULL_TREE
);
2448 /* _resume_at |= 1 */
2449 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2450 build_int_cst (short_unsigned_type_node
, 1));
2451 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2452 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2455 /* So .. call the actor .. */
2456 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2457 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2461 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2462 r
= maybe_cleanup_point_expr_void (r
);
2465 finish_compound_stmt (dstr_stmt
);
2466 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2469 /* Helper that returns an identifier for an appended extension to the
2470 current un-mangled function name. */
2473 get_fn_local_identifier (tree orig
, const char *append
)
2475 /* Figure out the bits we need to generate names for the outlined things
2476 For consistency, this needs to behave the same way as
2477 ASM_FORMAT_PRIVATE_NAME does. */
2478 tree nm
= DECL_NAME (orig
);
2479 const char *sep
, *pfx
= "";
2480 #ifndef NO_DOT_IN_LABEL
2483 #ifndef NO_DOLLAR_IN_LABEL
2492 if (DECL_ASSEMBLER_NAME (orig
))
2493 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2495 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2496 && DECL_TI_ARGS (orig
))
2498 tree tpl_args
= DECL_TI_ARGS (orig
);
2499 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2500 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2502 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2503 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2505 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2508 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2510 return get_identifier (an
);
2513 /* Build an initial or final await initialized from the promise
2514 initial_suspend or final_suspend expression. */
2517 build_init_or_final_await (location_t loc
, bool is_final
)
2519 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2520 : coro_initial_suspend_identifier
;
2523 = coro_build_promise_expression (current_function_decl
, NULL
, suspend_alt
,
2524 loc
, NULL
, /*musthave=*/true);
2526 /* So build the co_await for this */
2527 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2528 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2529 : INITIAL_SUSPEND_POINT
));
2532 /* Callback to record the essential data for each await point found in the
2536 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
)
2539 suspend_point_info
&s
2540 = suspend_points
->get_or_insert (await_expr
, &seen
);
2543 warning_at (EXPR_LOCATION (await_expr
), 0, "duplicate info for %qE",
2547 s
.awaitable_type
= aw_type
;
2548 s
.await_field_id
= aw_nam
;
2552 /* This data set is used when analyzing statements for await expressions. */
2554 struct susp_frame_data
2556 /* Function-wide. */
2557 tree
*field_list
; /* The current coroutine frame field list. */
2558 tree handle_type
; /* The self-handle type for this coroutine. */
2559 tree fs_label
; /* The destination for co_returns. */
2560 vec
<tree
, va_gc
> *block_stack
; /* Track block scopes. */
2561 vec
<tree
, va_gc
> *bind_stack
; /* Track current bind expr. */
2562 unsigned await_number
; /* Which await in the function. */
2563 unsigned cond_number
; /* Which replaced condition in the fn. */
2564 /* Temporary values for one statement or expression being analyzed. */
2565 hash_set
<tree
> captured_temps
; /* The suspend captured these temps. */
2566 vec
<tree
, va_gc
> *to_replace
; /* The VAR decls to replace. */
2567 hash_set
<tree
> *truth_aoif_to_expand
; /* The set of TRUTH exprs to expand. */
2568 unsigned saw_awaits
; /* Count of awaits in this statement */
2569 bool captures_temporary
; /* This expr captures temps by ref. */
2570 bool needs_truth_if_exp
; /* We must expand a truth_if expression. */
2571 bool has_awaiter_init
; /* We must handle initializing an awaiter. */
2574 /* If this is an await expression, then count it (both uniquely within the
2575 function and locally within a single statement). */
2578 register_awaits (tree
*stmt
, int *, void *d
)
2580 tree aw_expr
= *stmt
;
2582 /* We should have already lowered co_yields to their co_await. */
2583 gcc_checking_assert (TREE_CODE (aw_expr
) != CO_YIELD_EXPR
);
2585 if (TREE_CODE (aw_expr
) != CO_AWAIT_EXPR
)
2588 /* Count how many awaits the current expression contains. */
2589 susp_frame_data
*data
= (susp_frame_data
*) d
;
2591 /* Each await suspend context is unique, this is a function-wide value. */
2592 data
->await_number
++;
2594 /* Awaitables should either be user-locals or promoted to coroutine frame
2595 entries at this point, and their initializers should have been broken
2597 tree aw
= TREE_OPERAND (aw_expr
, 1);
2598 gcc_checking_assert (!TREE_OPERAND (aw_expr
, 2));
2600 tree aw_field_type
= TREE_TYPE (aw
);
2601 tree aw_field_nam
= NULL_TREE
;
2602 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
);
2604 /* Rewrite target expressions on the await_suspend () to remove extraneous
2605 cleanups for the awaitables, which are now promoted to frame vars and
2606 managed via that. */
2607 tree v
= TREE_OPERAND (aw_expr
, 3);
2608 tree o
= TREE_VEC_ELT (v
, 1);
2609 if (TREE_CODE (o
) == TARGET_EXPR
)
2610 TREE_VEC_ELT (v
, 1) = get_target_expr (TREE_OPERAND (o
, 1));
2614 /* There are cases where any await expression is relevant. */
2616 find_any_await (tree
*stmt
, int *dosub
, void *d
)
2618 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
2620 *dosub
= 0; /* We don't need to consider this any further. */
2621 tree
**p
= (tree
**) d
;
2629 tmp_target_expr_p (tree t
)
2631 if (TREE_CODE (t
) != TARGET_EXPR
)
2633 tree v
= TREE_OPERAND (t
, 0);
2634 if (!DECL_ARTIFICIAL (v
))
2641 /* Structure to record sub-expressions that need to be handled by the
2642 statement flattener. */
2644 struct coro_interesting_subtree
2647 hash_set
<tree
> *temps_used
;
2650 /* tree-walk callback that returns the first encountered sub-expression of
2651 a kind that needs to be handled specifically by the statement flattener. */
2654 find_interesting_subtree (tree
*expr_p
, int *dosub
, void *d
)
2656 tree expr
= *expr_p
;
2657 coro_interesting_subtree
*p
= (coro_interesting_subtree
*)d
;
2658 if (TREE_CODE (expr
) == CO_AWAIT_EXPR
)
2660 *dosub
= 0; /* We don't need to consider this any further. */
2661 if (TREE_OPERAND (expr
, 2))
2667 else if (tmp_target_expr_p (expr
)
2668 && !p
->temps_used
->contains (expr
))
2677 /* Node for a doubly-linked list of promoted variables and their
2678 initializers. When the initializer is a conditional expression
2679 the 'then' and 'else' clauses are represented by a linked list
2680 attached to then_cl and else_cl respectively. */
2682 struct var_nest_node
2684 var_nest_node () = default;
2685 var_nest_node (tree v
, tree i
, var_nest_node
*p
, var_nest_node
*n
)
2686 : var(v
), init(i
), prev(p
), next(n
)
2695 var_nest_node
*prev
;
2696 var_nest_node
*next
;
2697 var_nest_node
*then_cl
;
2698 var_nest_node
*else_cl
;
2701 /* This is called for single statements from the co-await statement walker.
2702 It checks to see if the statement contains any initializers for awaitables
2703 and if any of these capture items by reference. */
2706 flatten_await_stmt (var_nest_node
*n
, hash_set
<tree
> *promoted
,
2707 hash_set
<tree
> *temps_used
, tree
*replace_in
)
2709 bool init_expr
= false;
2710 switch (TREE_CODE (n
->init
))
2713 /* Compound expressions must be flattened specifically. */
2716 tree first
= TREE_OPERAND (n
->init
, 0);
2717 n
->init
= TREE_OPERAND (n
->init
, 1);
2719 = new var_nest_node(NULL_TREE
, first
, n
->prev
, n
);
2720 /* The compiler (but not the user) can generate temporaries with
2721 uses in the second arm of a compound expr. */
2722 flatten_await_stmt (ins
, promoted
, temps_used
, &n
->init
);
2723 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2724 /* The two arms have been processed separately. */
2728 /* Handle conditional expressions. */
2734 tree old_expr
= TREE_OPERAND (n
->init
, 1);
2735 if (TREE_CODE (old_expr
) == COMPOUND_EXPR
)
2737 tree first
= TREE_OPERAND (old_expr
, 0);
2738 TREE_OPERAND (n
->init
, 1) = TREE_OPERAND (old_expr
, 1);
2740 = new var_nest_node(NULL_TREE
, first
, n
->prev
, n
);
2741 flatten_await_stmt (ins
, promoted
, temps_used
,
2742 &TREE_OPERAND (n
->init
, 1));
2743 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2746 if (TREE_CODE (old_expr
) != COND_EXPR
)
2748 /* Reconstruct x = t ? y : z;
2749 as (void) t ? x = y : x = z; */
2750 tree var
= TREE_OPERAND (n
->init
, 0);
2751 tree var_type
= TREE_TYPE (var
);
2752 tree cond
= COND_EXPR_COND (old_expr
);
2753 /* We are allowed a void type throw in one or both of the cond
2755 tree then_cl
= COND_EXPR_THEN (old_expr
);
2756 if (!VOID_TYPE_P (TREE_TYPE (then_cl
)))
2758 gcc_checking_assert (TREE_CODE (then_cl
) != STATEMENT_LIST
);
2760 = build2 (init_expr
? INIT_EXPR
: MODIFY_EXPR
, var_type
,
2763 tree else_cl
= COND_EXPR_ELSE (old_expr
);
2764 if (!VOID_TYPE_P (TREE_TYPE (else_cl
)))
2766 gcc_checking_assert (TREE_CODE (then_cl
) != STATEMENT_LIST
);
2768 = build2 (init_expr
? INIT_EXPR
: MODIFY_EXPR
, var_type
,
2771 n
->init
= build3 (COND_EXPR
, var_type
, cond
, then_cl
, else_cl
);
2777 tree cond
= COND_EXPR_COND (n
->init
);
2778 /* If the condition contains an await expression, then we need to
2779 set that first and use a separate var. */
2780 if (cp_walk_tree (&cond
, find_any_await
, &found
, NULL
))
2782 tree cond_type
= TREE_TYPE (cond
);
2783 tree cond_var
= build_lang_decl (VAR_DECL
, NULL_TREE
, cond_type
);
2784 DECL_ARTIFICIAL (cond_var
) = true;
2785 layout_decl (cond_var
, 0);
2786 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type
));
2787 cond
= build2 (INIT_EXPR
, cond_type
, cond_var
, cond
);
2789 = new var_nest_node (cond_var
, cond
, n
->prev
, n
);
2790 COND_EXPR_COND (n
->init
) = cond_var
;
2791 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2795 = new var_nest_node (n
->var
, COND_EXPR_THEN (n
->init
), NULL
, NULL
);
2797 = new var_nest_node (n
->var
, COND_EXPR_ELSE (n
->init
), NULL
, NULL
);
2798 flatten_await_stmt (n
->then_cl
, promoted
, temps_used
, NULL
);
2799 /* Point to the start of the flattened code. */
2800 while (n
->then_cl
->prev
)
2801 n
->then_cl
= n
->then_cl
->prev
;
2802 flatten_await_stmt (n
->else_cl
, promoted
, temps_used
, NULL
);
2803 while (n
->else_cl
->prev
)
2804 n
->else_cl
= n
->else_cl
->prev
;
2809 coro_interesting_subtree v
= { NULL
, temps_used
};
2810 tree t
= cp_walk_tree (&n
->init
, find_interesting_subtree
, (void *)&v
, NULL
);
2813 switch (TREE_CODE (t
))
2818 /* Await expressions with initializers have a compiler-temporary
2819 as the awaitable. 'promote' this. */
2820 tree var
= TREE_OPERAND (t
, 1);
2821 bool already_present
= promoted
->add (var
);
2822 gcc_checking_assert (!already_present
);
2823 tree init
= TREE_OPERAND (t
, 2);
2824 switch (TREE_CODE (init
))
2830 tree inner
= TREE_OPERAND (init
, 1);
2831 /* We can have non-lvalue-expressions here, but when we see
2832 a target expression, mark it as already used. */
2833 if (TREE_CODE (inner
) == TARGET_EXPR
)
2835 temps_used
->add (inner
);
2837 (TREE_CODE (TREE_OPERAND (inner
, 1)) != COND_EXPR
);
2842 /* If this is a call and not a CTOR, then we didn't expect it. */
2844 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init
), 0)));
2847 var_nest_node
*ins
= new var_nest_node (var
, init
, n
->prev
, n
);
2848 TREE_OPERAND (t
, 2) = NULL_TREE
;
2849 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2850 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2856 /* We have a temporary; promote it. */
2858 temps_used
->add (init
);
2859 tree var_type
= TREE_TYPE (init
);
2860 char *buf
= xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init
, 0)));
2861 tree var
= build_lang_decl (VAR_DECL
, get_identifier (buf
), var_type
);
2862 DECL_ARTIFICIAL (var
) = true;
2864 bool already_present
= promoted
->add (var
);
2865 gcc_checking_assert (!already_present
);
2866 tree inner
= TREE_OPERAND (init
, 1);
2867 gcc_checking_assert (TREE_CODE (inner
) != COND_EXPR
);
2868 if (TYPE_NEEDS_CONSTRUCTING (var_type
))
2870 releasing_vec
p_in (make_tree_vector_single (init
));
2871 init
= build_special_member_call (var
, complete_ctor_identifier
,
2872 &p_in
, var_type
, LOOKUP_NORMAL
,
2873 tf_warning_or_error
);
2876 init
= build2 (INIT_EXPR
, var_type
, var
, init
);
2878 = new var_nest_node (var
, init
, n
->prev
, n
);
2879 /* We have to replace the target expr... */
2880 proxy_replace pr
= {TREE_OPERAND (t
, 0), var
};
2882 /* ... and any uses of its var. */
2883 cp_walk_tree (&n
->init
, replace_proxy
, &pr
, NULL
);
2884 /* Compiler-generated temporaries can also have uses in following
2885 arms of compound expressions, which will be listed in 'replace_in'
2888 cp_walk_tree (replace_in
, replace_proxy
, &pr
, NULL
);
2889 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2890 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2897 /* Helper for 'process_conditional' that handles recursion into nested
2901 handle_nested_conditionals (var_nest_node
*n
, vec
<tree
>& list
,
2902 hash_map
<tree
, tree
>& map
)
2906 if (n
->var
&& DECL_NAME (n
->var
))
2908 list
.safe_push (n
->var
);
2909 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n
->var
)))
2912 tree
& flag
= map
.get_or_insert (n
->var
, &existed
);
2915 /* We didn't see this var before and it needs a DTOR, so
2916 build a guard variable for it. */
2918 = xasprintf ("%s_guard",
2919 IDENTIFIER_POINTER (DECL_NAME (n
->var
)));
2920 flag
= build_lang_decl (VAR_DECL
, get_identifier (nam
),
2923 DECL_ARTIFICIAL (flag
) = true;
2926 /* The initializer for this variable is replaced by a compound
2927 expression that performs the init and then records that the
2928 variable is live (and the DTOR should be run at the scope
2930 tree set_flag
= build2 (INIT_EXPR
, boolean_type_node
,
2931 flag
, boolean_true_node
);
2933 = build2 (COMPOUND_EXPR
, boolean_type_node
, n
->init
, set_flag
);
2936 if (TREE_CODE (n
->init
) == COND_EXPR
)
2938 tree new_then
= push_stmt_list ();
2939 handle_nested_conditionals (n
->then_cl
, list
, map
);
2940 new_then
= pop_stmt_list (new_then
);
2941 tree new_else
= push_stmt_list ();
2942 handle_nested_conditionals (n
->else_cl
, list
, map
);
2943 new_else
= pop_stmt_list (new_else
);
2945 = build4 (IF_STMT
, void_type_node
, COND_EXPR_COND (n
->init
),
2946 new_then
, new_else
, NULL_TREE
);
2950 finish_expr_stmt (n
->init
);
2955 /* helper for 'maybe_promote_temps'.
2957 When we have a conditional expression which might embed await expressions
2958 and/or promoted variables, we need to handle it appropriately.
2960 The linked lists for the 'then' and 'else' clauses in a conditional node
2961 identify the promoted variables (but these cannot be wrapped in a regular
2964 So recurse through the lists and build up a composite list of captured vars.
2965 Declare these and any guard variables needed to decide if a DTOR should be
2966 run. Then embed the conditional into a try-finally expression that handles
2967 running each DTOR conditionally on its guard variable. */
2970 process_conditional (var_nest_node
*n
, tree
& vlist
)
2972 tree init
= n
->init
;
2973 hash_map
<tree
, tree
> var_flags
;
2974 vec
<tree
> var_list
= vNULL
;
2975 tree new_then
= push_stmt_list ();
2976 handle_nested_conditionals (n
->then_cl
, var_list
, var_flags
);
2977 new_then
= pop_stmt_list (new_then
);
2978 tree new_else
= push_stmt_list ();
2979 handle_nested_conditionals (n
->else_cl
, var_list
, var_flags
);
2980 new_else
= pop_stmt_list (new_else
);
2981 /* Declare the vars. There are two loops so that the boolean flags are
2982 grouped in the frame. */
2983 for (unsigned i
= 0; i
< var_list
.length(); i
++)
2985 tree var
= var_list
[i
];
2986 DECL_CHAIN (var
) = vlist
;
2988 add_decl_expr (var
);
2990 /* Define the guard flags for variables that need a DTOR. */
2991 for (unsigned i
= 0; i
< var_list
.length(); i
++)
2993 tree
*flag
= var_flags
.get (var_list
[i
]);
2996 DECL_INITIAL (*flag
) = boolean_false_node
;
2997 DECL_CHAIN (*flag
) = vlist
;
2999 add_decl_expr (*flag
);
3003 = build4 (IF_STMT
, void_type_node
, COND_EXPR_COND (init
),
3004 new_then
, new_else
, NULL_TREE
);
3005 /* Build a set of conditional DTORs. */
3006 tree final_actions
= push_stmt_list ();
3007 while (!var_list
.is_empty())
3009 tree var
= var_list
.pop ();
3010 tree
*flag
= var_flags
.get (var
);
3013 tree var_type
= TREE_TYPE (var
);
3015 = build_special_member_call (var
, complete_dtor_identifier
,
3016 NULL
, var_type
, LOOKUP_NORMAL
,
3017 tf_warning_or_error
);
3018 tree cond_cleanup
= begin_if_stmt ();
3019 finish_if_stmt_cond (*flag
, cond_cleanup
);
3020 finish_expr_stmt (cleanup
);
3021 finish_then_clause (cond_cleanup
);
3022 finish_if_stmt (cond_cleanup
);
3024 final_actions
= pop_stmt_list (final_actions
);
3026 = build2 (TRY_FINALLY_EXPR
, void_type_node
, new_if
, final_actions
);
3027 add_stmt (try_finally
);
3030 /* Given *STMT, that contains at least one await expression.
3032 The full expression represented in the original source code will contain
3033 suspension points, but it is still required that the lifetime of temporary
3034 values extends to the end of the expression.
3036 We already have a mechanism to 'promote' user-authored local variables
3037 to a coroutine frame counterpart (which allows explicit management of the
3038 lifetime across suspensions). The transform here re-writes STMT into
3039 a bind expression, promotes temporary values into local variables in that
3040 and flattens the statement into a series of cleanups.
3042 Conditional expressions are re-written to regular 'if' statements.
3043 The cleanups for variables initialized inside a conditional (including
3044 nested cases) are wrapped in a try-finally clause, with guard variables
3045 to determine which DTORs need to be run. */
3048 maybe_promote_temps (tree
*stmt
, void *d
)
3050 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3052 location_t sloc
= EXPR_LOCATION (*stmt
);
3054 /* Strip off uninteresting wrappers. */
3055 if (TREE_CODE (expr
) == CLEANUP_POINT_EXPR
)
3056 expr
= TREE_OPERAND (expr
, 0);
3057 if (TREE_CODE (expr
) == EXPR_STMT
)
3058 expr
= EXPR_STMT_EXPR (expr
);
3059 if (TREE_CODE (expr
) == CONVERT_EXPR
3060 && VOID_TYPE_P (TREE_TYPE (expr
)))
3061 expr
= TREE_OPERAND (expr
, 0);
3064 /* We walk the statement trees, flattening it into an ordered list of
3065 variables with initializers and fragments corresponding to compound
3066 expressions, truth or/and if and ternary conditionals. Conditional
3067 expressions carry a nested list of fragments for the then and else
3068 clauses. We anchor to the 'bottom' of the fragment list; we will write
3069 a cleanup nest with one shell for each variable initialized. */
3070 var_nest_node
*root
= new var_nest_node (NULL_TREE
, expr
, NULL
, NULL
);
3071 /* Check to see we didn't promote one twice. */
3072 hash_set
<tree
> promoted_vars
;
3073 hash_set
<tree
> used_temps
;
3074 flatten_await_stmt (root
, &promoted_vars
, &used_temps
, NULL
);
3076 gcc_checking_assert (root
->next
== NULL
);
3077 tree vlist
= NULL_TREE
;
3078 var_nest_node
*t
= root
;
3079 gcc_checking_assert (!t
->var
);
3080 /* We build the bind scope expression from the bottom-up.
3081 EXPR_LIST holds the inner expression nest at the current cleanup
3082 level (becoming the final expression list when we've exhausted the
3083 number of sub-expression fragments). */
3084 tree expr_list
= NULL_TREE
;
3087 tree new_list
= push_stmt_list ();
3088 /* When we have a promoted variable, then add that to the bind scope
3089 and initialize it. When there's no promoted variable, we just need
3090 to run the initializer.
3091 If the initializer is a conditional expression, we need to collect
3092 and declare any promoted variables nested within it. DTORs for such
3093 variables must be run conditionally too. */
3094 if (t
->var
&& DECL_NAME (t
->var
))
3097 DECL_CHAIN (var
) = vlist
;
3099 add_decl_expr (var
);
3100 if (TREE_CODE (t
->init
) == COND_EXPR
)
3101 process_conditional (t
, vlist
);
3103 finish_expr_stmt (t
->init
);
3104 tree var_type
= TREE_TYPE (var
);
3105 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type
))
3108 = build_special_member_call (var
, complete_dtor_identifier
,
3109 NULL
, var_type
, LOOKUP_NORMAL
,
3110 tf_warning_or_error
);
3111 tree cl
= build_stmt (sloc
, CLEANUP_STMT
, expr_list
, cleanup
, var
);
3112 add_stmt (cl
); /* push this onto the level above. */
3115 add_stmt (expr_list
);
3121 if (TREE_CODE (t
->init
) == COND_EXPR
)
3122 process_conditional (t
, vlist
);
3124 finish_expr_stmt (t
->init
);
3126 add_stmt (expr_list
);
3128 expr_list
= pop_stmt_list (new_list
);
3129 var_nest_node
*old
= t
;
3134 /* Now produce the bind expression containing the 'promoted' temporaries
3135 as its variable list, and the cleanup nest as the statement. */
3136 tree await_bind
= build3_loc (sloc
, BIND_EXPR
, void_type_node
,
3138 BIND_EXPR_BODY (await_bind
) = expr_list
;
3139 BIND_EXPR_VARS (await_bind
) = nreverse (vlist
);
3140 tree b_block
= make_node (BLOCK
);
3141 if (!awpts
->block_stack
->is_empty ())
3143 tree s_block
= awpts
->block_stack
->last ();
3146 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
3147 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
3148 BLOCK_SUBBLOCKS (s_block
) = b_block
;
3151 BLOCK_VARS (b_block
) = BIND_EXPR_VARS (await_bind
) ;
3152 BIND_EXPR_BLOCK (await_bind
) = b_block
;
3153 TREE_SIDE_EFFECTS (await_bind
) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind
));
3155 hash_set
<tree
> visited
;
3156 return cp_walk_tree (stmt
, register_awaits
, d
, &visited
);
3159 /* Lightweight callback to determine two key factors:
3160 1) If the statement/expression contains any await expressions.
3161 2) If the statement/expression potentially requires a re-write to handle
3162 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3163 so that the await expressions are not processed in the case of the
3166 CO_YIELD expressions are re-written to their underlying co_await. */
3169 analyze_expression_awaits (tree
*stmt
, int *do_subtree
, void *d
)
3171 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3173 switch (TREE_CODE (*stmt
))
3175 default: return NULL_TREE
;
3177 /* co_yield is syntactic sugar, re-write it to co_await. */
3178 *stmt
= TREE_OPERAND (*stmt
, 1);
3181 awpts
->saw_awaits
++;
3182 /* A non-null initializer for the awaiter means we need to expand. */
3183 if (TREE_OPERAND (*stmt
, 2))
3184 awpts
->has_awaiter_init
= true;
3186 case TRUTH_ANDIF_EXPR
:
3187 case TRUTH_ORIF_EXPR
:
3189 /* We don't need special action for awaits in the always-executed
3190 arm of a TRUTH_IF. */
3191 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 0),
3192 analyze_expression_awaits
, d
, NULL
))
3194 /* However, if there are await expressions on the conditionally
3195 executed branch, we must expand the TRUTH_IF to ensure that the
3196 expanded await expression control-flow is fully contained in the
3197 conditionally executed code. */
3198 unsigned aw_count
= awpts
->saw_awaits
;
3199 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 1),
3200 analyze_expression_awaits
, d
, NULL
))
3202 if (awpts
->saw_awaits
> aw_count
)
3204 awpts
->truth_aoif_to_expand
->add (*stmt
);
3205 awpts
->needs_truth_if_exp
= true;
3207 /* We've done the sub-trees here. */
3213 return NULL_TREE
; /* Recurse until done. */
3217 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3218 the conditionally executed branch, change this in a ternary operator.
3220 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3221 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3223 Apply this recursively to the condition and the conditionally-exec
3226 struct truth_if_transform
{
3229 hash_set
<tree
> *truth_aoif_to_expand
;
3233 expand_one_truth_if (tree
*expr
, int *do_subtree
, void *d
)
3235 truth_if_transform
*xform
= (truth_if_transform
*) d
;
3237 bool needs_not
= false;
3238 switch (TREE_CODE (*expr
))
3241 case TRUTH_ORIF_EXPR
:
3244 case TRUTH_ANDIF_EXPR
:
3246 if (!xform
->truth_aoif_to_expand
->contains (*expr
))
3249 location_t sloc
= EXPR_LOCATION (*expr
);
3250 /* Transform truth expression into a cond expression with
3251 * the always-executed arm as the condition.
3252 * the conditionally-executed arm as the then clause.
3253 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3254 tree cond
= TREE_OPERAND (*expr
, 0);
3255 tree test1
= TREE_OPERAND (*expr
, 1);
3256 tree fixed
= needs_not
? boolean_true_node
: boolean_false_node
;
3258 cond
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3260 = build3_loc (sloc
, COND_EXPR
, boolean_type_node
,
3261 cond
, test1
, fixed
);
3263 if (tree res
= cp_walk_tree (&COND_EXPR_COND (*expr
),
3264 expand_one_truth_if
, d
, NULL
))
3266 if (tree res
= cp_walk_tree (&COND_EXPR_THEN (*expr
),
3267 expand_one_truth_if
, d
, NULL
))
3269 /* We've manually processed necessary sub-trees here. */
3277 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3278 name is made up from NAM_ROOT, NAM_VERS. */
3281 add_var_to_bind (tree
& bind
, tree var_type
,
3282 const char *nam_root
, unsigned nam_vers
)
3284 tree b_vars
= BIND_EXPR_VARS (bind
);
3285 /* Build a variable to hold the condition, this will be included in the
3286 frame as a local var. */
3287 char *nam
= xasprintf ("%s.%d", nam_root
, nam_vers
);
3288 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
3290 DECL_CHAIN (newvar
) = b_vars
;
3291 BIND_EXPR_VARS (bind
) = newvar
;
3295 /* Helper to build and add if (!cond) break; */
3298 coro_build_add_if_not_cond_break (tree cond
)
3300 tree if_stmt
= begin_if_stmt ();
3301 tree invert
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3302 finish_if_stmt_cond (invert
, if_stmt
);
3303 finish_break_stmt ();
3304 finish_then_clause (if_stmt
);
3305 finish_if_stmt (if_stmt
);
3308 /* Tree walk callback to analyze, register and pre-process statements that
3309 contain await expressions. */
3312 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
3314 tree res
= NULL_TREE
;
3315 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3317 /* Process a statement at a time. */
3318 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3320 /* For conditional expressions, we might wish to add an artificial var
3321 to their containing bind expr. */
3322 vec_safe_push (awpts
->bind_stack
, *stmt
);
3323 /* We might need to insert a new bind expression, and want to link it
3324 into the correct scope, so keep a note of the current block scope. */
3325 tree blk
= BIND_EXPR_BLOCK (*stmt
);
3326 vec_safe_push (awpts
->block_stack
, blk
);
3327 res
= cp_walk_tree (&BIND_EXPR_BODY (*stmt
), await_statement_walker
,
3329 awpts
->block_stack
->pop ();
3330 awpts
->bind_stack
->pop ();
3331 *do_subtree
= 0; /* Done subtrees. */
3334 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
3336 tree_stmt_iterator i
;
3337 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
3339 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_walker
,
3344 *do_subtree
= 0; /* Done subtrees. */
3348 /* We have something to be handled as a single statement. */
3349 bool has_cleanup_wrapper
= TREE_CODE (*stmt
) == CLEANUP_POINT_EXPR
;
3350 hash_set
<tree
> visited
;
3351 awpts
->saw_awaits
= 0;
3352 hash_set
<tree
> truth_aoif_to_expand
;
3353 awpts
->truth_aoif_to_expand
= &truth_aoif_to_expand
;
3354 awpts
->needs_truth_if_exp
= false;
3355 awpts
->has_awaiter_init
= false;
3357 if (has_cleanup_wrapper
)
3358 expr
= TREE_OPERAND (expr
, 0);
3361 if (STATEMENT_CLASS_P (expr
))
3362 switch (TREE_CODE (expr
))
3364 /* Unless it's a special case, just walk the subtrees as usual. */
3365 default: return NULL_TREE
;
3367 /* When we have a conditional expression, which contains one or more
3368 await expressions, we have to break the condition out into a
3369 regular statement so that the control flow introduced by the await
3370 transforms can be implemented. */
3373 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3374 bool cond = cond with awaits.
3375 if (cond) then stmt1 else stmt2. */
3376 tree if_stmt
= *stmt
;
3377 /* We treat the condition as if it was a stand-alone statement,
3378 to see if there are any await expressions which will be analyzed
3380 if ((res
= cp_walk_tree (&IF_COND (if_stmt
),
3381 analyze_expression_awaits
, d
, &visited
)))
3383 if (!awpts
->saw_awaits
)
3384 return NULL_TREE
; /* Nothing special to do here. */
3386 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3387 tree
& bind_expr
= awpts
->bind_stack
->last ();
3388 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3389 "ifcd", awpts
->cond_number
++);
3390 tree insert_list
= push_stmt_list ();
3391 tree cond_inner
= IF_COND (if_stmt
);
3392 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3393 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3394 add_decl_expr (newvar
);
3395 location_t sloc
= EXPR_LOCATION (IF_COND (if_stmt
));
3396 /* We want to initialize the new variable with the expression
3397 that contains the await(s) and potentially also needs to
3398 have truth_if expressions expanded. */
3399 tree new_s
= build2_loc (sloc
, MODIFY_EXPR
, boolean_type_node
,
3400 newvar
, cond_inner
);
3401 finish_expr_stmt (new_s
);
3402 IF_COND (if_stmt
) = newvar
;
3404 *stmt
= pop_stmt_list (insert_list
);
3405 /* So now walk the new statement list. */
3406 res
= cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3407 *do_subtree
= 0; /* Done subtrees. */
3413 /* We turn 'while (cond with awaits) stmt' into
3415 if (!(cond with awaits))
3419 tree while_stmt
= *stmt
;
3420 if ((res
= cp_walk_tree (&WHILE_COND (while_stmt
),
3421 analyze_expression_awaits
, d
, &visited
)))
3423 if (!awpts
->saw_awaits
)
3424 return NULL_TREE
; /* Nothing special to do here. */
3426 tree insert_list
= push_stmt_list ();
3427 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt
));
3428 /* The original while body. */
3429 add_stmt (WHILE_BODY (while_stmt
));
3430 /* The new while body. */
3431 WHILE_BODY (while_stmt
) = pop_stmt_list (insert_list
);
3432 WHILE_COND (while_stmt
) = boolean_true_node
;
3433 /* So now walk the new statement list. */
3434 res
= cp_walk_tree (&WHILE_BODY (while_stmt
),
3435 await_statement_walker
, d
, NULL
);
3436 *do_subtree
= 0; /* Done subtrees. */
3442 /* We turn do stmt while (cond with awaits) into:
3445 if (!(cond with awaits))
3448 tree do_stmt
= *stmt
;
3449 if ((res
= cp_walk_tree (&DO_COND (do_stmt
),
3450 analyze_expression_awaits
, d
, &visited
)))
3452 if (!awpts
->saw_awaits
)
3453 return NULL_TREE
; /* Nothing special to do here. */
3455 tree insert_list
= push_stmt_list ();
3456 /* The original do stmt body. */
3457 add_stmt (DO_BODY (do_stmt
));
3458 coro_build_add_if_not_cond_break (DO_COND (do_stmt
));
3459 /* The new while body. */
3460 DO_BODY (do_stmt
) = pop_stmt_list (insert_list
);
3461 DO_COND (do_stmt
) = boolean_true_node
;
3462 /* So now walk the new statement list. */
3463 res
= cp_walk_tree (&DO_BODY (do_stmt
), await_statement_walker
,
3465 *do_subtree
= 0; /* Done subtrees. */
3471 /* We turn 'switch (cond with awaits) stmt' into
3472 switch_type cond = cond with awaits
3473 switch (cond) stmt. */
3474 tree sw_stmt
= *stmt
;
3475 if ((res
= cp_walk_tree (&SWITCH_STMT_COND (sw_stmt
),
3476 analyze_expression_awaits
, d
, &visited
)))
3478 if (!awpts
->saw_awaits
)
3479 return NULL_TREE
; /* Nothing special to do here. */
3481 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3482 /* Build a variable to hold the condition, this will be
3483 included in the frame as a local var. */
3484 tree
& bind_expr
= awpts
->bind_stack
->last ();
3485 tree sw_type
= SWITCH_STMT_TYPE (sw_stmt
);
3486 tree newvar
= add_var_to_bind (bind_expr
, sw_type
, "swch",
3487 awpts
->cond_number
++);
3488 tree insert_list
= push_stmt_list ();
3489 add_decl_expr (newvar
);
3491 tree cond_inner
= SWITCH_STMT_COND (sw_stmt
);
3492 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3493 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3494 location_t sloc
= EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt
));
3495 tree new_s
= build2_loc (sloc
, INIT_EXPR
, sw_type
, newvar
,
3497 finish_expr_stmt (new_s
);
3498 SWITCH_STMT_COND (sw_stmt
) = newvar
;
3499 /* Now add the switch statement with the condition re-
3500 written to use the local var. */
3502 *stmt
= pop_stmt_list (insert_list
);
3503 /* Process the expanded list. */
3504 res
= cp_walk_tree (stmt
, await_statement_walker
,
3506 *do_subtree
= 0; /* Done subtrees. */
3510 case CO_RETURN_EXPR
:
3512 /* Expand the co_return as per [stmt.return.coroutine]
3514 { p.return_void (); goto final_suspend; }
3515 - for co_return [void expr];
3516 { expr; p.return_void(); goto final_suspend;}
3517 - for co_return [non void expr];
3518 { p.return_value(expr); goto final_suspend; } */
3519 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
,
3522 location_t loc
= EXPR_LOCATION (expr
);
3523 tree call
= TREE_OPERAND (expr
, 1);
3524 expr
= TREE_OPERAND (expr
, 0);
3525 tree ret_list
= push_stmt_list ();
3526 /* [stmt.return.coroutine], 2.2
3527 If expr is present and void, it is placed immediately before
3528 the call for return_void; */
3529 tree
*maybe_await_stmt
= NULL
;
3530 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
3532 finish_expr_stmt (expr
);
3533 /* If the return argument was a void expression, then any
3534 awaits must be contained in that. */
3535 maybe_await_stmt
= tsi_stmt_ptr (tsi_last (ret_list
));
3537 /* Insert p.return_{void,value(expr)}. */
3538 finish_expr_stmt (call
);
3539 /* Absent a return of a void expression, any awaits must be in
3540 the parameter to return_value(). */
3541 if (!maybe_await_stmt
)
3542 maybe_await_stmt
= tsi_stmt_ptr (tsi_last (ret_list
));
3543 expr
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, awpts
->fs_label
);
3544 finish_expr_stmt (expr
);
3545 *stmt
= pop_stmt_list (ret_list
);
3546 /* Once this is complete, we will have processed subtrees. */
3548 if (awpts
->saw_awaits
)
3550 gcc_checking_assert (maybe_await_stmt
);
3551 res
= cp_walk_tree (maybe_await_stmt
, await_statement_walker
,
3556 return NULL_TREE
; /* Done. */
3560 else if (EXPR_P (expr
))
3562 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
, d
, &visited
)))
3564 *do_subtree
= 0; /* Done subtrees. */
3565 if (!awpts
->saw_awaits
)
3566 return NULL_TREE
; /* Nothing special to do here. */
3568 if (awpts
->needs_truth_if_exp
)
3570 /* If a truth-and/or-if expression has an await expression in the
3571 conditionally-taken branch, then it must be rewritten into a
3572 regular conditional. */
3573 truth_if_transform xf
= {stmt
, NULL_TREE
, &truth_aoif_to_expand
};
3574 if ((res
= cp_walk_tree (stmt
, expand_one_truth_if
, &xf
, NULL
)))
3577 /* Process this statement, which contains at least one await expression
3578 to 'promote' temporary values to a coroutine frame slot. */
3579 return maybe_promote_temps (stmt
, d
);
3581 /* Continue recursion, if needed. */
3585 /* For figuring out what param usage we have. */
3587 struct param_frame_data
3590 hash_map
<tree
, param_info
> *param_uses
;
3591 hash_set
<tree
*> *visited
;
3596 /* A tree-walk callback that records the use of parameters (to allow for
3597 optimizations where handling unused parameters may be omitted). */
3600 register_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
3602 param_frame_data
*data
= (param_frame_data
*) d
;
3604 /* For lambda closure content, we have to look specifically. */
3605 if (TREE_CODE (*stmt
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (*stmt
))
3607 tree t
= DECL_VALUE_EXPR (*stmt
);
3608 return cp_walk_tree (&t
, register_param_uses
, d
, NULL
);
3611 if (TREE_CODE (*stmt
) != PARM_DECL
)
3614 /* If we already saw the containing expression, then we're done. */
3615 if (data
->visited
->add (stmt
))
3619 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
3620 gcc_checking_assert (existed
);
3622 if (!parm
.body_uses
)
3624 vec_alloc (parm
.body_uses
, 4);
3625 parm
.body_uses
->quick_push (stmt
);
3626 data
->param_seen
= true;
3629 parm
.body_uses
->safe_push (stmt
);
3634 /* Small helper for the repetitive task of adding a new field to the coro
3638 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
3641 tree id
= get_identifier (name
);
3642 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
3643 DECL_CHAIN (decl
) = *field_list
;
3648 /* For recording local variable usage. */
3650 struct local_vars_frame_data
3653 hash_map
<tree
, local_var_info
> *local_var_uses
;
3654 unsigned int nest_depth
, bind_indx
;
3657 bool local_var_seen
;
3660 /* A tree-walk callback that processes one bind expression noting local
3661 variables, and making a coroutine frame slot available for those that
3662 need it, so that they can be 'promoted' across suspension points. */
3665 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
3667 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
3669 /* As we enter a bind expression - record the vars there and then recurse.
3670 As we exit drop the nest depth.
3671 The bind index is a growing count of how many bind indices we've seen.
3672 We build a space in the frame for each local var. */
3674 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3679 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
3680 lvar
= DECL_CHAIN (lvar
))
3683 local_var_info
&local_var
3684 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
3685 gcc_checking_assert (!existed
);
3686 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
3687 tree lvtype
= TREE_TYPE (lvar
);
3688 local_var
.frame_type
= lvtype
;
3689 local_var
.field_idx
= local_var
.field_id
= NULL_TREE
;
3691 /* Make sure that we only present vars to the tests below. */
3692 if (TREE_CODE (lvar
) == TYPE_DECL
3693 || TREE_CODE (lvar
) == NAMESPACE_DECL
)
3696 /* We don't move static vars into the frame. */
3697 local_var
.is_static
= TREE_STATIC (lvar
);
3698 if (local_var
.is_static
)
3701 lvd
->local_var_seen
= true;
3702 /* If this var is a lambda capture proxy, we want to leave it alone,
3703 and later rewrite the DECL_VALUE_EXPR to indirect through the
3704 frame copy of the pointer to the lambda closure object. */
3705 local_var
.is_lambda_capture
= is_capture_proxy (lvar
);
3706 if (local_var
.is_lambda_capture
)
3709 /* If a variable has a value expression, then that's what needs
3711 local_var
.has_value_expr_p
= DECL_HAS_VALUE_EXPR_P (lvar
);
3712 if (local_var
.has_value_expr_p
)
3715 /* Make names depth+index unique, so that we can support nested
3716 scopes with identically named locals. */
3717 tree lvname
= DECL_NAME (lvar
);
3719 if (lvname
!= NULL_TREE
)
3720 buf
= xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname
),
3721 lvd
->nest_depth
, lvd
->bind_indx
);
3723 buf
= xasprintf ("_D%u.%u.%u", DECL_UID (lvar
), lvd
->nest_depth
,
3725 /* TODO: Figure out if we should build a local type that has any
3726 excess alignment or size from the original decl. */
3728 = coro_make_frame_entry (lvd
->field_list
, buf
, lvtype
, lvd
->loc
);
3730 /* We don't walk any of the local var sub-trees, they won't contain
3733 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
3734 *do_subtree
= 0; /* We've done this. */
3740 /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
3741 for either actor or destroy functions. */
3744 act_des_fn (tree orig
, tree fn_type
, tree coro_frame_ptr
, const char* name
)
3746 tree fn_name
= get_fn_local_identifier (orig
, name
);
3747 tree fn
= build_lang_decl (FUNCTION_DECL
, fn_name
, fn_type
);
3748 DECL_CONTEXT (fn
) = DECL_CONTEXT (orig
);
3749 DECL_ARTIFICIAL (fn
) = true;
3750 DECL_INITIAL (fn
) = error_mark_node
;
3751 tree id
= get_identifier ("frame_ptr");
3752 tree fp
= build_lang_decl (PARM_DECL
, id
, coro_frame_ptr
);
3753 DECL_CONTEXT (fp
) = fn
;
3754 DECL_ARG_TYPE (fp
) = type_passed_as (coro_frame_ptr
);
3755 DECL_ARGUMENTS (fn
) = fp
;
3756 /* Copy selected attributes from the original function. */
3757 TREE_USED (fn
) = TREE_USED (orig
);
3758 if (DECL_SECTION_NAME (orig
))
3759 set_decl_section_name (fn
, DECL_SECTION_NAME (orig
));
3760 /* Copy any alignment that the FE added. */
3761 if (DECL_ALIGN (orig
))
3762 SET_DECL_ALIGN (fn
, DECL_ALIGN (orig
));
3763 /* Copy any alignment the user added. */
3764 DECL_USER_ALIGN (fn
) = DECL_USER_ALIGN (orig
);
3765 /* Apply attributes from the original fn. */
3766 DECL_ATTRIBUTES (fn
) = copy_list (DECL_ATTRIBUTES (orig
));
3770 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
3773 coro_rewrite_function_body (location_t fn_start
, tree fnbody
,
3774 tree orig
, tree resume_fn_ptr_type
,
3775 tree
& resume_fn_field
, tree
& fs_label
)
3777 /* This will be our new outer scope. */
3778 tree update_body
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3779 tree top_block
= make_node (BLOCK
);
3780 BIND_EXPR_BLOCK (update_body
) = top_block
;
3781 BIND_EXPR_BODY (update_body
) = push_stmt_list ();
3783 /* If the function has a top level bind expression, then connect that
3784 after first making sure we give it a new block. */
3785 tree first
= expr_first (fnbody
);
3786 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
3788 tree block
= BIND_EXPR_BLOCK (first
);
3789 gcc_checking_assert (block
);
3790 gcc_checking_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
3791 gcc_checking_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
3792 /* Replace the top block to avoid issues with locations for args
3793 appearing to be in a non-existent place. */
3794 tree replace_blk
= make_node (BLOCK
);
3795 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
3796 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
3797 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
3798 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
3799 BIND_EXPR_BLOCK (first
) = replace_blk
;
3800 /* The top block has one child, so far, and we have now got a
3802 BLOCK_SUPERCONTEXT (block
) = top_block
;
3803 BLOCK_SUBBLOCKS (top_block
) = block
;
3806 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
3808 tree promise
= get_coroutine_promise_proxy (orig
);
3809 tree var_list
= NULL_TREE
;
3810 tree initial_await
= build_init_or_final_await (fn_start
, false);
3812 /* [stmt.return.coroutine] / 3
3813 If p.return_void() is a valid expression, flowing off the end of a
3814 coroutine is equivalent to a co_return with no operand; otherwise
3815 flowing off the end of a coroutine results in undefined behavior. */
3817 = get_coroutine_return_void_expr (current_function_decl
, fn_start
, false);
3819 if (flag_exceptions
)
3821 /* Build promise.unhandled_exception(); */
3823 = coro_build_promise_expression (current_function_decl
, promise
,
3824 coro_unhandled_exception_identifier
,
3825 fn_start
, NULL
, /*musthave=*/true);
3826 /* Create and initialize the initial-await-resume-called variable per
3827 [dcl.fct.def.coroutine] / 5.3. */
3828 tree i_a_r_c
= build_lang_decl (VAR_DECL
, get_identifier ("i_a_r_c"),
3830 DECL_ARTIFICIAL (i_a_r_c
) = true;
3831 DECL_CHAIN (i_a_r_c
) = var_list
;
3833 DECL_INITIAL (i_a_r_c
) = boolean_false_node
;
3834 add_decl_expr (i_a_r_c
);
3835 /* Start the try-catch. */
3836 tree tcb
= build_stmt (fn_start
, TRY_BLOCK
, NULL_TREE
, NULL_TREE
);
3838 TRY_STMTS (tcb
) = push_stmt_list ();
3839 if (initial_await
!= error_mark_node
)
3841 /* Build a compound expression that sets the
3842 initial-await-resume-called variable true and then calls the
3843 initial suspend expression await resume. */
3844 tree vec
= TREE_OPERAND (initial_await
, 3);
3845 tree aw_r
= TREE_VEC_ELT (vec
, 2);
3846 tree update
= build2 (MODIFY_EXPR
, boolean_type_node
, i_a_r_c
,
3848 aw_r
= cp_build_compound_expr (update
, aw_r
, tf_warning_or_error
);
3849 TREE_VEC_ELT (vec
, 2) = aw_r
;
3851 /* Add the initial await to the start of the user-authored function. */
3852 finish_expr_stmt (initial_await
);
3853 /* Append the original function body. */
3856 add_stmt (return_void
);
3857 TRY_STMTS (tcb
) = pop_stmt_list (TRY_STMTS (tcb
));
3858 TRY_HANDLERS (tcb
) = push_stmt_list ();
3859 /* Mimic what the parser does for the catch. */
3860 tree handler
= begin_handler ();
3861 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
3863 /* Get the initial await resume called value. */
3864 tree not_iarc_if
= begin_if_stmt ();
3865 tree not_iarc
= build1_loc (fn_start
, TRUTH_NOT_EXPR
,
3866 boolean_type_node
, i_a_r_c
);
3867 finish_if_stmt_cond (not_iarc
, not_iarc_if
);
3868 /* If the initial await resume called value is false, rethrow... */
3869 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
3870 TREE_NO_WARNING (rethrow
) = true;
3871 finish_expr_stmt (rethrow
);
3872 finish_then_clause (not_iarc_if
);
3873 tree iarc_scope
= IF_SCOPE (not_iarc_if
);
3874 IF_SCOPE (not_iarc_if
) = NULL
;
3875 not_iarc_if
= do_poplevel (iarc_scope
);
3876 add_stmt (not_iarc_if
);
3877 /* ... else call the promise unhandled exception method. */
3878 ueh
= maybe_cleanup_point_expr_void (ueh
);
3880 finish_handler (handler
);
3881 TRY_HANDLERS (tcb
) = pop_stmt_list (TRY_HANDLERS (tcb
));
3887 /* We still try to look for the promise method and warn if it's not
3890 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
3891 fn_start
, /*musthave=*/false);
3892 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
3893 warning_at (fn_start
, 0, "no member named %qE in %qT",
3894 coro_unhandled_exception_identifier
,
3895 get_coroutine_promise_type (orig
));
3897 /* Else we don't check and don't care if the method is missing..
3898 just add the initial suspend, function and return. */
3899 finish_expr_stmt (initial_await
);
3900 /* Append the original function body. */
3903 add_stmt (return_void
);
3906 /* co_return branches to the final_suspend label, so declare that now. */
3908 = create_named_label_with_ctx (fn_start
, "final.suspend", NULL_TREE
);
3909 add_stmt (build_stmt (fn_start
, LABEL_EXPR
, fs_label
));
3911 /* Before entering the final suspend point, we signal that this point has
3912 been reached by setting the resume function pointer to zero (this is
3913 what the 'done()' builtin tests) as per the current ABI. */
3915 = build_lang_decl (VAR_DECL
, get_identifier ("resume.fn.ptr.proxy"),
3916 resume_fn_ptr_type
);
3917 DECL_ARTIFICIAL (resume_fn_field
) = true;
3919 = build1 (CONVERT_EXPR
, resume_fn_ptr_type
, integer_zero_node
);
3921 = build2 (INIT_EXPR
, resume_fn_ptr_type
, resume_fn_field
, zero_resume
);
3922 finish_expr_stmt (zero_resume
);
3923 finish_expr_stmt (build_init_or_final_await (fn_start
, true));
3924 BIND_EXPR_BODY (update_body
) = pop_stmt_list (BIND_EXPR_BODY (update_body
));
3925 BIND_EXPR_VARS (update_body
) = nreverse (var_list
);
3926 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (update_body
);
3932 a) Check that the function and promise type are valid for a
3934 b) Carry out the initial morph to create the skeleton of the
3935 coroutine ramp function and the rewritten body.
3939 1. We only hit this code once all dependencies are resolved.
3940 2. The function body will be either a bind expr or a statement list
3941 3. That cfun and current_function_decl are valid for the case we're
3943 4. 'input_location' will be of the final brace for the function.
3945 We do something like this:
3946 declare a dummy coro frame.
3948 using handle_type = coro::coroutine_handle<coro1::promise_type>;
3949 void (*__resume)(_R_frame *);
3950 void (*__destroy)(_R_frame *);
3951 coro1::promise_type __p;
3952 bool frame_needs_free; free the coro frame mem if set.
3953 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
3955 handle_type self_handle;
3956 (maybe) parameter copies.
3957 (maybe) local variables saved (including awaitables)
3958 (maybe) trailing space.
3962 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
3964 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
3966 *resumer
= error_mark_node
;
3967 *destroyer
= error_mark_node
;
3968 if (!coro_function_valid_p (orig
))
3970 /* For early errors, we do not want a diagnostic about the missing
3971 ramp return value, since the user cannot fix this - a 'return' is
3972 not allowed in a coroutine. */
3973 TREE_NO_WARNING (orig
) = true;
3974 /* Discard the body, we can't process it further. */
3975 pop_stmt_list (DECL_SAVED_TREE (orig
));
3976 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3980 /* We can't validly get here with an empty statement list, since there's no
3981 way for the FE to decide it's a coroutine in the absence of any code. */
3982 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
3983 gcc_checking_assert (fnbody
!= NULL_TREE
);
3985 /* We don't have the locus of the opening brace - it's filled in later (and
3986 there doesn't really seem to be any easy way to get at it).
3987 The closing brace is assumed to be input_location. */
3988 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
3989 gcc_rich_location
fn_start_loc (fn_start
);
3991 /* Initial processing of the function-body.
3992 If we have no expressions or just an error then punt. */
3993 tree body_start
= expr_first (fnbody
);
3994 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
3996 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3997 append_to_statement_list (fnbody
, &DECL_SAVED_TREE (orig
));
3998 /* Suppress warnings about the missing return value. */
3999 TREE_NO_WARNING (orig
) = true;
4003 /* So, we've tied off the original user-authored body in fn_body.
4005 Start the replacement synthesized ramp body as newbody.
4006 If we encounter a fatal error we might return a now-empty body.
4008 Note, the returned ramp body is not 'popped', to be compatible with
4009 the way that decl.c handles regular functions, the scope pop is done
4012 tree newbody
= push_stmt_list ();
4013 DECL_SAVED_TREE (orig
) = newbody
;
4015 /* If our original body is noexcept, then that's what we apply to our
4016 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
4017 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
4020 /* The function body we will continue with is the single operand to
4021 the must-not-throw. */
4022 fnbody
= TREE_OPERAND (body_start
, 0);
4023 /* Transfer the must-not-throw to the ramp body. */
4024 add_stmt (body_start
);
4025 /* Re-start the ramp as must-not-throw. */
4026 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
4029 /* Create the coro frame type, as far as it can be known at this stage.
4030 1. Types we already know. */
4032 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
4033 tree handle_type
= get_coroutine_handle_type (orig
);
4034 tree promise_type
= get_coroutine_promise_type (orig
);
4036 /* 2. Types we need to define or look up. */
4038 tree fr_name
= get_fn_local_identifier (orig
, "frame");
4039 tree coro_frame_type
= xref_tag (record_type
, fr_name
);
4040 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
4041 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
4042 tree act_des_fn_type
4043 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
4044 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
4046 /* Declare the actor and destroyer function. */
4047 tree actor
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "actor");
4048 tree destroy
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "destroy");
4050 /* Construct the wrapped function body; we will analyze this to determine
4051 the requirements for the coroutine frame. */
4053 tree resume_fn_field
= NULL_TREE
;
4054 tree fs_label
= NULL_TREE
;
4055 fnbody
= coro_rewrite_function_body (fn_start
, fnbody
, orig
, act_des_fn_ptr
,
4056 resume_fn_field
, fs_label
);
4057 /* Build our dummy coro frame layout. */
4058 coro_frame_type
= begin_class_definition (coro_frame_type
);
4060 tree field_list
= NULL_TREE
;
4062 = coro_make_frame_entry (&field_list
, "__resume",
4063 act_des_fn_ptr
, fn_start
);
4065 = coro_make_frame_entry (&field_list
, "__destroy",
4066 act_des_fn_ptr
, fn_start
);
4068 = coro_make_frame_entry (&field_list
, "__p", promise_type
, fn_start
);
4069 tree fnf_name
= coro_make_frame_entry (&field_list
, "__frame_needs_free",
4070 boolean_type_node
, fn_start
);
4071 tree resume_idx_name
4072 = coro_make_frame_entry (&field_list
, "__resume_at",
4073 short_unsigned_type_node
, fn_start
);
4075 /* We need a handle to this coroutine, which is passed to every
4076 await_suspend(). There's no point in creating it over and over. */
4077 (void) coro_make_frame_entry (&field_list
, "__self_h", handle_type
, fn_start
);
4079 /* Now add in fields for function params (if there are any).
4080 We do not attempt elision of copies at this stage, we do analyze the
4081 uses and build worklists to replace those when the state machine is
4084 hash_map
<tree
, param_info
> *param_uses
= NULL
;
4085 if (DECL_ARGUMENTS (orig
))
4087 /* Build a hash map with an entry for each param.
4088 The key is the param tree.
4089 Then we have an entry for the frame field name.
4090 Then a cache for the field ref when we come to use it.
4091 Then a tree list of the uses.
4092 The second two entries start out empty - and only get populated
4093 when we see uses. */
4094 param_uses
= new hash_map
<tree
, param_info
>;
4095 bool lambda_p
= LAMBDA_FUNCTION_P (orig
);
4097 unsigned no_name_parm
= 0;
4098 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4099 arg
= DECL_CHAIN (arg
))
4102 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4103 gcc_checking_assert (!existed
);
4104 parm
.body_uses
= NULL
;
4105 tree actual_type
= TREE_TYPE (arg
);
4106 actual_type
= complete_type_or_else (actual_type
, orig
);
4107 if (actual_type
== NULL_TREE
)
4108 actual_type
= error_mark_node
;
4109 parm
.orig_type
= actual_type
;
4110 parm
.by_ref
= parm
.pt_ref
= false;
4111 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
4113 /* If the user passes by reference, then we will save the
4114 pointer to the original. As noted in
4115 [dcl.fct.def.coroutine] / 13, if the lifetime of the
4116 referenced item ends and then the coroutine is resumed,
4117 we have UB; well, the user asked for it. */
4118 actual_type
= build_pointer_type (TREE_TYPE (actual_type
));
4121 else if (TYPE_REF_P (DECL_ARG_TYPE (arg
)))
4124 parm
.frame_type
= actual_type
;
4126 parm
.this_ptr
= is_this_parameter (arg
);
4127 parm
.lambda_cobj
= lambda_p
&& DECL_NAME (arg
) == closure_identifier
;
4129 parm
.trivial_dtor
= TYPE_HAS_TRIVIAL_DESTRUCTOR (parm
.frame_type
);
4131 if (DECL_NAME (arg
))
4133 tree pname
= DECL_NAME (arg
);
4134 buf
= xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname
));
4137 buf
= xasprintf ("__unnamed_parm.%d", no_name_parm
++);
4138 parm
.field_id
= coro_make_frame_entry
4139 (&field_list
, buf
, actual_type
, DECL_SOURCE_LOCATION (arg
));
4143 /* We want to record every instance of param's use, so don't include
4144 a 'visited' hash_set on the tree walk, but only record a containing
4146 hash_set
<tree
*> visited
;
4147 param_frame_data param_data
4148 = {&field_list
, param_uses
, &visited
, fn_start
, false};
4149 cp_walk_tree (&fnbody
, register_param_uses
, ¶m_data
, NULL
);
4152 /* We need to know, and inspect, each suspend point in the function
4153 in several places. It's convenient to place this map out of line
4154 since it's used from tree walk callbacks. */
4155 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
4157 /* Now insert the data for any body await points, at this time we also need
4158 to promote any temporaries that are captured by reference (to regular
4159 vars) they will get added to the coro frame along with other locals. */
4160 susp_frame_data body_aw_points
4161 = {&field_list
, handle_type
, fs_label
, NULL
, NULL
, 0, 0,
4162 hash_set
<tree
> (), NULL
, NULL
, 0, false, false, false};
4163 body_aw_points
.block_stack
= make_tree_vector ();
4164 body_aw_points
.bind_stack
= make_tree_vector ();
4165 body_aw_points
.to_replace
= make_tree_vector ();
4166 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
4168 /* 4. Now make space for local vars, this is conservative again, and we
4169 would expect to delete unused entries later. */
4170 hash_map
<tree
, local_var_info
> local_var_uses
;
4171 local_vars_frame_data local_vars_data
4172 = {&field_list
, &local_var_uses
, 0, 0, fn_start
, false, false};
4173 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
4175 /* Tie off the struct for now, so that we can build offsets to the
4177 TYPE_FIELDS (coro_frame_type
) = field_list
;
4178 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
4179 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
4180 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
4182 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
4185 /* Now build the ramp function pieces. */
4186 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4187 add_stmt (ramp_bind
);
4188 tree ramp_body
= push_stmt_list ();
4190 tree coro_fp
= build_lang_decl (VAR_DECL
, get_identifier ("coro.frameptr"),
4192 tree varlist
= coro_fp
;
4194 /* Collected the scope vars we need ... only one for now. */
4195 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
4197 /* We're now going to create a new top level scope block for the ramp
4199 tree top_block
= make_node (BLOCK
);
4201 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
4202 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
4203 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
4205 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4206 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4207 directly apparently). This avoids a "used uninitialized" warning. */
4208 tree zeroinit
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
4209 DECL_INITIAL (coro_fp
) = zeroinit
;
4210 add_decl_expr (coro_fp
);
4212 /* The CO_FRAME internal function is a mechanism to allow the middle end
4213 to adjust the allocation in response to optimizations. We provide the
4214 current conservative estimate of the frame size (as per the current)
4216 tree frame_size
= TYPE_SIZE_UNIT (coro_frame_type
);
4218 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
4219 frame_size
, coro_fp
);
4221 /* [dcl.fct.def.coroutine] / 10 (part1)
4222 The unqualified-id get_return_object_on_allocation_failure is looked up
4223 in the scope of the promise type by class member access lookup. */
4225 /* We don't require this, so coro_build_promise_expression can return NULL,
4226 but, if the lookup succeeds, then the function must be usable. */
4227 tree dummy_promise
= build_dummy_object (get_coroutine_promise_type (orig
));
4229 = coro_build_promise_expression (orig
, dummy_promise
,
4230 coro_gro_on_allocation_fail_identifier
,
4231 fn_start
, NULL
, /*musthave=*/false);
4233 /* however, should that fail, returning an error, the later stages can't
4234 handle the erroneous expression, so we reset the call as if it was
4236 if (grooaf
== error_mark_node
)
4239 /* Allocate the frame, this has several possibilities:
4240 [dcl.fct.def.coroutine] / 9 (part 1)
4241 The allocation function’s name is looked up in the scope of the promise
4242 type. It's not a failure for it to be absent see part 4, below. */
4244 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
4245 tree new_fn
= NULL_TREE
;
4247 if (TYPE_HAS_NEW_OPERATOR (promise_type
))
4249 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
4251 /* [dcl.fct.def.coroutine] / 9 (part 2)
4252 If the lookup finds an allocation function in the scope of the promise
4253 type, overload resolution is performed on a function call created by
4254 assembling an argument list. The first argument is the amount of space
4255 requested, and has type std::size_t. The succeeding arguments are
4256 those of the original function. */
4257 vec
<tree
, va_gc
> *args
= make_tree_vector ();
4258 vec_safe_push (args
, resizeable
); /* Space needed. */
4260 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4261 arg
= DECL_CHAIN (arg
))
4263 param_info
*parm_i
= param_uses
->get (arg
);
4264 gcc_checking_assert (parm_i
);
4265 if (parm_i
->this_ptr
|| parm_i
->lambda_cobj
)
4267 /* We pass a reference to *this to the allocator lookup. */
4268 tree tt
= TREE_TYPE (TREE_TYPE (arg
));
4269 tree this_ref
= build1 (INDIRECT_REF
, tt
, arg
);
4270 tt
= cp_build_reference_type (tt
, false);
4271 this_ref
= convert_to_reference (tt
, this_ref
, CONV_STATIC
,
4272 LOOKUP_NORMAL
, NULL_TREE
,
4273 tf_warning_or_error
);
4274 vec_safe_push (args
, this_ref
);
4277 vec_safe_push (args
, arg
);
4280 /* Note the function selected; we test to see if it's NOTHROW. */
4282 /* Failure is not an error for this attempt. */
4283 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
, NULL
,
4284 LOOKUP_NORMAL
, &func
, tf_none
);
4285 release_tree_vector (args
);
4287 if (new_fn
== error_mark_node
)
4289 /* [dcl.fct.def.coroutine] / 9 (part 3)
4290 If no viable function is found, overload resolution is performed
4291 again on a function call created by passing just the amount of
4292 space required as an argument of type std::size_t. */
4293 args
= make_tree_vector_single (resizeable
); /* Space needed. */
4294 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
,
4295 NULL_TREE
, LOOKUP_NORMAL
, &func
,
4297 release_tree_vector (args
);
4300 /* However, if the promise provides an operator new, then one of these
4301 two options must be available. */
4302 if (new_fn
== error_mark_node
)
4304 error_at (fn_start
, "%qE is provided by %qT but is not usable with"
4305 " the function signature %qD", nwname
, promise_type
, orig
);
4306 new_fn
= error_mark_node
;
4308 else if (grooaf
&& !TYPE_NOTHROW_P (TREE_TYPE (func
)))
4309 error_at (fn_start
, "%qE is provided by %qT but %qE is not marked"
4310 " %<throw()%> or %<noexcept%>", grooaf
, promise_type
, nwname
);
4311 else if (!grooaf
&& TYPE_NOTHROW_P (TREE_TYPE (func
)))
4312 warning_at (fn_start
, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4313 " no usable %<get_return_object_on_allocation_failure%>"
4314 " is provided by %qT", nwname
, promise_type
);
4316 else /* No operator new in the promise. */
4318 /* [dcl.fct.def.coroutine] / 9 (part 4)
4319 If this lookup fails, the allocation function’s name is looked up in
4320 the global scope. */
4322 vec
<tree
, va_gc
> *args
;
4323 /* build_operator_new_call () will insert size needed as element 0 of
4324 this, and we might need to append the std::nothrow constant. */
4325 vec_alloc (args
, 2);
4328 /* [dcl.fct.def.coroutine] / 10 (part 2)
4329 If any declarations (of the get return on allocation fail) are
4330 found, then the result of a call to an allocation function used
4331 to obtain storage for the coroutine state is assumed to return
4332 nullptr if it fails to obtain storage and, if a global allocation
4333 function is selected, the ::operator new(size_t, nothrow_t) form
4334 is used. The allocation function used in this case shall have a
4335 non-throwing noexcept-specification. So we need std::nothrow. */
4336 tree std_nt
= lookup_qualified_name (std_node
,
4337 get_identifier ("nothrow"),
4340 if (!std_nt
|| std_nt
== error_mark_node
)
4341 error_at (fn_start
, "%qE is provided by %qT but %<std::nothrow%> "
4342 "cannot be found", grooaf
, promise_type
);
4343 vec_safe_push (args
, std_nt
);
4346 /* If we get to this point, we must succeed in looking up the global
4347 operator new for the params provided. Extract a simplified version
4348 of the machinery from build_operator_new_call. This can update the
4351 new_fn
= build_operator_new_call (nwname
, &args
, &frame_size
, &cookie
,
4353 /*size_check=*/NULL
, /*fn=*/NULL
,
4354 tf_warning_or_error
);
4355 resizeable
= build_call_expr_internal_loc
4356 (fn_start
, IFN_CO_FRAME
, size_type_node
, 2, frame_size
, coro_fp
);
4357 /* If the operator call fails for some reason, then don't try to
4359 if (new_fn
!= error_mark_node
)
4360 CALL_EXPR_ARG (new_fn
, 0) = resizeable
;
4362 release_tree_vector (args
);
4365 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
4366 tree r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, allocated
);
4367 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4370 /* If the user provided a method to return an object on alloc fail, then
4371 check the returned pointer and call the func if it's null.
4372 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4376 /* [dcl.fct.def.coroutine] / 10 (part 3)
4377 If the allocation function returns nullptr,the coroutine returns
4378 control to the caller of the coroutine and the return value is
4379 obtained by a call to T::get_return_object_on_allocation_failure(),
4380 where T is the promise type. */
4382 gcc_checking_assert (same_type_p (fn_return_type
, TREE_TYPE (grooaf
)));
4383 tree if_stmt
= begin_if_stmt ();
4384 tree cond
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
4385 cond
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, cond
);
4386 finish_if_stmt_cond (cond
, if_stmt
);
4387 if (VOID_TYPE_P (fn_return_type
))
4389 /* Execute the get-return-object-on-alloc-fail call... */
4390 finish_expr_stmt (grooaf
);
4391 /* ... but discard the result, since we return void. */
4392 finish_return_stmt (NULL_TREE
);
4396 /* Get the fallback return object. */
4397 r
= build_cplus_new (fn_return_type
, grooaf
, tf_warning_or_error
);
4398 finish_return_stmt (r
);
4400 finish_then_clause (if_stmt
);
4401 finish_if_stmt (if_stmt
);
4404 /* deref the frame pointer, to use in member access code. */
4405 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
4407 /* For now, once allocation has succeeded we always assume that this needs
4408 destruction, there's no impl. for frame allocation elision. */
4410 = lookup_member (coro_frame_type
, fnf_name
, 1, 0, tf_warning_or_error
);
4411 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
4412 false, tf_warning_or_error
);
4413 r
= build2 (INIT_EXPR
, boolean_type_node
, fnf_x
, boolean_true_node
);
4414 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4417 /* Put the resumer and destroyer functions in. */
4419 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
4421 = lookup_member (coro_frame_type
, resume_name
,
4422 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4423 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
4424 false, tf_warning_or_error
);
4425 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, resume_x
, actor_addr
);
4426 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4429 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
4431 = lookup_member (coro_frame_type
, destroy_name
,
4432 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4434 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
4435 tf_warning_or_error
);
4436 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, destroy_x
, destroy_addr
);
4437 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4440 /* [dcl.fct.def.coroutine] /13
4441 When a coroutine is invoked, a copy is created for each coroutine
4442 parameter. Each such copy is an object with automatic storage duration
4443 that is direct-initialized from an lvalue referring to the corresponding
4444 parameter if the parameter is an lvalue reference, and from an xvalue
4445 referring to it otherwise. A reference to a parameter in the function-
4446 body of the coroutine and in the call to the coroutine promise
4447 constructor is replaced by a reference to its copy. */
4449 vec
<tree
, va_gc
> *promise_args
= NULL
; /* So that we can adjust refs. */
4451 /* The initialization and destruction of each parameter copy occurs in the
4452 context of the called coroutine. Initializations of parameter copies are
4453 sequenced before the call to the coroutine promise constructor and
4454 indeterminately sequenced with respect to each other. The lifetime of
4455 parameter copies ends immediately after the lifetime of the coroutine
4456 promise object ends. */
4458 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
4460 if (DECL_ARGUMENTS (orig
))
4462 promise_args
= make_tree_vector ();
4463 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4464 arg
= DECL_CHAIN (arg
))
4467 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4469 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
4470 /*protect=*/1, /*want_type=*/0,
4471 tf_warning_or_error
);
4473 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
4474 false, tf_warning_or_error
);
4476 /* Add this to the promise CTOR arguments list, accounting for
4477 refs and special handling for method this ptr. */
4478 if (parm
.this_ptr
|| parm
.lambda_cobj
)
4480 /* We pass a reference to *this to the param preview. */
4481 tree tt
= TREE_TYPE (arg
);
4482 gcc_checking_assert (POINTER_TYPE_P (tt
));
4483 tree ct
= TREE_TYPE (tt
);
4484 tree this_ref
= build1 (INDIRECT_REF
, ct
, arg
);
4485 tree rt
= cp_build_reference_type (ct
, false);
4486 this_ref
= convert_to_reference (rt
, this_ref
, CONV_STATIC
,
4487 LOOKUP_NORMAL
, NULL_TREE
,
4488 tf_warning_or_error
);
4489 vec_safe_push (promise_args
, this_ref
);
4491 else if (parm
.by_ref
)
4492 vec_safe_push (promise_args
, fld_idx
);
4494 vec_safe_push (promise_args
, arg
);
4496 if (TYPE_NEEDS_CONSTRUCTING (parm
.frame_type
))
4498 vec
<tree
, va_gc
> *p_in
;
4499 if (CLASS_TYPE_P (parm
.frame_type
)
4500 && classtype_has_non_deleted_move_ctor (parm
.frame_type
))
4501 p_in
= make_tree_vector_single (move (arg
));
4502 else if (lvalue_p (arg
))
4503 p_in
= make_tree_vector_single (rvalue (arg
));
4505 p_in
= make_tree_vector_single (arg
);
4506 /* Construct in place or move as relevant. */
4507 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
4508 &p_in
, parm
.frame_type
,
4510 tf_warning_or_error
);
4511 release_tree_vector (p_in
);
4515 if (!same_type_p (parm
.frame_type
, DECL_ARG_TYPE (arg
)))
4516 r
= build1_loc (DECL_SOURCE_LOCATION (arg
), CONVERT_EXPR
,
4517 parm
.frame_type
, arg
);
4520 r
= build_modify_expr (fn_start
, fld_idx
, parm
.frame_type
,
4521 INIT_EXPR
, DECL_SOURCE_LOCATION (arg
), r
,
4524 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4526 if (!parm
.trivial_dtor
)
4528 if (param_dtor_list
== NULL
)
4529 param_dtor_list
= make_tree_vector ();
4530 vec_safe_push (param_dtor_list
, parm
.field_id
);
4535 /* Set up the promise. */
4537 = lookup_member (coro_frame_type
, promise_name
,
4538 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4540 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
4541 false, tf_warning_or_error
);
4543 if (TYPE_NEEDS_CONSTRUCTING (promise_type
))
4545 /* Do a placement new constructor for the promise type (we never call
4546 the new operator, just the constructor on the object in place in the
4549 First try to find a constructor with the same parameter list as the
4550 original function (if it has params), failing that find a constructor
4551 with no parameter list. */
4553 if (DECL_ARGUMENTS (orig
))
4555 r
= build_special_member_call (p
, complete_ctor_identifier
,
4556 &promise_args
, promise_type
,
4557 LOOKUP_NORMAL
, tf_none
);
4558 release_tree_vector (promise_args
);
4563 if (r
== NULL_TREE
|| r
== error_mark_node
)
4564 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
4565 promise_type
, LOOKUP_NORMAL
,
4566 tf_warning_or_error
);
4568 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4572 /* Set up a new bind context for the GRO. */
4573 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4574 /* Make and connect the scope blocks. */
4575 tree gro_block
= make_node (BLOCK
);
4576 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
4577 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
4578 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
4579 add_stmt (gro_context_bind
);
4582 = coro_build_promise_expression (orig
, p
,
4583 coro_get_return_object_identifier
,
4584 fn_start
, NULL
, /*musthave=*/true);
4585 /* Without a return object we haven't got much clue what's going on. */
4586 if (get_ro
== error_mark_node
)
4588 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4589 DECL_SAVED_TREE (orig
) = newbody
;
4590 /* Suppress warnings about the missing return value. */
4591 TREE_NO_WARNING (orig
) = true;
4595 tree gro_context_body
= push_stmt_list ();
4596 tree gro_type
= TREE_TYPE (get_ro
);
4597 bool gro_is_void_p
= VOID_TYPE_P (gro_type
);
4599 tree gro
= NULL_TREE
;
4600 tree gro_bind_vars
= NULL_TREE
;
4601 tree gro_cleanup_stmt
= NULL_TREE
;
4602 /* We have to sequence the call to get_return_object before initial
4606 else if (same_type_p (gro_type
, fn_return_type
))
4608 /* [dcl.fct.def.coroutine] / 7
4609 The expression promise.get_return_object() is used to initialize the
4610 glvalue result or... (see below)
4611 Construct the return result directly. */
4612 if (TYPE_NEEDS_CONSTRUCTING (gro_type
))
4614 vec
<tree
, va_gc
> *arg
= make_tree_vector_single (get_ro
);
4615 r
= build_special_member_call (DECL_RESULT (orig
),
4616 complete_ctor_identifier
,
4617 &arg
, gro_type
, LOOKUP_NORMAL
,
4618 tf_warning_or_error
);
4619 release_tree_vector (arg
);
4622 r
= build2_loc (fn_start
, INIT_EXPR
, gro_type
,
4623 DECL_RESULT (orig
), get_ro
);
4627 /* ... or ... Construct an object that will be used as the single
4628 param to the CTOR for the return object. */
4629 gro
= build_lang_decl (VAR_DECL
, get_identifier ("coro.gro"), gro_type
);
4630 DECL_CONTEXT (gro
) = current_scope ();
4631 DECL_ARTIFICIAL (gro
) = true;
4632 DECL_IGNORED_P (gro
) = true;
4633 add_decl_expr (gro
);
4634 gro_bind_vars
= gro
;
4635 if (TYPE_NEEDS_CONSTRUCTING (gro_type
))
4637 vec
<tree
, va_gc
> *arg
= make_tree_vector_single (get_ro
);
4638 r
= build_special_member_call (gro
, complete_ctor_identifier
,
4639 &arg
, gro_type
, LOOKUP_NORMAL
,
4640 tf_warning_or_error
);
4641 release_tree_vector (arg
);
4644 r
= build2_loc (fn_start
, INIT_EXPR
, gro_type
, gro
, get_ro
);
4645 /* The constructed object might require a cleanup. */
4646 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type
))
4649 = build_special_member_call (gro
, complete_dtor_identifier
,
4650 NULL
, gro_type
, LOOKUP_NORMAL
,
4651 tf_warning_or_error
);
4652 gro_cleanup_stmt
= build_stmt (input_location
, CLEANUP_STMT
, NULL
,
4656 finish_expr_stmt (r
);
4658 if (gro_cleanup_stmt
)
4659 CLEANUP_BODY (gro_cleanup_stmt
) = push_stmt_list ();
4661 /* Initialize the resume_idx_name to 0, meaning "not started". */
4663 = lookup_member (coro_frame_type
, resume_idx_name
,
4664 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4666 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
4667 tf_warning_or_error
);
4668 r
= build_int_cst (short_unsigned_type_node
, 0);
4669 r
= build2_loc (fn_start
, INIT_EXPR
, short_unsigned_type_node
, resume_idx
, r
);
4670 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4673 /* So .. call the actor .. */
4674 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
4675 r
= maybe_cleanup_point_expr_void (r
);
4678 /* Switch to using 'input_location' as the loc, since we're now more
4679 logically doing things related to the end of the function. */
4681 /* The ramp is done, we just need the return value.
4682 [dcl.fct.def.coroutine] / 7
4683 The expression promise.get_return_object() is used to initialize the
4684 glvalue result or prvalue result object of a call to a coroutine.
4686 If the 'get return object' is non-void, then we built it before the
4687 promise was constructed. We now supply a reference to that var,
4688 either as the return value (if it's the same type) or to the CTOR
4689 for an object of the return type. */
4691 if (same_type_p (gro_type
, fn_return_type
))
4692 r
= gro_is_void_p
? NULL_TREE
: DECL_RESULT (orig
);
4695 if (CLASS_TYPE_P (fn_return_type
))
4697 /* For class type return objects, we can attempt to construct,
4698 even if the gro is void. */
4699 vec
<tree
, va_gc
> *args
= NULL
;
4700 vec
<tree
, va_gc
> **arglist
= NULL
;
4703 args
= make_tree_vector_single (rvalue (gro
));
4706 r
= build_special_member_call (NULL_TREE
,
4707 complete_ctor_identifier
, arglist
,
4708 fn_return_type
, LOOKUP_NORMAL
,
4709 tf_warning_or_error
);
4710 r
= build_cplus_new (fn_return_type
, r
, tf_warning_or_error
);
4712 release_tree_vector (args
);
4714 else if (gro_is_void_p
)
4716 /* We can't initialize a non-class return value from void. */
4717 error_at (input_location
, "cannot initialize a return object of type"
4718 " %qT with an rvalue of type %<void%>", fn_return_type
);
4719 r
= error_mark_node
;
4722 r
= build1_loc (input_location
, CONVERT_EXPR
,
4723 fn_return_type
, rvalue (gro
));
4726 finish_return_stmt (r
);
4728 if (gro_cleanup_stmt
)
4730 CLEANUP_BODY (gro_cleanup_stmt
)
4731 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt
));
4732 add_stmt (gro_cleanup_stmt
);
4735 /* Finish up the ramp function. */
4736 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
4737 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
4738 TREE_SIDE_EFFECTS (gro_context_bind
) = true;
4739 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4740 TREE_SIDE_EFFECTS (ramp_bind
) = true;
4742 /* Start to build the final functions.
4744 We push_deferring_access_checks to avoid these routines being seen as
4745 nested by the middle end; we are doing the outlining here. */
4747 push_deferring_access_checks (dk_no_check
);
4749 /* Build the actor... */
4750 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
, param_uses
,
4751 &local_var_uses
, param_dtor_list
, resume_fn_field
,
4752 body_aw_points
.await_number
, frame_size
);
4755 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
4757 pop_deferring_access_checks ();
4759 DECL_SAVED_TREE (orig
) = newbody
;
4760 /* Link our new functions into the list. */
4761 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
4762 TREE_CHAIN (actor
) = destroy
;
4763 TREE_CHAIN (orig
) = actor
;
4766 *destroyer
= destroy
;
4768 delete suspend_points
;
4769 suspend_points
= NULL
;
4773 #include "gt-cp-coroutines.h"