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
;
99 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
101 typedef tree compare_type
; /* We only compare the function decl. */
102 static inline hashval_t
hash (coroutine_info
*);
103 static inline hashval_t
hash (const compare_type
&);
104 static inline bool equal (coroutine_info
*, coroutine_info
*);
105 static inline bool equal (coroutine_info
*, const compare_type
&);
108 /* This table holds all the collected coroutine state for coroutines in
109 the current translation unit. */
111 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
113 /* We will initialize state lazily. */
114 static bool coro_initialized
= false;
116 /* Return a hash value for the entry pointed to by INFO.
117 The compare type is a tree, but the only trees we are going use are
118 function decls. We use the DECL_UID as the hash value since that is
119 stable across PCH. */
122 coroutine_info_hasher::hash (coroutine_info
*info
)
124 return DECL_UID (info
->function_decl
);
127 /* Return a hash value for the compare value COMP. */
130 coroutine_info_hasher::hash (const compare_type
& comp
)
132 return DECL_UID (comp
);
135 /* Return true if the entries pointed to by LHS and RHS are for the
139 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
141 return lhs
->function_decl
== rhs
->function_decl
;
145 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
147 return lhs
->function_decl
== rhs
;
150 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
151 entry does not yet exist. */
154 get_or_insert_coroutine_info (tree fn_decl
)
156 gcc_checking_assert (coroutine_info_table
!= NULL
);
158 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
159 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
163 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
164 (*slot
)->function_decl
= fn_decl
;
170 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
173 get_coroutine_info (tree fn_decl
)
175 if (coroutine_info_table
== NULL
)
178 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
179 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
185 /* We will lazily create all the identifiers that are used by coroutines
186 on the first attempt to lookup the traits. */
188 /* Identifiers that are used by all coroutines. */
190 static GTY(()) tree coro_traits_identifier
;
191 static GTY(()) tree coro_handle_identifier
;
192 static GTY(()) tree coro_promise_type_identifier
;
194 /* Required promise method name identifiers. */
196 static GTY(()) tree coro_await_transform_identifier
;
197 static GTY(()) tree coro_initial_suspend_identifier
;
198 static GTY(()) tree coro_final_suspend_identifier
;
199 static GTY(()) tree coro_return_void_identifier
;
200 static GTY(()) tree coro_return_value_identifier
;
201 static GTY(()) tree coro_yield_value_identifier
;
202 static GTY(()) tree coro_resume_identifier
;
203 static GTY(()) tree coro_address_identifier
;
204 static GTY(()) tree coro_from_address_identifier
;
205 static GTY(()) tree coro_get_return_object_identifier
;
206 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
207 static GTY(()) tree coro_unhandled_exception_identifier
;
209 /* Awaitable methods. */
211 static GTY(()) tree coro_await_ready_identifier
;
212 static GTY(()) tree coro_await_suspend_identifier
;
213 static GTY(()) tree coro_await_resume_identifier
;
215 /* Create the identifiers used by the coroutines library interfaces. */
218 coro_init_identifiers ()
220 coro_traits_identifier
= get_identifier ("coroutine_traits");
221 coro_handle_identifier
= get_identifier ("coroutine_handle");
222 coro_promise_type_identifier
= get_identifier ("promise_type");
224 coro_await_transform_identifier
= get_identifier ("await_transform");
225 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
226 coro_final_suspend_identifier
= get_identifier ("final_suspend");
227 coro_return_void_identifier
= get_identifier ("return_void");
228 coro_return_value_identifier
= get_identifier ("return_value");
229 coro_yield_value_identifier
= get_identifier ("yield_value");
230 coro_resume_identifier
= get_identifier ("resume");
231 coro_address_identifier
= get_identifier ("address");
232 coro_from_address_identifier
= get_identifier ("from_address");
233 coro_get_return_object_identifier
= get_identifier ("get_return_object");
234 coro_gro_on_allocation_fail_identifier
=
235 get_identifier ("get_return_object_on_allocation_failure");
236 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
238 coro_await_ready_identifier
= get_identifier ("await_ready");
239 coro_await_suspend_identifier
= get_identifier ("await_suspend");
240 coro_await_resume_identifier
= get_identifier ("await_resume");
243 /* Trees we only need to set up once. */
245 static GTY(()) tree coro_traits_templ
;
246 static GTY(()) tree coro_handle_templ
;
247 static GTY(()) tree void_coro_handle_type
;
249 /* ================= Parse, Semantics and Type checking ================= */
251 /* This initial set of routines are helper for the parsing and template
254 At the completion of this, we will have completed trees for each of the
255 keywords, but making use of proxy variables for the self-handle and the
256 promise class instance. */
258 /* [coroutine.traits]
259 Lookup the coroutine_traits template decl. */
262 find_coro_traits_template_decl (location_t kw
)
264 /* If we are missing fundamental information, such as the traits, (or the
265 declaration found is not a type template), then don't emit an error for
266 every keyword in a TU, just do it once. */
267 static bool traits_error_emitted
= false;
269 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
271 /*complain=*/!traits_error_emitted
);
272 if (traits_decl
== error_mark_node
273 || !DECL_TYPE_TEMPLATE_P (traits_decl
))
275 if (!traits_error_emitted
)
277 gcc_rich_location
richloc (kw
);
278 error_at (&richloc
, "coroutines require a traits template; cannot"
279 " find %<%E::%E%>", std_node
, coro_traits_identifier
);
280 inform (&richloc
, "perhaps %<#include <coroutine>%> is missing");
281 traits_error_emitted
= true;
289 /* Instantiate Coroutine traits for the function signature. */
292 instantiate_coro_traits (tree fndecl
, location_t kw
)
294 /* [coroutine.traits.primary]
295 So now build up a type list for the template <typename _R, typename...>.
296 The types are the function's arg types and _R is the function return
299 tree functyp
= TREE_TYPE (fndecl
);
300 tree arg
= DECL_ARGUMENTS (fndecl
);
301 tree arg_node
= TYPE_ARG_TYPES (functyp
);
302 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
305 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
307 if (is_this_parameter (arg
)
308 || DECL_NAME (arg
) == closure_identifier
)
310 /* We pass a reference to *this to the param preview. */
311 tree ct
= TREE_TYPE (TREE_TYPE (arg
));
312 TREE_VEC_ELT (argtypes
, p
++) = cp_build_reference_type (ct
, false);
315 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
317 arg_node
= TREE_CHAIN (arg_node
);
318 arg
= DECL_CHAIN (arg
);
321 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
322 SET_ARGUMENT_PACK_ARGS (argtypepack
, argtypes
);
324 tree targ
= make_tree_vec (2);
325 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
326 TREE_VEC_ELT (targ
, 1) = argtypepack
;
329 = lookup_template_class (coro_traits_templ
, targ
,
330 /*in_decl=*/NULL_TREE
, /*context=*/NULL_TREE
,
331 /*entering scope=*/false, tf_warning_or_error
);
333 if (traits_class
== error_mark_node
)
335 error_at (kw
, "cannot instantiate %<coroutine traits%>");
342 /* [coroutine.handle] */
345 find_coro_handle_template_decl (location_t kw
)
347 /* As for the coroutine traits, this error is per TU, so only emit
349 static bool coro_handle_error_emitted
= false;
350 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
352 !coro_handle_error_emitted
);
353 if (handle_decl
== error_mark_node
354 || !DECL_CLASS_TEMPLATE_P (handle_decl
))
356 if (!coro_handle_error_emitted
)
357 error_at (kw
, "coroutines require a handle class template;"
358 " cannot find %<%E::%E%>", std_node
, coro_handle_identifier
);
359 coro_handle_error_emitted
= true;
366 /* Instantiate the handle template for a given promise type. */
369 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
371 /* So now build up a type list for the template, one entry, the promise. */
372 tree targ
= make_tree_vec (1);
373 TREE_VEC_ELT (targ
, 0) = promise_type
;
375 = lookup_template_class (coro_handle_identifier
, targ
,
376 /* in_decl=*/NULL_TREE
,
377 /* context=*/std_node
,
378 /* entering scope=*/false, tf_warning_or_error
);
380 if (handle_type
== error_mark_node
)
382 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
383 " promise type %qT", promise_type
);
390 /* Look for the promise_type in the instantiated traits. */
393 find_promise_type (tree traits_class
)
396 = lookup_member (traits_class
, coro_promise_type_identifier
,
397 /* protect=*/1, /*want_type=*/true, tf_warning_or_error
);
401 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
403 /* NULL_TREE on fail. */
408 coro_promise_type_found_p (tree fndecl
, location_t loc
)
410 gcc_assert (fndecl
!= NULL_TREE
);
412 if (!coro_initialized
)
414 /* Trees we only need to create once.
415 Set up the identifiers we will use. */
416 coro_init_identifiers ();
418 /* Coroutine traits template. */
419 coro_traits_templ
= find_coro_traits_template_decl (loc
);
420 if (coro_traits_templ
== NULL_TREE
)
423 /* coroutine_handle<> template. */
424 coro_handle_templ
= find_coro_handle_template_decl (loc
);
425 if (coro_handle_templ
== NULL_TREE
)
428 /* We can also instantiate the void coroutine_handle<> */
429 void_coro_handle_type
=
430 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
431 if (void_coro_handle_type
== NULL_TREE
)
434 /* A table to hold the state, per coroutine decl. */
435 gcc_checking_assert (coroutine_info_table
== NULL
);
436 coroutine_info_table
=
437 hash_table
<coroutine_info_hasher
>::create_ggc (11);
439 if (coroutine_info_table
== NULL
)
442 coro_initialized
= true;
445 /* Save the coroutine data on the side to avoid the overhead on every
446 function decl tree. */
448 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
449 /* Without this, we cannot really proceed. */
450 gcc_checking_assert (coro_info
);
452 /* If we don't already have a current promise type, try to look it up. */
453 if (coro_info
->promise_type
== NULL_TREE
)
455 /* Get the coroutine traits template class instance for the function
456 signature we have - coroutine_traits <R, ...> */
458 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
460 /* Find the promise type for that. */
461 coro_info
->promise_type
= find_promise_type (templ_class
);
463 /* If we don't find it, punt on the rest. */
464 if (coro_info
->promise_type
== NULL_TREE
)
466 if (!coro_info
->coro_promise_error_emitted
)
467 error_at (loc
, "unable to find the promise type for"
469 coro_info
->coro_promise_error_emitted
= true;
473 /* Try to find the handle type for the promise. */
475 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
476 if (handle_type
== NULL_TREE
)
479 /* Complete this, we're going to use it. */
480 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
482 /* Diagnostic would be emitted by complete_type_or_else. */
483 if (!coro_info
->handle_type
)
486 /* Build a proxy for a handle to "self" as the param to
487 await_suspend() calls. */
488 coro_info
->self_h_proxy
489 = build_lang_decl (VAR_DECL
, get_identifier ("self_h.proxy"),
490 coro_info
->handle_type
);
492 /* Build a proxy for the promise so that we can perform lookups. */
493 coro_info
->promise_proxy
494 = build_lang_decl (VAR_DECL
, get_identifier ("promise.proxy"),
495 coro_info
->promise_type
);
497 /* Note where we first saw a coroutine keyword. */
498 coro_info
->first_coro_keyword
= loc
;
504 /* These functions assumes that the caller has verified that the state for
505 the decl has been initialized, we try to minimize work here. */
508 get_coroutine_promise_type (tree decl
)
510 if (coroutine_info
*info
= get_coroutine_info (decl
))
511 return info
->promise_type
;
517 get_coroutine_handle_type (tree decl
)
519 if (coroutine_info
*info
= get_coroutine_info (decl
))
520 return info
->handle_type
;
526 get_coroutine_self_handle_proxy (tree decl
)
528 if (coroutine_info
*info
= get_coroutine_info (decl
))
529 return info
->self_h_proxy
;
535 get_coroutine_promise_proxy (tree decl
)
537 if (coroutine_info
*info
= get_coroutine_info (decl
))
538 return info
->promise_proxy
;
544 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
547 tree promise
= get_coroutine_promise_type (fndecl
);
549 = lookup_member (promise
, member_id
,
550 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
551 if (musthave
&& pm_memb
== NULL_TREE
)
553 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
554 return error_mark_node
;
559 /* Build an expression of the form p.method (args) where the p is a promise
560 object for the current coroutine.
561 OBJECT is the promise object instance to use, it may be NULL, in which case
562 we will use the promise_proxy instance for this coroutine.
563 ARGS may be NULL, for empty parm lists. */
566 coro_build_promise_expression (tree fn
, tree promise_obj
, tree member_id
,
567 location_t loc
, vec
<tree
, va_gc
> **args
,
570 tree meth
= lookup_promise_method (fn
, member_id
, loc
, musthave
);
571 if (meth
== error_mark_node
)
572 return error_mark_node
;
574 /* If we don't find it, and it isn't needed, an empty return is OK. */
579 = promise_obj
? promise_obj
580 : get_coroutine_promise_proxy (current_function_decl
);
582 if (BASELINK_P (meth
))
583 expr
= build_new_method_call (promise
, meth
, args
, NULL_TREE
,
584 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
587 expr
= build_class_member_access_expr (promise
, meth
, NULL_TREE
,
588 true, tf_warning_or_error
);
589 vec
<tree
, va_gc
> *real_args
;
591 real_args
= make_tree_vector ();
594 expr
= build_op_call (expr
, &real_args
, tf_warning_or_error
);
599 /* Caching get for the expression p.return_void (). */
602 get_coroutine_return_void_expr (tree decl
, location_t loc
, bool musthave
)
604 if (coroutine_info
*info
= get_coroutine_info (decl
))
606 /* If we don't have it try to build it. */
607 if (!info
->return_void
)
609 = coro_build_promise_expression (current_function_decl
, NULL
,
610 coro_return_void_identifier
,
611 loc
, NULL
, musthave
);
612 /* Don't return an error if it's an optional call. */
613 if (!musthave
&& info
->return_void
== error_mark_node
)
615 return info
->return_void
;
617 return musthave
? error_mark_node
: NULL_TREE
;
620 /* Lookup an Awaitable member, which should be await_ready, await_suspend
624 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
627 = lookup_member (await_type
, member_id
,
628 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
629 if (aw_memb
== NULL_TREE
)
631 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
632 return error_mark_node
;
637 /* Here we check the constraints that are common to all keywords (since the
638 presence of a coroutine keyword makes the function into a coroutine). */
641 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
644 if (fndecl
== NULL_TREE
)
646 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
650 /* This is arranged in order of prohibitions in the std. */
651 if (DECL_MAIN_P (fndecl
))
653 /* [basic.start.main] 3. The function main shall not be a coroutine. */
654 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
659 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
661 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
662 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
664 cp_function_chain
->invalid_constexpr
= true;
668 if (FNDECL_USED_AUTO (fndecl
))
670 /* [dcl.spec.auto] 15. A function declared with a return type that uses
671 a placeholder type shall not be a coroutine. */
673 "%qs cannot be used in a function with a deduced return type",
678 if (varargs_function_p (fndecl
))
680 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
681 coroutine shall not terminate with an ellipsis that is not part
682 of a parameter-declaration. */
684 "%qs cannot be used in a varargs function", kw_name
);
688 if (DECL_CONSTRUCTOR_P (fndecl
))
690 /* [class.ctor] 7. a constructor shall not be a coroutine. */
691 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
695 if (DECL_DESTRUCTOR_P (fndecl
))
697 /* [class.dtor] 21. a destructor shall not be a coroutine. */
698 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
705 /* Here we check the constraints that are not per keyword. */
708 coro_function_valid_p (tree fndecl
)
710 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
712 /* For cases where fundamental information cannot be found, e.g. the
713 coroutine traits are missing, we need to punt early. */
714 if (!coro_promise_type_found_p (fndecl
, f_loc
))
717 /* Since we think the function is a coroutine, that implies we parsed
718 a keyword that triggered this. Keywords check promise validity for
719 their context and thus the promise type should be known at this point. */
720 if (get_coroutine_handle_type (fndecl
) == NULL_TREE
721 || get_coroutine_promise_type (fndecl
) == NULL_TREE
)
724 if (current_function_returns_value
|| current_function_returns_null
)
726 /* TODO: record or extract positions of returns (and the first coro
727 keyword) so that we can add notes to the diagnostic about where
728 the bad keyword is and what made the function into a coro. */
729 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
730 " did you mean %<co_return%>?");
737 enum suspend_point_kind
{
738 CO_AWAIT_SUSPEND_POINT
= 0,
739 CO_YIELD_SUSPEND_POINT
,
740 INITIAL_SUSPEND_POINT
,
744 /* Helper function to build a named variable for the temps we use for each
745 await point. The root of the name is determined by SUSPEND_KIND, and
746 the variable is of type V_TYPE. The awaitable number is reset each time
747 we encounter a final suspend. */
750 get_awaitable_var (suspend_point_kind suspend_kind
, tree v_type
)
754 switch (suspend_kind
)
756 default: buf
= xasprintf ("Aw%d", awn
++); break;
757 case CO_YIELD_SUSPEND_POINT
: buf
= xasprintf ("Yd%d", awn
++); break;
758 case INITIAL_SUSPEND_POINT
: buf
= xasprintf ("Is"); break;
759 case FINAL_SUSPEND_POINT
: buf
= xasprintf ("Fs"); awn
= 0; break;
761 tree ret
= get_identifier (buf
);
763 ret
= build_lang_decl (VAR_DECL
, ret
, v_type
);
764 DECL_ARTIFICIAL (ret
) = true;
768 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
769 It is also used to build the initial and final suspend points.
771 'a', 'o' and 'e' are used as per the description in the section noted.
773 A, the original yield/await expr, is found at source location LOC.
775 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
776 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
779 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
781 /* Try and overload of operator co_await, .... */
783 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
785 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
786 NULL_TREE
, NULL
, tf_warning_or_error
);
787 /* If no viable functions are found, o is a. */
788 if (!o
|| o
== error_mark_node
)
792 o
= a
; /* This is most likely about to fail anyway. */
794 tree o_type
= TREE_TYPE (o
);
795 if (o_type
&& !VOID_TYPE_P (o_type
))
796 o_type
= complete_type_or_else (o_type
, o
);
799 return error_mark_node
;
801 if (TREE_CODE (o_type
) != RECORD_TYPE
)
803 error_at (loc
, "awaitable type %qT is not a structure",
805 return error_mark_node
;
808 /* Check for required awaitable members and their types. */
810 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
811 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
812 return error_mark_node
;
814 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
815 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
816 return error_mark_node
;
818 /* The type of the co_await is the return type of the awaitable's
819 await_resume, so we need to look that up. */
821 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
822 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
823 return error_mark_node
;
825 /* To complete the lookups, we need an instance of 'e' which is built from
826 'o' according to [expr.await] 3.4.
828 If we need to materialize this as a temporary, then that will have to be
829 'promoted' to a coroutine frame var. However, if the awaitable is a
830 user variable, parameter or comes from a scope outside this function,
831 then we must use it directly - or we will see unnecessary copies.
833 If o is a variable, find the underlying var. */
834 tree e_proxy
= STRIP_NOPS (o
);
835 if (INDIRECT_REF_P (e_proxy
))
836 e_proxy
= TREE_OPERAND (e_proxy
, 0);
837 while (TREE_CODE (e_proxy
) == COMPONENT_REF
)
839 e_proxy
= TREE_OPERAND (e_proxy
, 0);
840 if (INDIRECT_REF_P (e_proxy
))
841 e_proxy
= TREE_OPERAND (e_proxy
, 0);
842 if (TREE_CODE (e_proxy
) == CALL_EXPR
)
844 /* We could have operator-> here too. */
845 tree op
= TREE_OPERAND (CALL_EXPR_FN (e_proxy
), 0);
846 if (DECL_OVERLOADED_OPERATOR_P (op
)
847 && DECL_OVERLOADED_OPERATOR_IS (op
, COMPONENT_REF
))
849 e_proxy
= CALL_EXPR_ARG (e_proxy
, 0);
850 STRIP_NOPS (e_proxy
);
851 gcc_checking_assert (TREE_CODE (e_proxy
) == ADDR_EXPR
);
852 e_proxy
= TREE_OPERAND (e_proxy
, 0);
855 STRIP_NOPS (e_proxy
);
858 /* Only build a temporary if we need it. */
859 if (TREE_CODE (e_proxy
) == PARM_DECL
860 || (VAR_P (e_proxy
) && !is_local_temp (e_proxy
)))
863 o
= NULL_TREE
; /* The var is already present. */
865 else if (CLASS_TYPE_P (o_type
) || TYPE_NEEDS_CONSTRUCTING (o_type
))
867 e_proxy
= get_awaitable_var (suspend_kind
, o_type
);
868 releasing_vec
arg (make_tree_vector_single (rvalue (o
)));
869 o
= build_special_member_call (e_proxy
, complete_ctor_identifier
,
870 &arg
, o_type
, LOOKUP_NORMAL
,
871 tf_warning_or_error
);
875 e_proxy
= get_awaitable_var (suspend_kind
, o_type
);
876 o
= build2 (INIT_EXPR
, o_type
, e_proxy
, rvalue (o
));
879 /* I suppose we could check that this is contextually convertible to bool. */
880 tree awrd_func
= NULL_TREE
;
882 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
883 &awrd_func
, tf_warning_or_error
);
885 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
886 return error_mark_node
;
888 /* The suspend method may return one of three types:
889 1. void (no special action needed).
890 2. bool (if true, we don't need to suspend).
891 3. a coroutine handle, we execute the handle.resume() call. */
892 tree awsp_func
= NULL_TREE
;
893 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
894 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
896 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
897 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
899 release_tree_vector (args
);
900 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
901 return error_mark_node
;
904 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
905 if (same_type_p (susp_return_type
, void_type_node
))
907 else if (same_type_p (susp_return_type
, boolean_type_node
))
909 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
910 && CLASS_TYPE_P (susp_return_type
))
912 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
913 if (tt
== coro_handle_templ
)
919 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
920 " a coroutine handle");
921 return error_mark_node
;
924 /* Finally, the type of e.await_resume() is the co_await's type. */
925 tree awrs_func
= NULL_TREE
;
927 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
928 &awrs_func
, tf_warning_or_error
);
930 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
931 return error_mark_node
;
933 /* We now have three call expressions, in terms of the promise, handle and
934 'e' proxies. Save them in the await expression for later expansion. */
936 tree awaiter_calls
= make_tree_vec (3);
937 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
938 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
940 if (TREE_CODE (awrs_call
) == TARGET_EXPR
)
943 awrs_call
= TREE_OPERAND (awrs_call
, 1);
945 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
947 tree await_expr
= build5_loc (loc
, CO_AWAIT_EXPR
,
948 TREE_TYPE (TREE_TYPE (awrs_func
)),
949 a
, e_proxy
, o
, awaiter_calls
,
950 build_int_cst (integer_type_node
,
951 (int) suspend_kind
));
954 TREE_OPERAND (te
, 1) = await_expr
;
957 tree t
= convert_from_reference (await_expr
);
962 finish_co_await_expr (location_t kw
, tree expr
)
964 if (!expr
|| error_operand_p (expr
))
965 return error_mark_node
;
967 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
969 return error_mark_node
;
971 /* The current function has now become a coroutine, if it wasn't already. */
972 DECL_COROUTINE_P (current_function_decl
) = 1;
974 /* This function will appear to have no return statement, even if it
975 is declared to return non-void (most likely). This is correct - we
976 synthesize the return for the ramp in the compiler. So suppress any
977 extraneous warnings during substitution. */
978 TREE_NO_WARNING (current_function_decl
) = true;
980 /* If we don't know the promise type, we can't proceed, build the
981 co_await with the expression unchanged. */
982 tree functype
= TREE_TYPE (current_function_decl
);
983 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
984 return build5_loc (kw
, CO_AWAIT_EXPR
, unknown_type_node
, expr
,
985 NULL_TREE
, NULL_TREE
, NULL_TREE
, integer_zero_node
);
987 /* We must be able to look up the "await_transform" method in the scope of
988 the promise type, and obtain its return type. */
989 if (!coro_promise_type_found_p (current_function_decl
, kw
))
990 return error_mark_node
;
993 The incoming cast expression might be transformed by a promise
994 'await_transform()'. */
996 = lookup_promise_method (current_function_decl
,
997 coro_await_transform_identifier
, kw
,
999 if (at_meth
== error_mark_node
)
1000 return error_mark_node
;
1005 /* try to build a = p.await_transform (e). */
1006 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1007 a
= build_new_method_call (get_coroutine_promise_proxy (
1008 current_function_decl
),
1009 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
1010 NULL
, tf_warning_or_error
);
1012 /* As I read the section.
1013 We saw an await_transform method, so it's mandatory that we replace
1014 expr with p.await_transform (expr), therefore if the method call fails
1015 (presumably, we don't have suitable arguments) then this part of the
1017 if (a
== error_mark_node
)
1018 return error_mark_node
;
1021 /* Now we want to build co_await a. */
1022 tree op
= build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
1023 if (op
!= error_mark_node
)
1025 TREE_SIDE_EFFECTS (op
) = 1;
1026 SET_EXPR_LOCATION (op
, kw
);
1032 /* Take the EXPR given and attempt to build:
1033 co_await p.yield_value (expr);
1034 per [expr.yield] para 1. */
1037 finish_co_yield_expr (location_t kw
, tree expr
)
1039 if (!expr
|| error_operand_p (expr
))
1040 return error_mark_node
;
1042 /* Check the general requirements and simple syntax errors. */
1043 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1045 return error_mark_node
;
1047 /* The current function has now become a coroutine, if it wasn't already. */
1048 DECL_COROUTINE_P (current_function_decl
) = 1;
1050 /* This function will appear to have no return statement, even if it
1051 is declared to return non-void (most likely). This is correct - we
1052 synthesize the return for the ramp in the compiler. So suppress any
1053 extraneous warnings during substitution. */
1054 TREE_NO_WARNING (current_function_decl
) = true;
1056 /* If we don't know the promise type, we can't proceed, build the
1057 co_await with the expression unchanged. */
1058 tree functype
= TREE_TYPE (current_function_decl
);
1059 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1060 return build2_loc (kw
, CO_YIELD_EXPR
, unknown_type_node
, expr
, NULL_TREE
);
1062 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1063 /* We must be able to look up the "yield_value" method in the scope of
1064 the promise type, and obtain its return type. */
1065 return error_mark_node
;
1068 Let e be the operand of the yield-expression and p be an lvalue naming
1069 the promise object of the enclosing coroutine, then the yield-expression
1070 is equivalent to the expression co_await p.yield_value(e).
1071 build p.yield_value(e): */
1072 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1074 = coro_build_promise_expression (current_function_decl
, NULL
,
1075 coro_yield_value_identifier
, kw
,
1076 &args
, /*musthave=*/true);
1077 release_tree_vector (args
);
1079 /* Now build co_await p.yield_value (e).
1080 Noting that for co_yield, there is no evaluation of any potential
1081 promise transform_await(), so we call build_co_await directly. */
1083 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
1084 if (op
!= error_mark_node
)
1086 if (REFERENCE_REF_P (op
))
1087 op
= TREE_OPERAND (op
, 0);
1088 /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1089 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1090 its contained await. Otherwise, just build the CO_YIELD_EXPR. */
1091 if (TREE_CODE (op
) == TARGET_EXPR
)
1093 tree t
= TREE_OPERAND (op
, 1);
1094 t
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (t
), expr
, t
);
1095 TREE_OPERAND (op
, 1) = t
;
1098 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
1099 TREE_SIDE_EFFECTS (op
) = 1;
1100 op
= convert_from_reference (op
);
1106 /* Check and build a co_return statement.
1107 First that it's valid to have a co_return keyword here.
1108 If it is, then check and build the p.return_{void(),value(expr)}.
1109 These are built against a proxy for the promise, which will be filled
1110 in with the actual frame version when the function is transformed. */
1113 finish_co_return_stmt (location_t kw
, tree expr
)
1116 STRIP_ANY_LOCATION_WRAPPER (expr
);
1118 if (error_operand_p (expr
))
1119 return error_mark_node
;
1121 /* If it fails the following test, the function is not permitted to be a
1122 coroutine, so the co_return statement is erroneous. */
1123 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
1125 return error_mark_node
;
1127 /* The current function has now become a coroutine, if it wasn't
1129 DECL_COROUTINE_P (current_function_decl
) = 1;
1131 /* This function will appear to have no return statement, even if it
1132 is declared to return non-void (most likely). This is correct - we
1133 synthesize the return for the ramp in the compiler. So suppress any
1134 extraneous warnings during substitution. */
1135 TREE_NO_WARNING (current_function_decl
) = true;
1137 if (processing_template_decl
1138 && check_for_bare_parameter_packs (expr
))
1139 return error_mark_node
;
1141 /* If we don't know the promise type, we can't proceed, build the
1142 co_return with the expression unchanged. */
1143 tree functype
= TREE_TYPE (current_function_decl
);
1144 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1146 /* co_return expressions are always void type, regardless of the
1148 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
,
1150 expr
= maybe_cleanup_point_expr_void (expr
);
1151 return add_stmt (expr
);
1154 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1155 return error_mark_node
;
1157 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1158 whether the promise type has a suitable return_void/return_value. */
1159 TREE_NO_WARNING (current_function_decl
) = true;
1161 if (!processing_template_decl
&& warn_sequence_point
)
1162 verify_sequence_points (expr
);
1166 /* If we had an id-expression obfuscated by force_paren_expr, we need
1167 to undo it so we can try to treat it as an rvalue below. */
1168 expr
= maybe_undo_parenthesized_ref (expr
);
1170 if (processing_template_decl
)
1171 expr
= build_non_dependent_expr (expr
);
1173 if (error_operand_p (expr
))
1174 return error_mark_node
;
1177 /* If the promise object doesn't have the correct return call then
1178 there's a mis-match between the co_return <expr> and this. */
1179 tree co_ret_call
= error_mark_node
;
1180 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
1182 = get_coroutine_return_void_expr (current_function_decl
, kw
, true);
1185 /* [class.copy.elision] / 3.
1186 An implicitly movable entity is a variable of automatic storage
1187 duration that is either a non-volatile object or an rvalue reference
1188 to a non-volatile object type. For such objects in the context of
1189 the co_return, the overload resolution should be carried out first
1190 treating the object as an rvalue, if that fails, then we fall back
1191 to regular overload resolution. */
1194 if (tree moved
= treat_lvalue_as_rvalue_p (expr
, /*return*/true))
1197 releasing_vec args
= make_tree_vector_single (arg
);
1199 = coro_build_promise_expression (current_function_decl
, NULL
,
1200 coro_return_value_identifier
, kw
,
1201 &args
, /*musthave=*/true);
1204 /* Makes no sense for a co-routine really. */
1205 if (TREE_THIS_VOLATILE (current_function_decl
))
1207 "function declared %<noreturn%> has a"
1208 " %<co_return%> statement");
1210 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
1211 expr
= maybe_cleanup_point_expr_void (expr
);
1212 return add_stmt (expr
);
1215 /* We need to validate the arguments to __builtin_coro_promise, since the
1216 second two must be constant, and the builtins machinery doesn't seem to
1217 deal with that properly. */
1220 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
1222 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1224 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1225 switch (DECL_FUNCTION_CODE (fn
))
1230 case BUILT_IN_CORO_PROMISE
:
1232 /* Argument 0 is already checked by the normal built-in machinery
1233 Argument 1 must be a constant of size type. It probably makes
1234 little sense if it's not a power of 2, but that isn't specified
1236 tree arg
= CALL_EXPR_ARG (call
, 1);
1237 location_t loc
= EXPR_LOCATION (arg
);
1239 /* We expect alignof expressions in templates. */
1240 if (TREE_CODE (arg
) == NON_DEPENDENT_EXPR
1241 && TREE_CODE (TREE_OPERAND (arg
, 0)) == ALIGNOF_EXPR
)
1243 else if (!TREE_CONSTANT (arg
))
1245 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1246 " must be a constant");
1247 return error_mark_node
;
1249 /* Argument 2 is the direction - to / from handle address to promise
1251 arg
= CALL_EXPR_ARG (call
, 2);
1252 loc
= EXPR_LOCATION (arg
);
1253 if (!TREE_CONSTANT (arg
))
1255 error_at (loc
, "the direction argument to"
1256 " %<__builtin_coro_promise%> must be a constant");
1257 return error_mark_node
;
1265 /* ================= Morph and Expand. =================
1267 The entry point here is morph_fn_to_coro () which is called from
1268 finish_function () when we have completed any template expansion.
1270 This is preceded by helper functions that implement the phases below.
1272 The process proceeds in four phases.
1275 The user's function body is wrapped in the initial and final suspend
1276 points and we begin building the coroutine frame.
1277 We build empty decls for the actor and destroyer functions at this
1279 When exceptions are enabled, the user's function body will also be
1280 wrapped in a try-catch block with the catch invoking the promise
1281 class 'unhandled_exception' method.
1284 The user's function body is analyzed to determine the suspend points,
1285 if any, and to capture local variables that might persist across such
1286 suspensions. In most cases, it is not necessary to capture compiler
1287 temporaries, since the tree-lowering nests the suspensions correctly.
1288 However, in the case of a captured reference, there is a lifetime
1289 extension to the end of the full expression - which can mean across a
1290 suspend point in which case it must be promoted to a frame variable.
1292 At the conclusion of analysis, we have a conservative frame layout and
1293 maps of the local variables to their frame entry points.
1295 C Build the ramp function.
1296 Carry out the allocation for the coroutine frame (NOTE; the actual size
1297 computation is deferred until late in the middle end to allow for future
1298 optimizations that will be allowed to elide unused frame entries).
1299 We build the return object.
1301 D Build and expand the actor and destroyer function bodies.
1302 The destroyer is a trivial shim that sets a bit to indicate that the
1303 destroy dispatcher should be used and then calls into the actor.
1305 The actor function is the implementation of the user's state machine.
1306 The current suspend point is noted in an index.
1307 Each suspend point is encoded as a pair of internal functions, one in
1308 the relevant dispatcher, and one representing the suspend point.
1310 During this process, the user's local variables and the proxies for the
1311 self-handle and the promise class instance are re-written to their
1312 coroutine frame equivalents.
1314 The complete bodies for the ramp, actor and destroy function are passed
1315 back to finish_function for folding and gimplification. */
1317 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1320 coro_build_expr_stmt (tree expr
, location_t loc
)
1322 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1326 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1328 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1329 return coro_build_expr_stmt (t
, loc
);
1332 /* Helpers for label creation:
1333 1. Create a named label in the specified context. */
1336 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1338 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1340 DECL_CONTEXT (lab
) = ctx
;
1341 DECL_ARTIFICIAL (lab
) = true;
1342 DECL_IGNORED_P (lab
) = true;
1343 TREE_USED (lab
) = true;
1347 /* 2. Create a named label in the specified context. */
1350 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1352 tree lab_id
= get_identifier (name
);
1353 tree lab
= define_label (loc
, lab_id
);
1354 DECL_CONTEXT (lab
) = ctx
;
1355 DECL_ARTIFICIAL (lab
) = true;
1356 TREE_USED (lab
) = true;
1360 struct proxy_replace
1366 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1368 proxy_replace
*data
= (proxy_replace
*) d
;
1370 if (*here
== data
->from
)
1380 /* Support for expansion of co_await statements. */
1384 tree actor_fn
; /* Decl for context. */
1385 tree coro_fp
; /* Frame pointer var. */
1386 tree resume_idx
; /* This is the index var in the frame. */
1387 tree i_a_r_c
; /* initial suspend await_resume() was called if true. */
1388 tree self_h
; /* This is a handle to the current coro (frame var). */
1389 tree cleanup
; /* This is where to go once we complete local destroy. */
1390 tree cororet
; /* This is where to go if we suspend. */
1391 tree corocont
; /* This is where to go if we continue. */
1392 tree conthand
; /* This is the handle for a continuation. */
1393 unsigned index
; /* This is our current resume index. */
1396 /* Lightweight search for the first await expression in tree-walk order.
1398 The first await expression found in STMT.
1399 NULL_TREE if there are none.
1400 So can be used to determine if the statement needs to be processed for
1404 co_await_find_in_subtree (tree
*stmt
, int *, void *d
)
1406 tree
**p
= (tree
**) d
;
1407 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1415 /* Starting with a statement:
1417 stmt => some tree containing one or more await expressions.
1419 We replace the statement with:
1421 initialize awaitable
1427 revised statement with one await expression rewritten to its
1428 await_resume() return value.
1431 We then recurse into the initializer and the revised statement
1432 repeating this replacement until there are no more await expressions
1436 expand_one_await_expression (tree
*stmt
, tree
*await_expr
, void *d
)
1438 coro_aw_data
*data
= (coro_aw_data
*) d
;
1440 tree saved_statement
= *stmt
;
1441 tree saved_co_await
= *await_expr
;
1443 tree actor
= data
->actor_fn
;
1444 location_t loc
= EXPR_LOCATION (*stmt
);
1445 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1446 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1447 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1449 tree source
= TREE_OPERAND (saved_co_await
, 4);
1450 bool is_final
= (source
1451 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1452 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1453 int resume_point
= data
->index
;
1454 size_t bufsize
= sizeof ("destroy.") + 10;
1455 char *buf
= (char *) alloca (bufsize
);
1456 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1457 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1458 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1459 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1460 tree empty_list
= build_empty_stmt (loc
);
1462 tree await_type
= TREE_TYPE (var
);
1463 tree stmt_list
= NULL
;
1465 tree
*await_init
= NULL
;
1468 needs_dtor
= false; /* No need, the var's lifetime is managed elsewhere. */
1471 r
= coro_build_cvt_void_expr_stmt (expr
, loc
);
1472 append_to_statement_list_force (r
, &stmt_list
);
1473 /* We have an initializer, which might itself contain await exprs. */
1474 await_init
= tsi_stmt_ptr (tsi_last (stmt_list
));
1477 /* Use the await_ready() call to test if we need to suspend. */
1478 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1479 ready_cond
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, ready_cond
);
1481 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1483 tree body_list
= NULL
;
1484 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1485 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1487 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1488 append_to_statement_list (r
, &body_list
);
1490 /* Find out what we have to do with the awaiter's suspend method.
1492 (5.1) If the result of await-ready is false, the coroutine is considered
1494 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1495 await-suspend.resume() is evaluated.
1496 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1497 and the coroutine is resumed if the result is false.
1498 (5.1.3) Otherwise, await-suspend is evaluated. */
1500 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1501 tree susp_type
= TREE_TYPE (suspend
);
1503 bool is_cont
= false;
1504 /* NOTE: final suspend can't resume; the "resume" label in that case
1505 corresponds to implicit destruction. */
1506 if (VOID_TYPE_P (susp_type
))
1508 /* We just call await_suspend() and hit the yield. */
1509 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1510 append_to_statement_list (suspend
, &body_list
);
1512 else if (TREE_CODE (susp_type
) == BOOLEAN_TYPE
)
1514 /* Boolean return, continue if the call returns false. */
1515 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1517 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1518 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1519 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1521 append_to_statement_list (r
, &body_list
);
1525 r
= build1_loc (loc
, CONVERT_EXPR
, void_coro_handle_type
, suspend
);
1526 r
= build2_loc (loc
, INIT_EXPR
, void_coro_handle_type
, data
->conthand
, r
);
1527 r
= build1 (CONVERT_EXPR
, void_type_node
, r
);
1528 append_to_statement_list (r
, &body_list
);
1532 tree d_l
= build_address (destroy_label
);
1533 tree r_l
= build_address (resume_label
);
1534 tree susp
= build_address (data
->cororet
);
1535 tree cont
= build_address (data
->corocont
);
1536 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1538 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1540 tree sw
= begin_switch_stmt ();
1541 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1542 DECL_ARTIFICIAL (cond
) = 1;
1543 DECL_IGNORED_P (cond
) = 1;
1544 layout_decl (cond
, 0);
1546 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1547 susp_idx
, final_susp
, r_l
, d_l
,
1549 r
= build2 (INIT_EXPR
, integer_type_node
, cond
, r
);
1550 finish_switch_cond (r
, sw
);
1551 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1552 create_anon_label_with_ctx (loc
, actor
));
1553 add_stmt (r
); /* case 0: */
1554 /* Implement the suspend, a scope exit without clean ups. */
1555 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1,
1556 is_cont
? cont
: susp
);
1557 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1558 add_stmt (r
); /* goto ret; */
1559 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1560 create_anon_label_with_ctx (loc
, actor
));
1561 add_stmt (r
); /* case 1: */
1562 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1563 add_stmt (r
); /* goto resume; */
1564 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1565 create_anon_label_with_ctx (loc
, actor
));
1566 add_stmt (r
); /* default:; */
1567 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1568 add_stmt (r
); /* goto destroy; */
1570 /* part of finish switch. */
1571 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1573 tree scope
= SWITCH_STMT_SCOPE (sw
);
1574 SWITCH_STMT_SCOPE (sw
) = NULL
;
1575 r
= do_poplevel (scope
);
1576 append_to_statement_list (r
, &body_list
);
1578 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1579 append_to_statement_list (destroy_label
, &body_list
);
1582 tree dtor
= build_special_member_call (var
, complete_dtor_identifier
,
1583 NULL
, await_type
, LOOKUP_NORMAL
,
1584 tf_warning_or_error
);
1585 append_to_statement_list (dtor
, &body_list
);
1587 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1588 append_to_statement_list (r
, &body_list
);
1590 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1593 append_to_statement_list (r
, &stmt_list
);
1596 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1597 append_to_statement_list (resume_label
, &stmt_list
);
1599 /* This will produce the value (if one is provided) from the co_await
1601 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1602 if (REFERENCE_REF_P (resume_call
))
1603 /* Sink to await_resume call_expr. */
1604 resume_call
= TREE_OPERAND (resume_call
, 0);
1606 *await_expr
= resume_call
; /* Replace the co_await expr with its result. */
1607 append_to_statement_list_force (saved_statement
, &stmt_list
);
1608 /* Get a pointer to the revised statement. */
1609 tree
*revised
= tsi_stmt_ptr (tsi_last (stmt_list
));
1612 tree dtor
= build_special_member_call (var
, complete_dtor_identifier
,
1613 NULL
, await_type
, LOOKUP_NORMAL
,
1614 tf_warning_or_error
);
1615 append_to_statement_list (dtor
, &stmt_list
);
1619 /* Replace the original statement with the expansion. */
1622 /* Now, if the awaitable had an initializer, expand any awaits that might
1623 be embedded in it. */
1626 cp_walk_tree (await_init
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1627 expand_one_await_expression (await_init
, aw_expr_ptr
, d
);
1629 /* Expand any more await expressions in the the original statement. */
1630 if (cp_walk_tree (revised
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1631 expand_one_await_expression (revised
, aw_expr_ptr
, d
);
1636 /* Check to see if a statement contains at least one await expression, if
1637 so, then process that. */
1640 process_one_statement (tree
*stmt
, void *d
)
1643 if (cp_walk_tree (stmt
, co_await_find_in_subtree
, &aw_expr_ptr
, NULL
))
1644 expand_one_await_expression (stmt
, aw_expr_ptr
, d
);
1649 await_statement_expander (tree
*stmt
, int *do_subtree
, void *d
)
1651 tree res
= NULL_TREE
;
1653 /* Process a statement at a time. */
1654 if (STATEMENT_CLASS_P (*stmt
) || TREE_CODE (*stmt
) == BIND_EXPR
)
1655 return NULL_TREE
; /* Just process the sub-trees. */
1656 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1658 tree_stmt_iterator i
;
1659 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1661 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_expander
,
1666 *do_subtree
= 0; /* Done subtrees. */
1668 else if (EXPR_P (*stmt
))
1670 process_one_statement (stmt
, d
);
1671 *do_subtree
= 0; /* Done subtrees. */
1674 /* Continue statement walk, where required. */
1678 /* Suspend point hash_map. */
1680 struct suspend_point_info
1682 /* coro frame field type. */
1683 tree awaitable_type
;
1684 /* coro frame field name. */
1685 tree await_field_id
;
1688 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1690 struct await_xform_data
1692 tree actor_fn
; /* Decl for context. */
1700 /* When we built the await expressions, we didn't know the coro frame
1701 layout, therefore no idea where to find the promise or where to put
1702 the awaitables. Now we know these things, fill them in. */
1705 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1707 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1708 location_t loc
= EXPR_LOCATION (await_expr
);
1711 error_at (loc
, "no suspend point info for %qD", await_expr
);
1712 return error_mark_node
;
1715 /* So, on entry, we have:
1716 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1717 We no longer need a [it had diagnostic value, maybe?]
1718 We need to replace the promise proxy in all elements
1719 We need to replace the e_proxy in the awr_call. */
1721 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1723 /* If we have a frame var for the awaitable, get a reference to it. */
1725 if (si
->await_field_id
)
1728 = lookup_member (coro_frame_type
, si
->await_field_id
,
1729 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
1730 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
,
1732 tf_warning_or_error
);
1734 /* Replace references to the instance proxy with the frame entry now
1736 data
.from
= TREE_OPERAND (await_expr
, 1);
1738 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1740 /* .. and replace. */
1741 TREE_OPERAND (await_expr
, 1) = as
;
1744 /* Now do the self_handle. */
1745 data
.from
= xform
->self_h_proxy
;
1746 data
.to
= xform
->real_self_h
;
1747 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1749 /* Now do the promise. */
1750 data
.from
= xform
->promise_proxy
;
1751 data
.to
= xform
->real_promise
;
1752 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1757 /* A wrapper for the transform_await_expr function so that it can be a
1758 callback from cp_walk_tree. */
1761 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1763 /* Set actor function as new DECL_CONTEXT of label_decl. */
1764 struct await_xform_data
*xform
= (struct await_xform_data
*) d
;
1765 if (TREE_CODE (*stmt
) == LABEL_DECL
1766 && DECL_CONTEXT (*stmt
) != xform
->actor_fn
)
1767 DECL_CONTEXT (*stmt
) = xform
->actor_fn
;
1769 /* We should have already lowered co_yields to their co_await. */
1770 gcc_checking_assert (TREE_CODE (*stmt
) != CO_YIELD_EXPR
);
1771 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
)
1774 tree await_expr
= *stmt
;
1775 *stmt
= transform_await_expr (await_expr
, xform
);
1776 if (*stmt
== error_mark_node
)
1781 /* This caches information that we determine about function params,
1782 their uses and copies in the coroutine frame. */
1786 tree field_id
; /* The name of the copy in the coroutine frame. */
1787 vec
<tree
*> *body_uses
; /* Worklist of uses, void if there are none. */
1788 tree frame_type
; /* The type used to represent this parm in the frame. */
1789 tree orig_type
; /* The original type of the parm (not as passed). */
1790 bool by_ref
; /* Was passed by reference. */
1791 bool pt_ref
; /* Was a pointer to object. */
1792 bool trivial_dtor
; /* The frame type has a trivial DTOR. */
1793 bool this_ptr
; /* Is 'this' */
1794 bool lambda_cobj
; /* Lambda capture object */
1797 struct local_var_info
1802 bool is_lambda_capture
;
1804 bool has_value_expr_p
;
1808 /* For figuring out what local variable usage we have. */
1809 struct local_vars_transform
1813 tree coro_frame_type
;
1815 hash_map
<tree
, local_var_info
> *local_var_uses
;
1819 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
1821 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
1823 /* For each var in this bind expr (that has a frame id, which means it was
1824 accessed), build a frame reference for each and then walk the bind expr
1825 statements, substituting the frame ref for the original var. */
1827 if (TREE_CODE (*stmt
) == BIND_EXPR
)
1830 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1831 lvar
= DECL_CHAIN (lvar
))
1834 local_var_info
&local_var
1835 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
1836 gcc_checking_assert (existed
);
1838 /* Re-write the variable's context to be in the actor func. */
1839 DECL_CONTEXT (lvar
) = lvd
->context
;
1841 /* For capture proxies, this could include the decl value expr. */
1842 if (local_var
.is_lambda_capture
|| local_var
.has_value_expr_p
)
1844 tree ve
= DECL_VALUE_EXPR (lvar
);
1845 cp_walk_tree (&ve
, transform_local_var_uses
, d
, NULL
);
1846 continue; /* No frame entry for this. */
1849 /* TODO: implement selective generation of fields when vars are
1851 if (local_var
.field_id
== NULL_TREE
)
1852 continue; /* Wasn't used. */
1855 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
1856 /*protect=*/1, /*want_type=*/0,
1857 tf_warning_or_error
);
1858 tree fld_idx
= build3_loc (lvd
->loc
, COMPONENT_REF
, TREE_TYPE (lvar
),
1859 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
1860 local_var
.field_idx
= fld_idx
;
1862 /* FIXME: we should be able to do this in the loop above, but (at least
1863 for range for) there are cases where the DECL_INITIAL contains
1865 So, now we've built the revised var in the frame, substitute uses of
1866 it in initializers and the bind expr body. */
1867 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1868 lvar
= DECL_CHAIN (lvar
))
1870 /* we need to walk some of the decl trees, which might contain
1871 references to vars replaced at a higher level. */
1872 cp_walk_tree (&DECL_INITIAL (lvar
), transform_local_var_uses
, d
,
1874 cp_walk_tree (&DECL_SIZE (lvar
), transform_local_var_uses
, d
, NULL
);
1875 cp_walk_tree (&DECL_SIZE_UNIT (lvar
), transform_local_var_uses
, d
,
1878 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
1880 /* Now we have processed and removed references to the original vars,
1881 we can drop those from the bind - leaving capture proxies alone. */
1882 for (tree
*pvar
= &BIND_EXPR_VARS (*stmt
); *pvar
!= NULL
;)
1885 local_var_info
&local_var
1886 = lvd
->local_var_uses
->get_or_insert (*pvar
, &existed
);
1887 gcc_checking_assert (existed
);
1889 /* Leave lambda closure captures alone, we replace the *this
1890 pointer with the frame version and let the normal process
1892 Likewise, variables with their value found elsewhere.
1893 Skip past unused ones too. */
1894 if (local_var
.is_lambda_capture
1895 || local_var
.has_value_expr_p
1896 || local_var
.field_id
== NULL_TREE
)
1898 pvar
= &DECL_CHAIN (*pvar
);
1902 /* Discard this one, we replaced it. */
1903 *pvar
= DECL_CHAIN (*pvar
);
1906 *do_subtree
= 0; /* We've done the body already. */
1910 tree var_decl
= *stmt
;
1911 /* Look inside cleanups, we don't want to wrap a statement list in a
1913 bool needs_cleanup
= true;
1914 if (TREE_CODE (var_decl
) == CLEANUP_POINT_EXPR
)
1915 var_decl
= TREE_OPERAND (var_decl
, 0);
1917 needs_cleanup
= false;
1919 /* Look inside the decl_expr for the actual var. */
1920 bool decl_expr_p
= TREE_CODE (var_decl
) == DECL_EXPR
;
1921 if (decl_expr_p
&& TREE_CODE (DECL_EXPR_DECL (var_decl
)) == VAR_DECL
)
1922 var_decl
= DECL_EXPR_DECL (var_decl
);
1923 else if (TREE_CODE (var_decl
) != VAR_DECL
)
1926 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1927 for the promise and coroutine handle(s), to global vars or to compiler
1928 temporaries. Skip past these, we will handle them later. */
1929 local_var_info
*local_var_i
= lvd
->local_var_uses
->get (var_decl
);
1931 if (local_var_i
== NULL
)
1934 if (local_var_i
->is_lambda_capture
1935 || local_var_i
->is_static
1936 || local_var_i
->has_value_expr_p
)
1939 /* This is our revised 'local' i.e. a frame slot. */
1940 tree revised
= local_var_i
->field_idx
;
1941 gcc_checking_assert (DECL_CONTEXT (var_decl
) == lvd
->context
);
1943 if (decl_expr_p
&& DECL_INITIAL (var_decl
))
1945 location_t loc
= DECL_SOURCE_LOCATION (var_decl
);
1947 = cp_build_modify_expr (loc
, revised
, INIT_EXPR
,
1948 DECL_INITIAL (var_decl
), tf_warning_or_error
);
1950 r
= coro_build_cvt_void_expr_stmt (r
, EXPR_LOCATION (*stmt
));
1957 *do_subtree
= 0; /* We've accounted for the nested use. */
1961 /* The actor transform. */
1964 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
1965 tree orig
, hash_map
<tree
, param_info
> *param_uses
,
1966 hash_map
<tree
, local_var_info
> *local_var_uses
,
1967 vec
<tree
, va_gc
> *param_dtor_list
, tree resume_fn_field
,
1968 unsigned body_count
, tree frame_size
)
1970 verify_stmt_tree (fnbody
);
1971 /* Some things we inherit from the original function. */
1972 tree handle_type
= get_coroutine_handle_type (orig
);
1973 tree self_h_proxy
= get_coroutine_self_handle_proxy (orig
);
1974 tree promise_type
= get_coroutine_promise_type (orig
);
1975 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
1977 /* One param, the coro frame pointer. */
1978 tree actor_fp
= DECL_ARGUMENTS (actor
);
1980 /* A void return. */
1981 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
1982 DECL_ARTIFICIAL (resdecl
) = 1;
1983 DECL_IGNORED_P (resdecl
) = 1;
1984 DECL_RESULT (actor
) = resdecl
;
1985 DECL_COROUTINE_P (actor
) = 1;
1987 /* We have a definition here. */
1988 TREE_STATIC (actor
) = 1;
1990 tree actor_outer
= push_stmt_list ();
1991 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
1992 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
1994 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
1995 tree top_block
= make_node (BLOCK
);
1996 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
1998 tree continuation
= build_lang_decl (VAR_DECL
,
1999 get_identifier ("actor.continue"),
2000 void_coro_handle_type
);
2001 DECL_ARTIFICIAL (continuation
) = 1;
2002 DECL_IGNORED_P (continuation
) = 1;
2003 DECL_CONTEXT (continuation
) = actor
;
2004 BIND_EXPR_VARS (actor_bind
) = continuation
;
2006 /* Link in the block associated with the outer scope of the re-written
2008 tree first
= expr_first (fnbody
);
2009 gcc_checking_assert (first
&& TREE_CODE (first
) == BIND_EXPR
);
2010 tree block
= BIND_EXPR_BLOCK (first
);
2011 gcc_checking_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
2012 gcc_checking_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
2013 BLOCK_SUPERCONTEXT (block
) = top_block
;
2014 BLOCK_SUBBLOCKS (top_block
) = block
;
2016 add_stmt (actor_bind
);
2017 tree actor_body
= push_stmt_list ();
2019 /* The entry point for the actor code from the ramp. */
2020 tree actor_begin_label
2021 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
2022 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
2024 /* Declare the continuation handle. */
2025 add_decl_expr (continuation
);
2027 /* Re-write param references in the body, no code should be generated
2029 if (DECL_ARGUMENTS (orig
))
2032 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
2035 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
2036 if (!parm
.body_uses
)
2037 continue; /* Wasn't used in the original function body. */
2039 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
2040 /*protect=*/1, /*want_type=*/0,
2041 tf_warning_or_error
);
2042 tree fld_idx
= build3_loc (loc
, COMPONENT_REF
, parm
.frame_type
,
2043 actor_frame
, fld_ref
, NULL_TREE
);
2045 /* We keep these in the frame as a regular pointer, so convert that
2046 back to the type expected. */
2048 fld_idx
= build1_loc (loc
, CONVERT_EXPR
, TREE_TYPE (arg
), fld_idx
);
2052 FOR_EACH_VEC_ELT (*parm
.body_uses
, i
, puse
)
2057 /* Re-write local vars, similarly. */
2058 local_vars_transform xform_vars_data
2059 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
2060 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
2062 tree resume_idx_name
= get_identifier ("__resume_at");
2063 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2064 tf_warning_or_error
);
2065 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
2066 rat_field
, NULL_TREE
);
2069 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
2072 = create_named_label_with_ctx (loc
, "actor.continue.ret", actor
);
2074 tree lsb_if
= begin_if_stmt ();
2075 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
2076 build_int_cst (short_unsigned_type_node
, 1));
2077 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
2078 build_int_cst (short_unsigned_type_node
, 0));
2079 finish_if_stmt_cond (chkb0
, lsb_if
);
2081 tree destroy_dispatcher
= begin_switch_stmt ();
2082 finish_switch_cond (rat
, destroy_dispatcher
);
2083 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2084 create_anon_label_with_ctx (loc
, actor
));
2086 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2087 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2090 short unsigned lab_num
= 3;
2091 for (unsigned destr_pt
= 0; destr_pt
< body_count
; destr_pt
++)
2093 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2094 b
= build_case_label (l_num
, NULL_TREE
,
2095 create_anon_label_with_ctx (loc
, actor
));
2097 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2099 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2101 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
2106 /* Insert the prototype dispatcher. */
2107 finish_switch_stmt (destroy_dispatcher
);
2109 finish_then_clause (lsb_if
);
2111 tree dispatcher
= begin_switch_stmt ();
2112 finish_switch_cond (rat
, dispatcher
);
2113 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
2114 create_anon_label_with_ctx (loc
, actor
));
2116 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
2119 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2120 create_anon_label_with_ctx (loc
, actor
));
2122 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2123 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2127 /* The final resume should be made to hit the default (trap, UB) entry
2128 although it will be unreachable via the normal entry point, since that
2129 is set to NULL on reaching final suspend. */
2130 for (unsigned resu_pt
= 0; resu_pt
< body_count
; resu_pt
++)
2132 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2133 b
= build_case_label (l_num
, NULL_TREE
,
2134 create_anon_label_with_ctx (loc
, actor
));
2136 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2138 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2140 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
2145 /* Insert the prototype dispatcher. */
2146 finish_switch_stmt (dispatcher
);
2148 finish_if_stmt (lsb_if
);
2150 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
2153 /* actor's version of the promise. */
2154 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
2155 tf_warning_or_error
);
2156 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
, false,
2157 tf_warning_or_error
);
2159 /* actor's coroutine 'self handle'. */
2160 tree ash_m
= lookup_member (coro_frame_type
, get_identifier ("__self_h"), 1,
2161 0, tf_warning_or_error
);
2162 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
2163 false, tf_warning_or_error
);
2164 /* So construct the self-handle from the frame address. */
2165 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
2166 0, tf_warning_or_error
);
2168 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2169 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2170 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2171 NULL
, tf_warning_or_error
);
2172 r
= build2 (INIT_EXPR
, handle_type
, ash
, hfa
);
2173 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2175 release_tree_vector (args
);
2177 /* Now we know the real promise, and enough about the frame layout to
2178 decide where to put things. */
2180 await_xform_data xform
2181 = {actor
, actor_frame
, promise_proxy
, ap
, self_h_proxy
, ash
};
2183 /* Transform the await expressions in the function body. Only do each
2185 hash_set
<tree
> pset
;
2186 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2188 /* Now replace the promise proxy with its real value. */
2189 proxy_replace p_data
;
2190 p_data
.from
= promise_proxy
;
2192 cp_walk_tree (&fnbody
, replace_proxy
, &p_data
, NULL
);
2194 /* Set the actor pointer to null, so that 'done' will work.
2195 Resume from here is UB anyway - although a 'ready' await will
2196 branch to the final resume, and fall through to the destroy. */
2198 = lookup_member (coro_frame_type
, get_identifier ("__resume"),
2199 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2200 tree res_x
= build_class_member_access_expr (actor_frame
, resume_m
, NULL_TREE
,
2201 false, tf_warning_or_error
);
2202 p_data
.from
= resume_fn_field
;
2204 cp_walk_tree (&fnbody
, replace_proxy
, &p_data
, NULL
);
2206 /* Add in our function body with the co_returns rewritten to final form. */
2209 /* now do the tail of the function. */
2210 tree del_promise_label
2211 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2212 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2215 /* Destructors for the things we built explicitly. */
2216 r
= build_special_member_call (ap
, complete_dtor_identifier
, NULL
,
2217 promise_type
, LOOKUP_NORMAL
,
2218 tf_warning_or_error
);
2221 tree del_frame_label
2222 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2223 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2226 /* Here deallocate the frame (if we allocated it), which we will have at
2229 = lookup_member (coro_frame_type
, get_identifier ("__frame_needs_free"), 1,
2230 0, tf_warning_or_error
);
2231 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2232 false, tf_warning_or_error
);
2234 tree need_free_if
= begin_if_stmt ();
2235 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2236 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2237 finish_if_stmt_cond (cmp
, need_free_if
);
2238 if (param_dtor_list
!= NULL
)
2242 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2245 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2246 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2247 false, tf_warning_or_error
);
2248 tree t
= TREE_TYPE (a
);
2251 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2252 LOOKUP_NORMAL
, tf_warning_or_error
);
2257 /* [dcl.fct.def.coroutine] / 12
2258 The deallocation function’s name is looked up in the scope of the promise
2259 type. If this lookup fails, the deallocation function’s name is looked up
2260 in the global scope. If deallocation function lookup finds both a usual
2261 deallocation function with only a pointer parameter and a usual
2262 deallocation function with both a pointer parameter and a size parameter,
2263 then the selected deallocation function shall be the one with two
2264 parameters. Otherwise, the selected deallocation function shall be the
2265 function with one parameter. If no usual deallocation function is found
2266 the program is ill-formed. The selected deallocation function shall be
2267 called with the address of the block of storage to be reclaimed as its
2268 first argument. If a deallocation function with a parameter of type
2269 std::size_t is used, the size of the block is passed as the corresponding
2272 tree del_coro_fr
= NULL_TREE
;
2273 tree frame_arg
= build1 (CONVERT_EXPR
, ptr_type_node
, actor_fp
);
2275 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2276 tree fns
= lookup_promise_method (orig
, delname
, loc
, /*musthave=*/false);
2277 if (fns
&& BASELINK_P (fns
))
2279 /* Look for sized version first, since this takes precedence. */
2280 vec
<tree
, va_gc
> *args
= make_tree_vector ();
2281 vec_safe_push (args
, frame_arg
);
2282 vec_safe_push (args
, frame_size
);
2283 tree dummy_promise
= build_dummy_object (promise_type
);
2285 /* It's OK to fail for this one... */
2286 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2287 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2290 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2292 release_tree_vector (args
);
2293 args
= make_tree_vector_single (frame_arg
);
2294 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2295 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2299 /* But one of them must succeed, or the program is ill-formed. */
2300 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2302 error_at (loc
, "%qE is provided by %qT but is not usable with"
2303 " the function signature %qD", delname
, promise_type
, orig
);
2304 del_coro_fr
= error_mark_node
;
2309 del_coro_fr
= build_op_delete_call (DELETE_EXPR
, frame_arg
, frame_size
,
2310 /*global_p=*/true, /*placement=*/NULL
,
2312 tf_warning_or_error
);
2313 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2314 del_coro_fr
= error_mark_node
;
2317 del_coro_fr
= coro_build_cvt_void_expr_stmt (del_coro_fr
, loc
);
2318 add_stmt (del_coro_fr
);
2319 finish_then_clause (need_free_if
);
2320 tree scope
= IF_SCOPE (need_free_if
);
2321 IF_SCOPE (need_free_if
) = NULL
;
2322 r
= do_poplevel (scope
);
2326 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2327 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2328 r
= maybe_cleanup_point_expr_void (r
);
2331 /* This is the suspend return point. */
2332 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2335 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2336 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2337 r
= maybe_cleanup_point_expr_void (r
);
2340 /* This is the 'continuation' return point. For such a case we have a coro
2341 handle (from the await_suspend() call) and we want handle.resume() to
2342 execute as a tailcall allowing arbitrary chaining of coroutines. */
2343 r
= build_stmt (loc
, LABEL_EXPR
, continue_label
);
2346 /* We want to force a tail-call even for O0/1, so this expands the resume
2347 call into its underlying implementation. */
2348 tree addr
= lookup_member (void_coro_handle_type
, coro_address_identifier
,
2349 1, 0, tf_warning_or_error
);
2350 addr
= build_new_method_call (continuation
, addr
, NULL
, NULL_TREE
,
2351 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
2352 tree resume
= build_call_expr_loc
2353 (loc
, builtin_decl_explicit (BUILT_IN_CORO_RESUME
), 1, addr
);
2355 /* In order to support an arbitrary number of coroutine continuations,
2356 we must tail call them. However, some targets do not support indirect
2357 tail calls to arbitrary callees. See PR94359. */
2358 CALL_EXPR_TAILCALL (resume
) = true;
2359 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
2362 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2363 gcc_checking_assert (maybe_cleanup_point_expr_void (r
) == r
);
2366 /* We will need to know which resume point number should be encoded. */
2368 = lookup_member (coro_frame_type
, resume_idx_name
,
2369 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2370 tree resume_pt_number
2371 = build_class_member_access_expr (actor_frame
, res_idx_m
, NULL_TREE
, false,
2372 tf_warning_or_error
);
2374 /* We've now rewritten the tree and added the initial and final
2375 co_awaits. Now pass over the tree and expand the co_awaits. */
2377 coro_aw_data data
= {actor
, actor_fp
, resume_pt_number
, NULL_TREE
,
2378 ash
, del_promise_label
, ret_label
,
2379 continue_label
, continuation
, 2};
2380 cp_walk_tree (&actor_body
, await_statement_expander
, &data
, NULL
);
2382 BIND_EXPR_BODY (actor_bind
) = pop_stmt_list (actor_body
);
2383 TREE_SIDE_EFFECTS (actor_bind
) = true;
2385 finish_compound_stmt (stmt
);
2386 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2387 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2390 /* The prototype 'destroy' function :
2391 frame->__resume_at |= 1;
2395 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2398 /* One param, the coro frame pointer. */
2399 tree destr_fp
= DECL_ARGUMENTS (destroy
);
2401 /* A void return. */
2402 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2403 DECL_ARTIFICIAL (resdecl
) = 1;
2404 DECL_IGNORED_P (resdecl
) = 1;
2405 DECL_RESULT (destroy
) = resdecl
;
2407 /* We have a definition here. */
2408 TREE_STATIC (destroy
) = 1;
2409 DECL_COROUTINE_P (destroy
) = 1;
2411 tree destr_outer
= push_stmt_list ();
2412 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2413 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2415 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2417 tree resume_idx_name
= get_identifier ("__resume_at");
2418 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2419 tf_warning_or_error
);
2420 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, destr_frame
,
2421 rat_field
, NULL_TREE
);
2423 /* _resume_at |= 1 */
2424 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2425 build_int_cst (short_unsigned_type_node
, 1));
2426 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2427 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2430 /* So .. call the actor .. */
2431 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2432 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2436 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2437 r
= maybe_cleanup_point_expr_void (r
);
2440 finish_compound_stmt (dstr_stmt
);
2441 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2444 /* Helper that returns an identifier for an appended extension to the
2445 current un-mangled function name. */
2448 get_fn_local_identifier (tree orig
, const char *append
)
2450 /* Figure out the bits we need to generate names for the outlined things
2451 For consistency, this needs to behave the same way as
2452 ASM_FORMAT_PRIVATE_NAME does. */
2453 tree nm
= DECL_NAME (orig
);
2454 const char *sep
, *pfx
= "";
2455 #ifndef NO_DOT_IN_LABEL
2458 #ifndef NO_DOLLAR_IN_LABEL
2467 if (DECL_ASSEMBLER_NAME (orig
))
2468 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2470 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2471 && DECL_TI_ARGS (orig
))
2473 tree tpl_args
= DECL_TI_ARGS (orig
);
2474 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2475 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2477 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2478 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2480 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2483 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2485 return get_identifier (an
);
2488 /* Build an initial or final await initialized from the promise
2489 initial_suspend or final_suspend expression. */
2492 build_init_or_final_await (location_t loc
, bool is_final
)
2494 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2495 : coro_initial_suspend_identifier
;
2498 = coro_build_promise_expression (current_function_decl
, NULL
, suspend_alt
,
2499 loc
, NULL
, /*musthave=*/true);
2501 /* So build the co_await for this */
2502 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2503 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2504 : INITIAL_SUSPEND_POINT
));
2507 /* Callback to record the essential data for each await point found in the
2511 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
)
2514 suspend_point_info
&s
2515 = suspend_points
->get_or_insert (await_expr
, &seen
);
2518 warning_at (EXPR_LOCATION (await_expr
), 0, "duplicate info for %qE",
2522 s
.awaitable_type
= aw_type
;
2523 s
.await_field_id
= aw_nam
;
2527 /* This data set is used when analyzing statements for await expressions. */
2529 struct susp_frame_data
2531 /* Function-wide. */
2532 tree
*field_list
; /* The current coroutine frame field list. */
2533 tree handle_type
; /* The self-handle type for this coroutine. */
2534 tree fs_label
; /* The destination for co_returns. */
2535 vec
<tree
, va_gc
> *block_stack
; /* Track block scopes. */
2536 vec
<tree
, va_gc
> *bind_stack
; /* Track current bind expr. */
2537 unsigned await_number
; /* Which await in the function. */
2538 unsigned cond_number
; /* Which replaced condition in the fn. */
2539 /* Temporary values for one statement or expression being analyzed. */
2540 hash_set
<tree
> captured_temps
; /* The suspend captured these temps. */
2541 vec
<tree
, va_gc
> *to_replace
; /* The VAR decls to replace. */
2542 hash_set
<tree
> *truth_aoif_to_expand
; /* The set of TRUTH exprs to expand. */
2543 unsigned saw_awaits
; /* Count of awaits in this statement */
2544 bool captures_temporary
; /* This expr captures temps by ref. */
2545 bool needs_truth_if_exp
; /* We must expand a truth_if expression. */
2546 bool has_awaiter_init
; /* We must handle initializing an awaiter. */
2549 /* If this is an await expression, then count it (both uniquely within the
2550 function and locally within a single statement). */
2553 register_awaits (tree
*stmt
, int *, void *d
)
2555 tree aw_expr
= *stmt
;
2557 /* We should have already lowered co_yields to their co_await. */
2558 gcc_checking_assert (TREE_CODE (aw_expr
) != CO_YIELD_EXPR
);
2560 if (TREE_CODE (aw_expr
) != CO_AWAIT_EXPR
)
2563 /* Count how many awaits the current expression contains. */
2564 susp_frame_data
*data
= (susp_frame_data
*) d
;
2566 /* Each await suspend context is unique, this is a function-wide value. */
2567 data
->await_number
++;
2569 /* Awaitables should either be user-locals or promoted to coroutine frame
2570 entries at this point, and their initializers should have been broken
2572 tree aw
= TREE_OPERAND (aw_expr
, 1);
2573 gcc_checking_assert (!TREE_OPERAND (aw_expr
, 2));
2575 tree aw_field_type
= TREE_TYPE (aw
);
2576 tree aw_field_nam
= NULL_TREE
;
2577 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
);
2579 /* Rewrite target expressions on the await_suspend () to remove extraneous
2580 cleanups for the awaitables, which are now promoted to frame vars and
2581 managed via that. */
2582 tree v
= TREE_OPERAND (aw_expr
, 3);
2583 tree o
= TREE_VEC_ELT (v
, 1);
2584 if (TREE_CODE (o
) == TARGET_EXPR
)
2585 TREE_VEC_ELT (v
, 1) = get_target_expr (TREE_OPERAND (o
, 1));
2589 /* There are cases where any await expression is relevant. */
2591 find_any_await (tree
*stmt
, int *dosub
, void *d
)
2593 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
2595 *dosub
= 0; /* We don't need to consider this any further. */
2596 tree
**p
= (tree
**) d
;
2604 tmp_target_expr_p (tree t
)
2606 if (TREE_CODE (t
) != TARGET_EXPR
)
2608 tree v
= TREE_OPERAND (t
, 0);
2609 if (!DECL_ARTIFICIAL (v
))
2616 /* Structure to record sub-expressions that need to be handled by the
2617 statement flattener. */
2619 struct coro_interesting_subtree
2622 hash_set
<tree
> *temps_used
;
2625 /* tree-walk callback that returns the first encountered sub-expression of
2626 a kind that needs to be handled specifically by the statement flattener. */
2629 find_interesting_subtree (tree
*expr_p
, int *dosub
, void *d
)
2631 tree expr
= *expr_p
;
2632 coro_interesting_subtree
*p
= (coro_interesting_subtree
*)d
;
2633 if (TREE_CODE (expr
) == CO_AWAIT_EXPR
)
2635 *dosub
= 0; /* We don't need to consider this any further. */
2636 if (TREE_OPERAND (expr
, 2))
2642 else if (tmp_target_expr_p (expr
)
2643 && !p
->temps_used
->contains (expr
))
2652 /* Node for a doubly-linked list of promoted variables and their
2653 initializers. When the initializer is a conditional expression
2654 the 'then' and 'else' clauses are represented by a linked list
2655 attached to then_cl and else_cl respectively. */
2657 struct var_nest_node
2659 var_nest_node () = default;
2660 var_nest_node (tree v
, tree i
, var_nest_node
*p
, var_nest_node
*n
)
2661 : var(v
), init(i
), prev(p
), next(n
)
2670 var_nest_node
*prev
;
2671 var_nest_node
*next
;
2672 var_nest_node
*then_cl
;
2673 var_nest_node
*else_cl
;
2676 /* This is called for single statements from the co-await statement walker.
2677 It checks to see if the statement contains any initializers for awaitables
2678 and if any of these capture items by reference. */
2681 flatten_await_stmt (var_nest_node
*n
, hash_set
<tree
> *promoted
,
2682 hash_set
<tree
> *temps_used
, tree
*replace_in
)
2684 bool init_expr
= false;
2685 switch (TREE_CODE (n
->init
))
2688 /* Compound expressions must be flattened specifically. */
2691 tree first
= TREE_OPERAND (n
->init
, 0);
2692 n
->init
= TREE_OPERAND (n
->init
, 1);
2694 = new var_nest_node(NULL_TREE
, first
, n
->prev
, n
);
2695 /* The compiler (but not the user) can generate temporaries with
2696 uses in the second arm of a compound expr. */
2697 flatten_await_stmt (ins
, promoted
, temps_used
, &n
->init
);
2698 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2699 /* The two arms have been processed separately. */
2703 /* Handle conditional expressions. */
2709 tree old_expr
= TREE_OPERAND (n
->init
, 1);
2710 if (TREE_CODE (old_expr
) == COMPOUND_EXPR
)
2712 tree first
= TREE_OPERAND (old_expr
, 0);
2713 TREE_OPERAND (n
->init
, 1) = TREE_OPERAND (old_expr
, 1);
2715 = new var_nest_node(NULL_TREE
, first
, n
->prev
, n
);
2716 flatten_await_stmt (ins
, promoted
, temps_used
,
2717 &TREE_OPERAND (n
->init
, 1));
2718 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2721 if (TREE_CODE (old_expr
) != COND_EXPR
)
2723 /* Reconstruct x = t ? y : z;
2724 as (void) t ? x = y : x = z; */
2725 tree var
= TREE_OPERAND (n
->init
, 0);
2726 tree var_type
= TREE_TYPE (var
);
2727 tree cond
= COND_EXPR_COND (old_expr
);
2728 /* We are allowed a void type throw in one or both of the cond
2730 tree then_cl
= COND_EXPR_THEN (old_expr
);
2731 if (!VOID_TYPE_P (TREE_TYPE (then_cl
)))
2733 gcc_checking_assert (TREE_CODE (then_cl
) != STATEMENT_LIST
);
2735 = build2 (init_expr
? INIT_EXPR
: MODIFY_EXPR
, var_type
,
2738 tree else_cl
= COND_EXPR_ELSE (old_expr
);
2739 if (!VOID_TYPE_P (TREE_TYPE (else_cl
)))
2741 gcc_checking_assert (TREE_CODE (then_cl
) != STATEMENT_LIST
);
2743 = build2 (init_expr
? INIT_EXPR
: MODIFY_EXPR
, var_type
,
2746 n
->init
= build3 (COND_EXPR
, var_type
, cond
, then_cl
, else_cl
);
2752 tree cond
= COND_EXPR_COND (n
->init
);
2753 /* If the condition contains an await expression, then we need to
2754 set that first and use a separate var. */
2755 if (cp_walk_tree (&cond
, find_any_await
, &found
, NULL
))
2757 tree cond_type
= TREE_TYPE (cond
);
2758 tree cond_var
= build_lang_decl (VAR_DECL
, NULL_TREE
, cond_type
);
2759 DECL_ARTIFICIAL (cond_var
) = true;
2760 layout_decl (cond_var
, 0);
2761 gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type
));
2762 cond
= build2 (INIT_EXPR
, cond_type
, cond_var
, cond
);
2764 = new var_nest_node (cond_var
, cond
, n
->prev
, n
);
2765 COND_EXPR_COND (n
->init
) = cond_var
;
2766 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2770 = new var_nest_node (n
->var
, COND_EXPR_THEN (n
->init
), NULL
, NULL
);
2772 = new var_nest_node (n
->var
, COND_EXPR_ELSE (n
->init
), NULL
, NULL
);
2773 flatten_await_stmt (n
->then_cl
, promoted
, temps_used
, NULL
);
2774 /* Point to the start of the flattened code. */
2775 while (n
->then_cl
->prev
)
2776 n
->then_cl
= n
->then_cl
->prev
;
2777 flatten_await_stmt (n
->else_cl
, promoted
, temps_used
, NULL
);
2778 while (n
->else_cl
->prev
)
2779 n
->else_cl
= n
->else_cl
->prev
;
2784 coro_interesting_subtree v
= { NULL
, temps_used
};
2785 tree t
= cp_walk_tree (&n
->init
, find_interesting_subtree
, (void *)&v
, NULL
);
2788 switch (TREE_CODE (t
))
2793 /* Await expressions with initializers have a compiler-temporary
2794 as the awaitable. 'promote' this. */
2795 tree var
= TREE_OPERAND (t
, 1);
2796 bool already_present
= promoted
->add (var
);
2797 gcc_checking_assert (!already_present
);
2798 tree init
= TREE_OPERAND (t
, 2);
2799 switch (TREE_CODE (init
))
2805 tree inner
= TREE_OPERAND (init
, 1);
2806 /* We can have non-lvalue-expressions here, but when we see
2807 a target expression, mark it as already used. */
2808 if (TREE_CODE (inner
) == TARGET_EXPR
)
2810 temps_used
->add (inner
);
2812 (TREE_CODE (TREE_OPERAND (inner
, 1)) != COND_EXPR
);
2817 /* If this is a call and not a CTOR, then we didn't expect it. */
2819 (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init
), 0)));
2822 var_nest_node
*ins
= new var_nest_node (var
, init
, n
->prev
, n
);
2823 TREE_OPERAND (t
, 2) = NULL_TREE
;
2824 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2825 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2831 /* We have a temporary; promote it. */
2833 temps_used
->add (init
);
2834 tree var_type
= TREE_TYPE (init
);
2835 char *buf
= xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init
, 0)));
2836 tree var
= build_lang_decl (VAR_DECL
, get_identifier (buf
), var_type
);
2837 DECL_ARTIFICIAL (var
) = true;
2839 bool already_present
= promoted
->add (var
);
2840 gcc_checking_assert (!already_present
);
2841 tree inner
= TREE_OPERAND (init
, 1);
2842 gcc_checking_assert (TREE_CODE (inner
) != COND_EXPR
);
2843 if (TYPE_NEEDS_CONSTRUCTING (var_type
))
2845 releasing_vec
p_in (make_tree_vector_single (init
));
2846 init
= build_special_member_call (var
, complete_ctor_identifier
,
2847 &p_in
, var_type
, LOOKUP_NORMAL
,
2848 tf_warning_or_error
);
2851 init
= build2 (INIT_EXPR
, var_type
, var
, init
);
2853 = new var_nest_node (var
, init
, n
->prev
, n
);
2854 /* We have to replace the target expr... */
2855 proxy_replace pr
= {TREE_OPERAND (t
, 0), var
};
2857 /* ... and any uses of its var. */
2858 cp_walk_tree (&n
->init
, replace_proxy
, &pr
, NULL
);
2859 /* Compiler-generated temporaries can also have uses in following
2860 arms of compound expressions, which will be listed in 'replace_in'
2863 cp_walk_tree (replace_in
, replace_proxy
, &pr
, NULL
);
2864 flatten_await_stmt (ins
, promoted
, temps_used
, NULL
);
2865 flatten_await_stmt (n
, promoted
, temps_used
, NULL
);
2872 /* Helper for 'process_conditional' that handles recursion into nested
2876 handle_nested_conditionals (var_nest_node
*n
, vec
<tree
>& list
,
2877 hash_map
<tree
, tree
>& map
)
2881 if (n
->var
&& DECL_NAME (n
->var
))
2883 list
.safe_push (n
->var
);
2884 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n
->var
)))
2887 tree
& flag
= map
.get_or_insert (n
->var
, &existed
);
2890 /* We didn't see this var before and it needs a DTOR, so
2891 build a guard variable for it. */
2893 = xasprintf ("%s_guard",
2894 IDENTIFIER_POINTER (DECL_NAME (n
->var
)));
2895 flag
= build_lang_decl (VAR_DECL
, get_identifier (nam
),
2898 DECL_ARTIFICIAL (flag
) = true;
2901 /* The initializer for this variable is replaced by a compound
2902 expression that performs the init and then records that the
2903 variable is live (and the DTOR should be run at the scope
2905 tree set_flag
= build2 (INIT_EXPR
, boolean_type_node
,
2906 flag
, boolean_true_node
);
2908 = build2 (COMPOUND_EXPR
, boolean_type_node
, n
->init
, set_flag
);
2911 if (TREE_CODE (n
->init
) == COND_EXPR
)
2913 tree new_then
= push_stmt_list ();
2914 handle_nested_conditionals (n
->then_cl
, list
, map
);
2915 new_then
= pop_stmt_list (new_then
);
2916 tree new_else
= push_stmt_list ();
2917 handle_nested_conditionals (n
->else_cl
, list
, map
);
2918 new_else
= pop_stmt_list (new_else
);
2920 = build4 (IF_STMT
, void_type_node
, COND_EXPR_COND (n
->init
),
2921 new_then
, new_else
, NULL_TREE
);
2925 finish_expr_stmt (n
->init
);
2930 /* helper for 'maybe_promote_temps'.
2932 When we have a conditional expression which might embed await expressions
2933 and/or promoted variables, we need to handle it appropriately.
2935 The linked lists for the 'then' and 'else' clauses in a conditional node
2936 identify the promoted variables (but these cannot be wrapped in a regular
2939 So recurse through the lists and build up a composite list of captured vars.
2940 Declare these and any guard variables needed to decide if a DTOR should be
2941 run. Then embed the conditional into a try-finally expression that handles
2942 running each DTOR conditionally on its guard variable. */
2945 process_conditional (var_nest_node
*n
, tree
& vlist
)
2947 tree init
= n
->init
;
2948 hash_map
<tree
, tree
> var_flags
;
2949 vec
<tree
> var_list
= vNULL
;
2950 tree new_then
= push_stmt_list ();
2951 handle_nested_conditionals (n
->then_cl
, var_list
, var_flags
);
2952 new_then
= pop_stmt_list (new_then
);
2953 tree new_else
= push_stmt_list ();
2954 handle_nested_conditionals (n
->else_cl
, var_list
, var_flags
);
2955 new_else
= pop_stmt_list (new_else
);
2956 /* Declare the vars. There are two loops so that the boolean flags are
2957 grouped in the frame. */
2958 for (unsigned i
= 0; i
< var_list
.length(); i
++)
2960 tree var
= var_list
[i
];
2961 DECL_CHAIN (var
) = vlist
;
2963 add_decl_expr (var
);
2965 /* Define the guard flags for variables that need a DTOR. */
2966 for (unsigned i
= 0; i
< var_list
.length(); i
++)
2968 tree
*flag
= var_flags
.get (var_list
[i
]);
2971 DECL_INITIAL (*flag
) = boolean_false_node
;
2972 DECL_CHAIN (*flag
) = vlist
;
2974 add_decl_expr (*flag
);
2978 = build4 (IF_STMT
, void_type_node
, COND_EXPR_COND (init
),
2979 new_then
, new_else
, NULL_TREE
);
2980 /* Build a set of conditional DTORs. */
2981 tree final_actions
= push_stmt_list ();
2982 while (!var_list
.is_empty())
2984 tree var
= var_list
.pop ();
2985 tree
*flag
= var_flags
.get (var
);
2988 tree var_type
= TREE_TYPE (var
);
2990 = build_special_member_call (var
, complete_dtor_identifier
,
2991 NULL
, var_type
, LOOKUP_NORMAL
,
2992 tf_warning_or_error
);
2993 tree cond_cleanup
= begin_if_stmt ();
2994 finish_if_stmt_cond (*flag
, cond_cleanup
);
2995 finish_expr_stmt (cleanup
);
2996 finish_then_clause (cond_cleanup
);
2997 finish_if_stmt (cond_cleanup
);
2999 final_actions
= pop_stmt_list (final_actions
);
3001 = build2 (TRY_FINALLY_EXPR
, void_type_node
, new_if
, final_actions
);
3002 add_stmt (try_finally
);
3005 /* Given *STMT, that contains at least one await expression.
3007 The full expression represented in the original source code will contain
3008 suspension points, but it is still required that the lifetime of temporary
3009 values extends to the end of the expression.
3011 We already have a mechanism to 'promote' user-authored local variables
3012 to a coroutine frame counterpart (which allows explicit management of the
3013 lifetime across suspensions). The transform here re-writes STMT into
3014 a bind expression, promotes temporary values into local variables in that
3015 and flattens the statement into a series of cleanups.
3017 Conditional expressions are re-written to regular 'if' statements.
3018 The cleanups for variables initialized inside a conditional (including
3019 nested cases) are wrapped in a try-finally clause, with guard variables
3020 to determine which DTORs need to be run. */
3023 maybe_promote_temps (tree
*stmt
, void *d
)
3025 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3027 location_t sloc
= EXPR_LOCATION (*stmt
);
3029 /* Strip off uninteresting wrappers. */
3030 if (TREE_CODE (expr
) == CLEANUP_POINT_EXPR
)
3031 expr
= TREE_OPERAND (expr
, 0);
3032 if (TREE_CODE (expr
) == EXPR_STMT
)
3033 expr
= EXPR_STMT_EXPR (expr
);
3034 if (TREE_CODE (expr
) == CONVERT_EXPR
3035 && VOID_TYPE_P (TREE_TYPE (expr
)))
3036 expr
= TREE_OPERAND (expr
, 0);
3039 /* We walk the statement trees, flattening it into an ordered list of
3040 variables with initializers and fragments corresponding to compound
3041 expressions, truth or/and if and ternary conditionals. Conditional
3042 expressions carry a nested list of fragments for the then and else
3043 clauses. We anchor to the 'bottom' of the fragment list; we will write
3044 a cleanup nest with one shell for each variable initialized. */
3045 var_nest_node
*root
= new var_nest_node (NULL_TREE
, expr
, NULL
, NULL
);
3046 /* Check to see we didn't promote one twice. */
3047 hash_set
<tree
> promoted_vars
;
3048 hash_set
<tree
> used_temps
;
3049 flatten_await_stmt (root
, &promoted_vars
, &used_temps
, NULL
);
3051 gcc_checking_assert (root
->next
== NULL
);
3052 tree vlist
= NULL_TREE
;
3053 var_nest_node
*t
= root
;
3054 gcc_checking_assert (!t
->var
);
3055 /* We build the bind scope expression from the bottom-up.
3056 EXPR_LIST holds the inner expression nest at the current cleanup
3057 level (becoming the final expression list when we've exhausted the
3058 number of sub-expression fragments). */
3059 tree expr_list
= NULL_TREE
;
3062 tree new_list
= push_stmt_list ();
3063 /* When we have a promoted variable, then add that to the bind scope
3064 and initialize it. When there's no promoted variable, we just need
3065 to run the initializer.
3066 If the initializer is a conditional expression, we need to collect
3067 and declare any promoted variables nested within it. DTORs for such
3068 variables must be run conditionally too. */
3069 if (t
->var
&& DECL_NAME (t
->var
))
3072 DECL_CHAIN (var
) = vlist
;
3074 add_decl_expr (var
);
3075 if (TREE_CODE (t
->init
) == COND_EXPR
)
3076 process_conditional (t
, vlist
);
3078 finish_expr_stmt (t
->init
);
3079 tree var_type
= TREE_TYPE (var
);
3080 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type
))
3083 = build_special_member_call (var
, complete_dtor_identifier
,
3084 NULL
, var_type
, LOOKUP_NORMAL
,
3085 tf_warning_or_error
);
3086 tree cl
= build_stmt (sloc
, CLEANUP_STMT
, expr_list
, cleanup
, var
);
3087 add_stmt (cl
); /* push this onto the level above. */
3090 add_stmt (expr_list
);
3096 if (TREE_CODE (t
->init
) == COND_EXPR
)
3097 process_conditional (t
, vlist
);
3099 finish_expr_stmt (t
->init
);
3101 add_stmt (expr_list
);
3103 expr_list
= pop_stmt_list (new_list
);
3104 var_nest_node
*old
= t
;
3109 /* Now produce the bind expression containing the 'promoted' temporaries
3110 as its variable list, and the cleanup nest as the statement. */
3111 tree await_bind
= build3_loc (sloc
, BIND_EXPR
, void_type_node
,
3113 BIND_EXPR_BODY (await_bind
) = expr_list
;
3114 BIND_EXPR_VARS (await_bind
) = nreverse (vlist
);
3115 tree b_block
= make_node (BLOCK
);
3116 if (!awpts
->block_stack
->is_empty ())
3118 tree s_block
= awpts
->block_stack
->last ();
3121 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
3122 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
3123 BLOCK_SUBBLOCKS (s_block
) = b_block
;
3126 BLOCK_VARS (b_block
) = BIND_EXPR_VARS (await_bind
) ;
3127 BIND_EXPR_BLOCK (await_bind
) = b_block
;
3128 TREE_SIDE_EFFECTS (await_bind
) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind
));
3130 hash_set
<tree
> visited
;
3131 return cp_walk_tree (stmt
, register_awaits
, d
, &visited
);
3134 /* Lightweight callback to determine two key factors:
3135 1) If the statement/expression contains any await expressions.
3136 2) If the statement/expression potentially requires a re-write to handle
3137 TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3138 so that the await expressions are not processed in the case of the
3141 CO_YIELD expressions are re-written to their underlying co_await. */
3144 analyze_expression_awaits (tree
*stmt
, int *do_subtree
, void *d
)
3146 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3148 switch (TREE_CODE (*stmt
))
3150 default: return NULL_TREE
;
3152 /* co_yield is syntactic sugar, re-write it to co_await. */
3153 *stmt
= TREE_OPERAND (*stmt
, 1);
3156 awpts
->saw_awaits
++;
3157 /* A non-null initializer for the awaiter means we need to expand. */
3158 if (TREE_OPERAND (*stmt
, 2))
3159 awpts
->has_awaiter_init
= true;
3161 case TRUTH_ANDIF_EXPR
:
3162 case TRUTH_ORIF_EXPR
:
3164 /* We don't need special action for awaits in the always-executed
3165 arm of a TRUTH_IF. */
3166 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 0),
3167 analyze_expression_awaits
, d
, NULL
))
3169 /* However, if there are await expressions on the conditionally
3170 executed branch, we must expand the TRUTH_IF to ensure that the
3171 expanded await expression control-flow is fully contained in the
3172 conditionally executed code. */
3173 unsigned aw_count
= awpts
->saw_awaits
;
3174 if (tree res
= cp_walk_tree (&TREE_OPERAND (*stmt
, 1),
3175 analyze_expression_awaits
, d
, NULL
))
3177 if (awpts
->saw_awaits
> aw_count
)
3179 awpts
->truth_aoif_to_expand
->add (*stmt
);
3180 awpts
->needs_truth_if_exp
= true;
3182 /* We've done the sub-trees here. */
3188 return NULL_TREE
; /* Recurse until done. */
3192 If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3193 the conditionally executed branch, change this in a ternary operator.
3195 bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3196 not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3198 Apply this recursively to the condition and the conditionally-exec
3201 struct truth_if_transform
{
3204 hash_set
<tree
> *truth_aoif_to_expand
;
3208 expand_one_truth_if (tree
*expr
, int *do_subtree
, void *d
)
3210 truth_if_transform
*xform
= (truth_if_transform
*) d
;
3212 bool needs_not
= false;
3213 switch (TREE_CODE (*expr
))
3216 case TRUTH_ORIF_EXPR
:
3219 case TRUTH_ANDIF_EXPR
:
3221 if (!xform
->truth_aoif_to_expand
->contains (*expr
))
3224 location_t sloc
= EXPR_LOCATION (*expr
);
3225 /* Transform truth expression into a cond expression with
3226 * the always-executed arm as the condition.
3227 * the conditionally-executed arm as the then clause.
3228 * the 'else' clause is fixed: 'true' for ||,'false' for &&. */
3229 tree cond
= TREE_OPERAND (*expr
, 0);
3230 tree test1
= TREE_OPERAND (*expr
, 1);
3231 tree fixed
= needs_not
? boolean_true_node
: boolean_false_node
;
3233 cond
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3235 = build3_loc (sloc
, COND_EXPR
, boolean_type_node
,
3236 cond
, test1
, fixed
);
3238 if (tree res
= cp_walk_tree (&COND_EXPR_COND (*expr
),
3239 expand_one_truth_if
, d
, NULL
))
3241 if (tree res
= cp_walk_tree (&COND_EXPR_THEN (*expr
),
3242 expand_one_truth_if
, d
, NULL
))
3244 /* We've manually processed necessary sub-trees here. */
3252 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3253 name is made up from NAM_ROOT, NAM_VERS. */
3256 add_var_to_bind (tree
& bind
, tree var_type
,
3257 const char *nam_root
, unsigned nam_vers
)
3259 tree b_vars
= BIND_EXPR_VARS (bind
);
3260 /* Build a variable to hold the condition, this will be included in the
3261 frame as a local var. */
3262 char *nam
= xasprintf ("%s.%d", nam_root
, nam_vers
);
3263 tree newvar
= build_lang_decl (VAR_DECL
, get_identifier (nam
), var_type
);
3265 DECL_CHAIN (newvar
) = b_vars
;
3266 BIND_EXPR_VARS (bind
) = newvar
;
3270 /* Helper to build and add if (!cond) break; */
3273 coro_build_add_if_not_cond_break (tree cond
)
3275 tree if_stmt
= begin_if_stmt ();
3276 tree invert
= build1 (TRUTH_NOT_EXPR
, boolean_type_node
, cond
);
3277 finish_if_stmt_cond (invert
, if_stmt
);
3278 finish_break_stmt ();
3279 finish_then_clause (if_stmt
);
3280 finish_if_stmt (if_stmt
);
3283 /* Tree walk callback to analyze, register and pre-process statements that
3284 contain await expressions. */
3287 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
3289 tree res
= NULL_TREE
;
3290 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
3292 /* Process a statement at a time. */
3293 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3295 /* For conditional expressions, we might wish to add an artificial var
3296 to their containing bind expr. */
3297 vec_safe_push (awpts
->bind_stack
, *stmt
);
3298 /* We might need to insert a new bind expression, and want to link it
3299 into the correct scope, so keep a note of the current block scope. */
3300 tree blk
= BIND_EXPR_BLOCK (*stmt
);
3301 vec_safe_push (awpts
->block_stack
, blk
);
3302 res
= cp_walk_tree (&BIND_EXPR_BODY (*stmt
), await_statement_walker
,
3304 awpts
->block_stack
->pop ();
3305 awpts
->bind_stack
->pop ();
3306 *do_subtree
= 0; /* Done subtrees. */
3309 else if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
3311 tree_stmt_iterator i
;
3312 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
3314 res
= cp_walk_tree (tsi_stmt_ptr (i
), await_statement_walker
,
3319 *do_subtree
= 0; /* Done subtrees. */
3323 /* We have something to be handled as a single statement. */
3324 bool has_cleanup_wrapper
= TREE_CODE (*stmt
) == CLEANUP_POINT_EXPR
;
3325 hash_set
<tree
> visited
;
3326 awpts
->saw_awaits
= 0;
3327 hash_set
<tree
> truth_aoif_to_expand
;
3328 awpts
->truth_aoif_to_expand
= &truth_aoif_to_expand
;
3329 awpts
->needs_truth_if_exp
= false;
3330 awpts
->has_awaiter_init
= false;
3332 if (has_cleanup_wrapper
)
3333 expr
= TREE_OPERAND (expr
, 0);
3336 if (STATEMENT_CLASS_P (expr
))
3337 switch (TREE_CODE (expr
))
3339 /* Unless it's a special case, just walk the subtrees as usual. */
3340 default: return NULL_TREE
;
3342 /* When we have a conditional expression, which contains one or more
3343 await expressions, we have to break the condition out into a
3344 regular statement so that the control flow introduced by the await
3345 transforms can be implemented. */
3348 /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3349 bool cond = cond with awaits.
3350 if (cond) then stmt1 else stmt2. */
3351 tree if_stmt
= *stmt
;
3352 /* We treat the condition as if it was a stand-alone statement,
3353 to see if there are any await expressions which will be analyzed
3355 if ((res
= cp_walk_tree (&IF_COND (if_stmt
),
3356 analyze_expression_awaits
, d
, &visited
)))
3358 if (!awpts
->saw_awaits
)
3359 return NULL_TREE
; /* Nothing special to do here. */
3361 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3362 tree
& bind_expr
= awpts
->bind_stack
->last ();
3363 tree newvar
= add_var_to_bind (bind_expr
, boolean_type_node
,
3364 "ifcd", awpts
->cond_number
++);
3365 tree insert_list
= push_stmt_list ();
3366 tree cond_inner
= IF_COND (if_stmt
);
3367 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3368 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3369 add_decl_expr (newvar
);
3370 location_t sloc
= EXPR_LOCATION (IF_COND (if_stmt
));
3371 /* We want to initialize the new variable with the expression
3372 that contains the await(s) and potentially also needs to
3373 have truth_if expressions expanded. */
3374 tree new_s
= build2_loc (sloc
, MODIFY_EXPR
, boolean_type_node
,
3375 newvar
, cond_inner
);
3376 finish_expr_stmt (new_s
);
3377 IF_COND (if_stmt
) = newvar
;
3379 *stmt
= pop_stmt_list (insert_list
);
3380 /* So now walk the new statement list. */
3381 res
= cp_walk_tree (stmt
, await_statement_walker
, d
, NULL
);
3382 *do_subtree
= 0; /* Done subtrees. */
3388 /* We turn 'while (cond with awaits) stmt' into
3390 if (!(cond with awaits))
3394 tree while_stmt
= *stmt
;
3395 if ((res
= cp_walk_tree (&WHILE_COND (while_stmt
),
3396 analyze_expression_awaits
, d
, &visited
)))
3398 if (!awpts
->saw_awaits
)
3399 return NULL_TREE
; /* Nothing special to do here. */
3401 tree insert_list
= push_stmt_list ();
3402 coro_build_add_if_not_cond_break (WHILE_COND (while_stmt
));
3403 /* The original while body. */
3404 add_stmt (WHILE_BODY (while_stmt
));
3405 /* The new while body. */
3406 WHILE_BODY (while_stmt
) = pop_stmt_list (insert_list
);
3407 WHILE_COND (while_stmt
) = boolean_true_node
;
3408 /* So now walk the new statement list. */
3409 res
= cp_walk_tree (&WHILE_BODY (while_stmt
),
3410 await_statement_walker
, d
, NULL
);
3411 *do_subtree
= 0; /* Done subtrees. */
3417 /* We turn do stmt while (cond with awaits) into:
3420 if (!(cond with awaits))
3423 tree do_stmt
= *stmt
;
3424 if ((res
= cp_walk_tree (&DO_COND (do_stmt
),
3425 analyze_expression_awaits
, d
, &visited
)))
3427 if (!awpts
->saw_awaits
)
3428 return NULL_TREE
; /* Nothing special to do here. */
3430 tree insert_list
= push_stmt_list ();
3431 /* The original do stmt body. */
3432 add_stmt (DO_BODY (do_stmt
));
3433 coro_build_add_if_not_cond_break (DO_COND (do_stmt
));
3434 /* The new while body. */
3435 DO_BODY (do_stmt
) = pop_stmt_list (insert_list
);
3436 DO_COND (do_stmt
) = boolean_true_node
;
3437 /* So now walk the new statement list. */
3438 res
= cp_walk_tree (&DO_BODY (do_stmt
), await_statement_walker
,
3440 *do_subtree
= 0; /* Done subtrees. */
3446 /* We turn 'switch (cond with awaits) stmt' into
3447 switch_type cond = cond with awaits
3448 switch (cond) stmt. */
3449 tree sw_stmt
= *stmt
;
3450 if ((res
= cp_walk_tree (&SWITCH_STMT_COND (sw_stmt
),
3451 analyze_expression_awaits
, d
, &visited
)))
3453 if (!awpts
->saw_awaits
)
3454 return NULL_TREE
; /* Nothing special to do here. */
3456 gcc_checking_assert (!awpts
->bind_stack
->is_empty());
3457 /* Build a variable to hold the condition, this will be
3458 included in the frame as a local var. */
3459 tree
& bind_expr
= awpts
->bind_stack
->last ();
3460 tree sw_type
= SWITCH_STMT_TYPE (sw_stmt
);
3461 tree newvar
= add_var_to_bind (bind_expr
, sw_type
, "swch",
3462 awpts
->cond_number
++);
3463 tree insert_list
= push_stmt_list ();
3464 add_decl_expr (newvar
);
3466 tree cond_inner
= SWITCH_STMT_COND (sw_stmt
);
3467 if (TREE_CODE (cond_inner
) == CLEANUP_POINT_EXPR
)
3468 cond_inner
= TREE_OPERAND (cond_inner
, 0);
3469 location_t sloc
= EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt
));
3470 tree new_s
= build2_loc (sloc
, INIT_EXPR
, sw_type
, newvar
,
3472 finish_expr_stmt (new_s
);
3473 SWITCH_STMT_COND (sw_stmt
) = newvar
;
3474 /* Now add the switch statement with the condition re-
3475 written to use the local var. */
3477 *stmt
= pop_stmt_list (insert_list
);
3478 /* Process the expanded list. */
3479 res
= cp_walk_tree (stmt
, await_statement_walker
,
3481 *do_subtree
= 0; /* Done subtrees. */
3485 case CO_RETURN_EXPR
:
3487 /* Expand the co_return as per [stmt.return.coroutine]
3489 { p.return_void (); goto final_suspend; }
3490 - for co_return [void expr];
3491 { expr; p.return_void(); goto final_suspend;}
3492 - for co_return [non void expr];
3493 { p.return_value(expr); goto final_suspend; } */
3494 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
,
3497 location_t loc
= EXPR_LOCATION (expr
);
3498 tree call
= TREE_OPERAND (expr
, 1);
3499 expr
= TREE_OPERAND (expr
, 0);
3500 tree ret_list
= push_stmt_list ();
3501 /* [stmt.return.coroutine], 2.2
3502 If expr is present and void, it is placed immediately before
3503 the call for return_void; */
3504 tree
*maybe_await_stmt
= NULL
;
3505 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
3507 finish_expr_stmt (expr
);
3508 /* If the return argument was a void expression, then any
3509 awaits must be contained in that. */
3510 maybe_await_stmt
= tsi_stmt_ptr (tsi_last (ret_list
));
3512 /* Insert p.return_{void,value(expr)}. */
3513 finish_expr_stmt (call
);
3514 /* Absent a return of a void expression, any awaits must be in
3515 the parameter to return_value(). */
3516 if (!maybe_await_stmt
)
3517 maybe_await_stmt
= tsi_stmt_ptr (tsi_last (ret_list
));
3518 expr
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, awpts
->fs_label
);
3519 finish_expr_stmt (expr
);
3520 *stmt
= pop_stmt_list (ret_list
);
3521 /* Once this is complete, we will have processed subtrees. */
3523 if (awpts
->saw_awaits
)
3525 gcc_checking_assert (maybe_await_stmt
);
3526 res
= cp_walk_tree (maybe_await_stmt
, await_statement_walker
,
3531 return NULL_TREE
; /* Done. */
3535 else if (EXPR_P (expr
))
3537 if ((res
= cp_walk_tree (stmt
, analyze_expression_awaits
, d
, &visited
)))
3539 *do_subtree
= 0; /* Done subtrees. */
3540 if (!awpts
->saw_awaits
)
3541 return NULL_TREE
; /* Nothing special to do here. */
3543 if (awpts
->needs_truth_if_exp
)
3545 /* If a truth-and/or-if expression has an await expression in the
3546 conditionally-taken branch, then it must be rewritten into a
3547 regular conditional. */
3548 truth_if_transform xf
= {stmt
, NULL_TREE
, &truth_aoif_to_expand
};
3549 if ((res
= cp_walk_tree (stmt
, expand_one_truth_if
, &xf
, NULL
)))
3552 /* Process this statement, which contains at least one await expression
3553 to 'promote' temporary values to a coroutine frame slot. */
3554 return maybe_promote_temps (stmt
, d
);
3556 /* Continue recursion, if needed. */
3560 /* For figuring out what param usage we have. */
3562 struct param_frame_data
3565 hash_map
<tree
, param_info
> *param_uses
;
3566 hash_set
<tree
*> *visited
;
3571 /* A tree-walk callback that records the use of parameters (to allow for
3572 optimizations where handling unused parameters may be omitted). */
3575 register_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
3577 param_frame_data
*data
= (param_frame_data
*) d
;
3579 /* For lambda closure content, we have to look specifically. */
3580 if (TREE_CODE (*stmt
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (*stmt
))
3582 tree t
= DECL_VALUE_EXPR (*stmt
);
3583 return cp_walk_tree (&t
, register_param_uses
, d
, NULL
);
3586 if (TREE_CODE (*stmt
) != PARM_DECL
)
3589 /* If we already saw the containing expression, then we're done. */
3590 if (data
->visited
->add (stmt
))
3594 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
3595 gcc_checking_assert (existed
);
3597 if (!parm
.body_uses
)
3599 vec_alloc (parm
.body_uses
, 4);
3600 parm
.body_uses
->quick_push (stmt
);
3601 data
->param_seen
= true;
3604 parm
.body_uses
->safe_push (stmt
);
3609 /* Small helper for the repetitive task of adding a new field to the coro
3613 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
3616 tree id
= get_identifier (name
);
3617 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
3618 DECL_CHAIN (decl
) = *field_list
;
3623 /* For recording local variable usage. */
3625 struct local_vars_frame_data
3628 hash_map
<tree
, local_var_info
> *local_var_uses
;
3629 unsigned int nest_depth
, bind_indx
;
3632 bool local_var_seen
;
3635 /* A tree-walk callback that processes one bind expression noting local
3636 variables, and making a coroutine frame slot available for those that
3637 need it, so that they can be 'promoted' across suspension points. */
3640 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
3642 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
3644 /* As we enter a bind expression - record the vars there and then recurse.
3645 As we exit drop the nest depth.
3646 The bind index is a growing count of how many bind indices we've seen.
3647 We build a space in the frame for each local var. */
3649 if (TREE_CODE (*stmt
) == BIND_EXPR
)
3654 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
3655 lvar
= DECL_CHAIN (lvar
))
3658 local_var_info
&local_var
3659 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
3660 gcc_checking_assert (!existed
);
3661 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
3662 tree lvtype
= TREE_TYPE (lvar
);
3663 local_var
.frame_type
= lvtype
;
3664 local_var
.field_idx
= local_var
.field_id
= NULL_TREE
;
3666 /* Make sure that we only present vars to the tests below. */
3667 if (TREE_CODE (lvar
) == TYPE_DECL
3668 || TREE_CODE (lvar
) == NAMESPACE_DECL
)
3671 /* We don't move static vars into the frame. */
3672 local_var
.is_static
= TREE_STATIC (lvar
);
3673 if (local_var
.is_static
)
3676 lvd
->local_var_seen
= true;
3677 /* If this var is a lambda capture proxy, we want to leave it alone,
3678 and later rewrite the DECL_VALUE_EXPR to indirect through the
3679 frame copy of the pointer to the lambda closure object. */
3680 local_var
.is_lambda_capture
= is_capture_proxy (lvar
);
3681 if (local_var
.is_lambda_capture
)
3684 /* If a variable has a value expression, then that's what needs
3686 local_var
.has_value_expr_p
= DECL_HAS_VALUE_EXPR_P (lvar
);
3687 if (local_var
.has_value_expr_p
)
3690 /* Make names depth+index unique, so that we can support nested
3691 scopes with identically named locals. */
3692 tree lvname
= DECL_NAME (lvar
);
3694 if (lvname
!= NULL_TREE
)
3695 buf
= xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname
),
3696 lvd
->nest_depth
, lvd
->bind_indx
);
3698 buf
= xasprintf ("_D%u.%u.%u", DECL_UID (lvar
), lvd
->nest_depth
,
3700 /* TODO: Figure out if we should build a local type that has any
3701 excess alignment or size from the original decl. */
3703 = coro_make_frame_entry (lvd
->field_list
, buf
, lvtype
, lvd
->loc
);
3705 /* We don't walk any of the local var sub-trees, they won't contain
3708 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
3709 *do_subtree
= 0; /* We've done this. */
3715 /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
3716 for either actor or destroy functions. */
3719 act_des_fn (tree orig
, tree fn_type
, tree coro_frame_ptr
, const char* name
)
3721 tree fn_name
= get_fn_local_identifier (orig
, name
);
3722 tree fn
= build_lang_decl (FUNCTION_DECL
, fn_name
, fn_type
);
3723 DECL_CONTEXT (fn
) = DECL_CONTEXT (orig
);
3724 DECL_ARTIFICIAL (fn
) = true;
3725 DECL_INITIAL (fn
) = error_mark_node
;
3726 tree id
= get_identifier ("frame_ptr");
3727 tree fp
= build_lang_decl (PARM_DECL
, id
, coro_frame_ptr
);
3728 DECL_CONTEXT (fp
) = fn
;
3729 DECL_ARG_TYPE (fp
) = type_passed_as (coro_frame_ptr
);
3730 DECL_ARGUMENTS (fn
) = fp
;
3731 /* Copy selected attributes from the original function. */
3732 TREE_USED (fn
) = TREE_USED (orig
);
3733 if (DECL_SECTION_NAME (orig
))
3734 set_decl_section_name (fn
, DECL_SECTION_NAME (orig
));
3735 /* Copy any alignment that the FE added. */
3736 if (DECL_ALIGN (orig
))
3737 SET_DECL_ALIGN (fn
, DECL_ALIGN (orig
));
3738 /* Copy any alignment the user added. */
3739 DECL_USER_ALIGN (fn
) = DECL_USER_ALIGN (orig
);
3740 /* Apply attributes from the original fn. */
3741 DECL_ATTRIBUTES (fn
) = copy_list (DECL_ATTRIBUTES (orig
));
3745 /* Re-write the body as per [dcl.fct.def.coroutine] / 5. */
3748 coro_rewrite_function_body (location_t fn_start
, tree fnbody
,
3749 tree orig
, tree resume_fn_ptr_type
,
3750 tree
& resume_fn_field
, tree
& fs_label
)
3752 /* This will be our new outer scope. */
3753 tree update_body
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3754 tree top_block
= make_node (BLOCK
);
3755 BIND_EXPR_BLOCK (update_body
) = top_block
;
3756 BIND_EXPR_BODY (update_body
) = push_stmt_list ();
3758 /* If the function has a top level bind expression, then connect that
3759 after first making sure we give it a new block. */
3760 tree first
= expr_first (fnbody
);
3761 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
3763 tree block
= BIND_EXPR_BLOCK (first
);
3764 gcc_checking_assert (block
);
3765 gcc_checking_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
3766 gcc_checking_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
3767 /* Replace the top block to avoid issues with locations for args
3768 appearing to be in a non-existent place. */
3769 tree replace_blk
= make_node (BLOCK
);
3770 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
3771 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
3772 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
3773 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
3774 BIND_EXPR_BLOCK (first
) = replace_blk
;
3775 /* The top block has one child, so far, and we have now got a
3777 BLOCK_SUPERCONTEXT (block
) = top_block
;
3778 BLOCK_SUBBLOCKS (top_block
) = block
;
3781 /* Wrap the function body in a try {} catch (...) {} block, if exceptions
3783 tree promise
= get_coroutine_promise_proxy (orig
);
3784 tree var_list
= NULL_TREE
;
3785 tree initial_await
= build_init_or_final_await (fn_start
, false);
3787 /* [stmt.return.coroutine] / 3
3788 If p.return_void() is a valid expression, flowing off the end of a
3789 coroutine is equivalent to a co_return with no operand; otherwise
3790 flowing off the end of a coroutine results in undefined behavior. */
3792 = get_coroutine_return_void_expr (current_function_decl
, fn_start
, false);
3794 if (flag_exceptions
)
3796 /* Build promise.unhandled_exception(); */
3798 = coro_build_promise_expression (current_function_decl
, promise
,
3799 coro_unhandled_exception_identifier
,
3800 fn_start
, NULL
, /*musthave=*/true);
3801 /* Create and initialize the initial-await-resume-called variable per
3802 [dcl.fct.def.coroutine] / 5.3. */
3803 tree i_a_r_c
= build_lang_decl (VAR_DECL
, get_identifier ("i_a_r_c"),
3805 DECL_ARTIFICIAL (i_a_r_c
) = true;
3806 DECL_CHAIN (i_a_r_c
) = var_list
;
3808 DECL_INITIAL (i_a_r_c
) = boolean_false_node
;
3809 add_decl_expr (i_a_r_c
);
3810 /* Start the try-catch. */
3811 tree tcb
= build_stmt (fn_start
, TRY_BLOCK
, NULL_TREE
, NULL_TREE
);
3813 TRY_STMTS (tcb
) = push_stmt_list ();
3814 if (initial_await
!= error_mark_node
)
3816 /* Build a compound expression that sets the
3817 initial-await-resume-called variable true and then calls the
3818 initial suspend expression await resume. */
3819 tree vec
= TREE_OPERAND (initial_await
, 3);
3820 tree aw_r
= TREE_VEC_ELT (vec
, 2);
3821 tree update
= build2 (MODIFY_EXPR
, boolean_type_node
, i_a_r_c
,
3823 aw_r
= cp_build_compound_expr (update
, aw_r
, tf_warning_or_error
);
3824 TREE_VEC_ELT (vec
, 2) = aw_r
;
3826 /* Add the initial await to the start of the user-authored function. */
3827 finish_expr_stmt (initial_await
);
3828 /* Append the original function body. */
3831 add_stmt (return_void
);
3832 TRY_STMTS (tcb
) = pop_stmt_list (TRY_STMTS (tcb
));
3833 TRY_HANDLERS (tcb
) = push_stmt_list ();
3834 /* Mimic what the parser does for the catch. */
3835 tree handler
= begin_handler ();
3836 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
3838 /* Get the initial await resume called value. */
3839 tree not_iarc_if
= begin_if_stmt ();
3840 tree not_iarc
= build1_loc (fn_start
, TRUTH_NOT_EXPR
,
3841 boolean_type_node
, i_a_r_c
);
3842 finish_if_stmt_cond (not_iarc
, not_iarc_if
);
3843 /* If the initial await resume called value is false, rethrow... */
3844 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
3845 TREE_NO_WARNING (rethrow
) = true;
3846 finish_expr_stmt (rethrow
);
3847 finish_then_clause (not_iarc_if
);
3848 tree iarc_scope
= IF_SCOPE (not_iarc_if
);
3849 IF_SCOPE (not_iarc_if
) = NULL
;
3850 not_iarc_if
= do_poplevel (iarc_scope
);
3851 add_stmt (not_iarc_if
);
3852 /* ... else call the promise unhandled exception method. */
3853 ueh
= maybe_cleanup_point_expr_void (ueh
);
3855 finish_handler (handler
);
3856 TRY_HANDLERS (tcb
) = pop_stmt_list (TRY_HANDLERS (tcb
));
3862 /* We still try to look for the promise method and warn if it's not
3865 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
3866 fn_start
, /*musthave=*/false);
3867 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
3868 warning_at (fn_start
, 0, "no member named %qE in %qT",
3869 coro_unhandled_exception_identifier
,
3870 get_coroutine_promise_type (orig
));
3872 /* Else we don't check and don't care if the method is missing..
3873 just add the initial suspend, function and return. */
3874 finish_expr_stmt (initial_await
);
3875 /* Append the original function body. */
3878 add_stmt (return_void
);
3881 /* co_return branches to the final_suspend label, so declare that now. */
3883 = create_named_label_with_ctx (fn_start
, "final.suspend", NULL_TREE
);
3884 add_stmt (build_stmt (fn_start
, LABEL_EXPR
, fs_label
));
3886 /* Before entering the final suspend point, we signal that this point has
3887 been reached by setting the resume function pointer to zero (this is
3888 what the 'done()' builtin tests) as per the current ABI. */
3890 = build_lang_decl (VAR_DECL
, get_identifier ("resume.fn.ptr.proxy"),
3891 resume_fn_ptr_type
);
3892 DECL_ARTIFICIAL (resume_fn_field
) = true;
3894 = build1 (CONVERT_EXPR
, resume_fn_ptr_type
, integer_zero_node
);
3896 = build2 (INIT_EXPR
, resume_fn_ptr_type
, resume_fn_field
, zero_resume
);
3897 finish_expr_stmt (zero_resume
);
3898 finish_expr_stmt (build_init_or_final_await (fn_start
, true));
3899 BIND_EXPR_BODY (update_body
) = pop_stmt_list (BIND_EXPR_BODY (update_body
));
3900 BIND_EXPR_VARS (update_body
) = nreverse (var_list
);
3901 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (update_body
);
3907 a) Check that the function and promise type are valid for a
3909 b) Carry out the initial morph to create the skeleton of the
3910 coroutine ramp function and the rewritten body.
3914 1. We only hit this code once all dependencies are resolved.
3915 2. The function body will be either a bind expr or a statement list
3916 3. That cfun and current_function_decl are valid for the case we're
3918 4. 'input_location' will be of the final brace for the function.
3920 We do something like this:
3921 declare a dummy coro frame.
3923 using handle_type = coro::coroutine_handle<coro1::promise_type>;
3924 void (*__resume)(_R_frame *);
3925 void (*__destroy)(_R_frame *);
3926 coro1::promise_type __p;
3927 bool frame_needs_free; free the coro frame mem if set.
3928 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
3930 handle_type self_handle;
3931 (maybe) parameter copies.
3932 (maybe) local variables saved (including awaitables)
3933 (maybe) trailing space.
3937 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
3939 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
3941 *resumer
= error_mark_node
;
3942 *destroyer
= error_mark_node
;
3943 if (!coro_function_valid_p (orig
))
3945 /* For early errors, we do not want a diagnostic about the missing
3946 ramp return value, since the user cannot fix this - a 'return' is
3947 not allowed in a coroutine. */
3948 TREE_NO_WARNING (orig
) = true;
3949 /* Discard the body, we can't process it further. */
3950 pop_stmt_list (DECL_SAVED_TREE (orig
));
3951 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3955 /* We can't validly get here with an empty statement list, since there's no
3956 way for the FE to decide it's a coroutine in the absence of any code. */
3957 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
3958 gcc_checking_assert (fnbody
!= NULL_TREE
);
3960 /* We don't have the locus of the opening brace - it's filled in later (and
3961 there doesn't really seem to be any easy way to get at it).
3962 The closing brace is assumed to be input_location. */
3963 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
3964 gcc_rich_location
fn_start_loc (fn_start
);
3966 /* Initial processing of the function-body.
3967 If we have no expressions or just an error then punt. */
3968 tree body_start
= expr_first (fnbody
);
3969 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
3971 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3972 append_to_statement_list (fnbody
, &DECL_SAVED_TREE (orig
));
3973 /* Suppress warnings about the missing return value. */
3974 TREE_NO_WARNING (orig
) = true;
3978 /* So, we've tied off the original user-authored body in fn_body.
3980 Start the replacement synthesized ramp body as newbody.
3981 If we encounter a fatal error we might return a now-empty body.
3983 Note, the returned ramp body is not 'popped', to be compatible with
3984 the way that decl.c handles regular functions, the scope pop is done
3987 tree newbody
= push_stmt_list ();
3988 DECL_SAVED_TREE (orig
) = newbody
;
3990 /* If our original body is noexcept, then that's what we apply to our
3991 generated ramp, transfer any MUST_NOT_THOW_EXPR to that. */
3992 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
3995 /* The function body we will continue with is the single operand to
3996 the must-not-throw. */
3997 fnbody
= TREE_OPERAND (body_start
, 0);
3998 /* Transfer the must-not-throw to the ramp body. */
3999 add_stmt (body_start
);
4000 /* Re-start the ramp as must-not-throw. */
4001 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
4004 /* Create the coro frame type, as far as it can be known at this stage.
4005 1. Types we already know. */
4007 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
4008 tree handle_type
= get_coroutine_handle_type (orig
);
4009 tree promise_type
= get_coroutine_promise_type (orig
);
4011 /* 2. Types we need to define or look up. */
4013 tree fr_name
= get_fn_local_identifier (orig
, "frame");
4014 tree coro_frame_type
= xref_tag (record_type
, fr_name
, ts_current
, false);
4015 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
4016 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
4017 tree act_des_fn_type
4018 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
4019 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
4021 /* Declare the actor and destroyer function. */
4022 tree actor
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "actor");
4023 tree destroy
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "destroy");
4025 /* Construct the wrapped function body; we will analyze this to determine
4026 the requirements for the coroutine frame. */
4028 tree resume_fn_field
= NULL_TREE
;
4029 tree fs_label
= NULL_TREE
;
4030 fnbody
= coro_rewrite_function_body (fn_start
, fnbody
, orig
, act_des_fn_ptr
,
4031 resume_fn_field
, fs_label
);
4032 /* Build our dummy coro frame layout. */
4033 coro_frame_type
= begin_class_definition (coro_frame_type
);
4035 tree field_list
= NULL_TREE
;
4037 = coro_make_frame_entry (&field_list
, "__resume",
4038 act_des_fn_ptr
, fn_start
);
4040 = coro_make_frame_entry (&field_list
, "__destroy",
4041 act_des_fn_ptr
, fn_start
);
4043 = coro_make_frame_entry (&field_list
, "__p", promise_type
, fn_start
);
4044 tree fnf_name
= coro_make_frame_entry (&field_list
, "__frame_needs_free",
4045 boolean_type_node
, fn_start
);
4046 tree resume_idx_name
4047 = coro_make_frame_entry (&field_list
, "__resume_at",
4048 short_unsigned_type_node
, fn_start
);
4050 /* We need a handle to this coroutine, which is passed to every
4051 await_suspend(). There's no point in creating it over and over. */
4052 (void) coro_make_frame_entry (&field_list
, "__self_h", handle_type
, fn_start
);
4054 /* Now add in fields for function params (if there are any).
4055 We do not attempt elision of copies at this stage, we do analyze the
4056 uses and build worklists to replace those when the state machine is
4059 hash_map
<tree
, param_info
> *param_uses
= NULL
;
4060 if (DECL_ARGUMENTS (orig
))
4062 /* Build a hash map with an entry for each param.
4063 The key is the param tree.
4064 Then we have an entry for the frame field name.
4065 Then a cache for the field ref when we come to use it.
4066 Then a tree list of the uses.
4067 The second two entries start out empty - and only get populated
4068 when we see uses. */
4069 param_uses
= new hash_map
<tree
, param_info
>;
4070 bool lambda_p
= LAMBDA_FUNCTION_P (orig
);
4072 unsigned no_name_parm
= 0;
4073 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4074 arg
= DECL_CHAIN (arg
))
4077 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4078 gcc_checking_assert (!existed
);
4079 parm
.body_uses
= NULL
;
4080 tree actual_type
= TREE_TYPE (arg
);
4081 actual_type
= complete_type_or_else (actual_type
, orig
);
4082 if (actual_type
== NULL_TREE
)
4083 actual_type
= error_mark_node
;
4084 parm
.orig_type
= actual_type
;
4085 parm
.by_ref
= parm
.pt_ref
= false;
4086 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
4088 /* If the user passes by reference, then we will save the
4089 pointer to the original. As noted in
4090 [dcl.fct.def.coroutine] / 13, if the lifetime of the
4091 referenced item ends and then the coroutine is resumed,
4092 we have UB; well, the user asked for it. */
4093 actual_type
= build_pointer_type (TREE_TYPE (actual_type
));
4096 else if (TYPE_REF_P (DECL_ARG_TYPE (arg
)))
4099 parm
.frame_type
= actual_type
;
4101 parm
.this_ptr
= is_this_parameter (arg
);
4102 parm
.lambda_cobj
= lambda_p
&& DECL_NAME (arg
) == closure_identifier
;
4104 parm
.trivial_dtor
= TYPE_HAS_TRIVIAL_DESTRUCTOR (parm
.frame_type
);
4106 if (DECL_NAME (arg
))
4108 tree pname
= DECL_NAME (arg
);
4109 buf
= xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname
));
4112 buf
= xasprintf ("__unnamed_parm.%d", no_name_parm
++);
4113 parm
.field_id
= coro_make_frame_entry
4114 (&field_list
, buf
, actual_type
, DECL_SOURCE_LOCATION (arg
));
4118 /* We want to record every instance of param's use, so don't include
4119 a 'visited' hash_set on the tree walk, but only record a containing
4121 hash_set
<tree
*> visited
;
4122 param_frame_data param_data
4123 = {&field_list
, param_uses
, &visited
, fn_start
, false};
4124 cp_walk_tree (&fnbody
, register_param_uses
, ¶m_data
, NULL
);
4127 /* We need to know, and inspect, each suspend point in the function
4128 in several places. It's convenient to place this map out of line
4129 since it's used from tree walk callbacks. */
4130 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
4132 /* Now insert the data for any body await points, at this time we also need
4133 to promote any temporaries that are captured by reference (to regular
4134 vars) they will get added to the coro frame along with other locals. */
4135 susp_frame_data body_aw_points
4136 = {&field_list
, handle_type
, fs_label
, NULL
, NULL
, 0, 0,
4137 hash_set
<tree
> (), NULL
, NULL
, 0, false, false, false};
4138 body_aw_points
.block_stack
= make_tree_vector ();
4139 body_aw_points
.bind_stack
= make_tree_vector ();
4140 body_aw_points
.to_replace
= make_tree_vector ();
4141 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
4143 /* 4. Now make space for local vars, this is conservative again, and we
4144 would expect to delete unused entries later. */
4145 hash_map
<tree
, local_var_info
> local_var_uses
;
4146 local_vars_frame_data local_vars_data
4147 = {&field_list
, &local_var_uses
, 0, 0, fn_start
, false, false};
4148 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
4150 /* Tie off the struct for now, so that we can build offsets to the
4152 TYPE_FIELDS (coro_frame_type
) = field_list
;
4153 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
4154 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
4155 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
4157 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
4160 /* Now build the ramp function pieces. */
4161 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4162 add_stmt (ramp_bind
);
4163 tree ramp_body
= push_stmt_list ();
4165 tree coro_fp
= build_lang_decl (VAR_DECL
, get_identifier ("coro.frameptr"),
4167 tree varlist
= coro_fp
;
4169 /* Collected the scope vars we need ... only one for now. */
4170 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
4172 /* We're now going to create a new top level scope block for the ramp
4174 tree top_block
= make_node (BLOCK
);
4176 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
4177 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
4178 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
4180 /* The decl_expr for the coro frame pointer, initialize to zero so that we
4181 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4182 directly apparently). This avoids a "used uninitialized" warning. */
4183 tree zeroinit
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
4184 DECL_INITIAL (coro_fp
) = zeroinit
;
4185 add_decl_expr (coro_fp
);
4187 /* The CO_FRAME internal function is a mechanism to allow the middle end
4188 to adjust the allocation in response to optimizations. We provide the
4189 current conservative estimate of the frame size (as per the current)
4191 tree frame_size
= TYPE_SIZE_UNIT (coro_frame_type
);
4193 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
4194 frame_size
, coro_fp
);
4196 /* [dcl.fct.def.coroutine] / 10 (part1)
4197 The unqualified-id get_return_object_on_allocation_failure is looked up
4198 in the scope of the promise type by class member access lookup. */
4200 /* We don't require this, so coro_build_promise_expression can return NULL,
4201 but, if the lookup succeeds, then the function must be usable. */
4202 tree dummy_promise
= build_dummy_object (get_coroutine_promise_type (orig
));
4204 = coro_build_promise_expression (orig
, dummy_promise
,
4205 coro_gro_on_allocation_fail_identifier
,
4206 fn_start
, NULL
, /*musthave=*/false);
4208 /* however, should that fail, returning an error, the later stages can't
4209 handle the erroneous expression, so we reset the call as if it was
4211 if (grooaf
== error_mark_node
)
4214 /* Allocate the frame, this has several possibilities:
4215 [dcl.fct.def.coroutine] / 9 (part 1)
4216 The allocation function’s name is looked up in the scope of the promise
4217 type. It's not a failure for it to be absent see part 4, below. */
4219 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
4220 tree new_fn
= NULL_TREE
;
4222 if (TYPE_HAS_NEW_OPERATOR (promise_type
))
4224 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
4226 /* [dcl.fct.def.coroutine] / 9 (part 2)
4227 If the lookup finds an allocation function in the scope of the promise
4228 type, overload resolution is performed on a function call created by
4229 assembling an argument list. The first argument is the amount of space
4230 requested, and has type std::size_t. The succeeding arguments are
4231 those of the original function. */
4232 vec
<tree
, va_gc
> *args
= make_tree_vector ();
4233 vec_safe_push (args
, resizeable
); /* Space needed. */
4235 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4236 arg
= DECL_CHAIN (arg
))
4238 param_info
*parm_i
= param_uses
->get (arg
);
4239 gcc_checking_assert (parm_i
);
4240 if (parm_i
->this_ptr
|| parm_i
->lambda_cobj
)
4242 /* We pass a reference to *this to the allocator lookup. */
4243 tree tt
= TREE_TYPE (TREE_TYPE (arg
));
4244 tree this_ref
= build1 (INDIRECT_REF
, tt
, arg
);
4245 tt
= cp_build_reference_type (tt
, false);
4246 this_ref
= convert_to_reference (tt
, this_ref
, CONV_STATIC
,
4247 LOOKUP_NORMAL
, NULL_TREE
,
4248 tf_warning_or_error
);
4249 vec_safe_push (args
, this_ref
);
4252 vec_safe_push (args
, arg
);
4255 /* Note the function selected; we test to see if it's NOTHROW. */
4257 /* Failure is not an error for this attempt. */
4258 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
, NULL
,
4259 LOOKUP_NORMAL
, &func
, tf_none
);
4260 release_tree_vector (args
);
4262 if (new_fn
== error_mark_node
)
4264 /* [dcl.fct.def.coroutine] / 9 (part 3)
4265 If no viable function is found, overload resolution is performed
4266 again on a function call created by passing just the amount of
4267 space required as an argument of type std::size_t. */
4268 args
= make_tree_vector_single (resizeable
); /* Space needed. */
4269 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
,
4270 NULL_TREE
, LOOKUP_NORMAL
, &func
,
4272 release_tree_vector (args
);
4275 /* However, if the promise provides an operator new, then one of these
4276 two options must be available. */
4277 if (new_fn
== error_mark_node
)
4279 error_at (fn_start
, "%qE is provided by %qT but is not usable with"
4280 " the function signature %qD", nwname
, promise_type
, orig
);
4281 new_fn
= error_mark_node
;
4283 else if (grooaf
&& !TYPE_NOTHROW_P (TREE_TYPE (func
)))
4284 error_at (fn_start
, "%qE is provided by %qT but %qE is not marked"
4285 " %<throw()%> or %<noexcept%>", grooaf
, promise_type
, nwname
);
4286 else if (!grooaf
&& TYPE_NOTHROW_P (TREE_TYPE (func
)))
4287 warning_at (fn_start
, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4288 " no usable %<get_return_object_on_allocation_failure%>"
4289 " is provided by %qT", nwname
, promise_type
);
4291 else /* No operator new in the promise. */
4293 /* [dcl.fct.def.coroutine] / 9 (part 4)
4294 If this lookup fails, the allocation function’s name is looked up in
4295 the global scope. */
4297 vec
<tree
, va_gc
> *args
;
4298 /* build_operator_new_call () will insert size needed as element 0 of
4299 this, and we might need to append the std::nothrow constant. */
4300 vec_alloc (args
, 2);
4303 /* [dcl.fct.def.coroutine] / 10 (part 2)
4304 If any declarations (of the get return on allocation fail) are
4305 found, then the result of a call to an allocation function used
4306 to obtain storage for the coroutine state is assumed to return
4307 nullptr if it fails to obtain storage and, if a global allocation
4308 function is selected, the ::operator new(size_t, nothrow_t) form
4309 is used. The allocation function used in this case shall have a
4310 non-throwing noexcept-specification. So we need std::nothrow. */
4311 tree std_nt
= lookup_qualified_name (std_node
,
4312 get_identifier ("nothrow"),
4314 /*complain=*/true, false);
4315 if (!std_nt
|| std_nt
== error_mark_node
)
4316 error_at (fn_start
, "%qE is provided by %qT but %<std::nothrow%> "
4317 "cannot be found", grooaf
, promise_type
);
4318 vec_safe_push (args
, std_nt
);
4321 /* If we get to this point, we must succeed in looking up the global
4322 operator new for the params provided. Extract a simplified version
4323 of the machinery from build_operator_new_call. This can update the
4326 new_fn
= build_operator_new_call (nwname
, &args
, &frame_size
, &cookie
,
4328 /*size_check=*/NULL
, /*fn=*/NULL
,
4329 tf_warning_or_error
);
4330 resizeable
= build_call_expr_internal_loc
4331 (fn_start
, IFN_CO_FRAME
, size_type_node
, 2, frame_size
, coro_fp
);
4332 /* If the operator call fails for some reason, then don't try to
4334 if (new_fn
!= error_mark_node
)
4335 CALL_EXPR_ARG (new_fn
, 0) = resizeable
;
4337 release_tree_vector (args
);
4340 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
4341 tree r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, allocated
);
4342 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4345 /* If the user provided a method to return an object on alloc fail, then
4346 check the returned pointer and call the func if it's null.
4347 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
4351 /* [dcl.fct.def.coroutine] / 10 (part 3)
4352 If the allocation function returns nullptr,the coroutine returns
4353 control to the caller of the coroutine and the return value is
4354 obtained by a call to T::get_return_object_on_allocation_failure(),
4355 where T is the promise type. */
4357 gcc_checking_assert (same_type_p (fn_return_type
, TREE_TYPE (grooaf
)));
4358 tree if_stmt
= begin_if_stmt ();
4359 tree cond
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
4360 cond
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, cond
);
4361 finish_if_stmt_cond (cond
, if_stmt
);
4362 if (VOID_TYPE_P (fn_return_type
))
4364 /* Execute the get-return-object-on-alloc-fail call... */
4365 finish_expr_stmt (grooaf
);
4366 /* ... but discard the result, since we return void. */
4367 finish_return_stmt (NULL_TREE
);
4371 /* Get the fallback return object. */
4372 r
= build_cplus_new (fn_return_type
, grooaf
, tf_warning_or_error
);
4373 finish_return_stmt (r
);
4375 finish_then_clause (if_stmt
);
4376 finish_if_stmt (if_stmt
);
4379 /* deref the frame pointer, to use in member access code. */
4380 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
4382 /* For now, once allocation has succeeded we always assume that this needs
4383 destruction, there's no impl. for frame allocation elision. */
4385 = lookup_member (coro_frame_type
, fnf_name
, 1, 0, tf_warning_or_error
);
4386 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
4387 false, tf_warning_or_error
);
4388 r
= build2 (INIT_EXPR
, boolean_type_node
, fnf_x
, boolean_true_node
);
4389 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4392 /* Put the resumer and destroyer functions in. */
4394 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
4396 = lookup_member (coro_frame_type
, resume_name
,
4397 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4398 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
4399 false, tf_warning_or_error
);
4400 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, resume_x
, actor_addr
);
4401 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4404 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
4406 = lookup_member (coro_frame_type
, destroy_name
,
4407 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4409 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
4410 tf_warning_or_error
);
4411 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, destroy_x
, destroy_addr
);
4412 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4415 /* [dcl.fct.def.coroutine] /13
4416 When a coroutine is invoked, a copy is created for each coroutine
4417 parameter. Each such copy is an object with automatic storage duration
4418 that is direct-initialized from an lvalue referring to the corresponding
4419 parameter if the parameter is an lvalue reference, and from an xvalue
4420 referring to it otherwise. A reference to a parameter in the function-
4421 body of the coroutine and in the call to the coroutine promise
4422 constructor is replaced by a reference to its copy. */
4424 vec
<tree
, va_gc
> *promise_args
= NULL
; /* So that we can adjust refs. */
4426 /* The initialization and destruction of each parameter copy occurs in the
4427 context of the called coroutine. Initializations of parameter copies are
4428 sequenced before the call to the coroutine promise constructor and
4429 indeterminately sequenced with respect to each other. The lifetime of
4430 parameter copies ends immediately after the lifetime of the coroutine
4431 promise object ends. */
4433 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
4435 if (DECL_ARGUMENTS (orig
))
4437 promise_args
= make_tree_vector ();
4438 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
4439 arg
= DECL_CHAIN (arg
))
4442 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
4444 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
4445 /*protect=*/1, /*want_type=*/0,
4446 tf_warning_or_error
);
4448 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
4449 false, tf_warning_or_error
);
4451 /* Add this to the promise CTOR arguments list, accounting for
4452 refs and special handling for method this ptr. */
4453 if (parm
.this_ptr
|| parm
.lambda_cobj
)
4455 /* We pass a reference to *this to the param preview. */
4456 tree tt
= TREE_TYPE (arg
);
4457 gcc_checking_assert (POINTER_TYPE_P (tt
));
4458 tree ct
= TREE_TYPE (tt
);
4459 tree this_ref
= build1 (INDIRECT_REF
, ct
, arg
);
4460 tree rt
= cp_build_reference_type (ct
, false);
4461 this_ref
= convert_to_reference (rt
, this_ref
, CONV_STATIC
,
4462 LOOKUP_NORMAL
, NULL_TREE
,
4463 tf_warning_or_error
);
4464 vec_safe_push (promise_args
, this_ref
);
4466 else if (parm
.by_ref
)
4467 vec_safe_push (promise_args
, fld_idx
);
4469 vec_safe_push (promise_args
, arg
);
4471 if (TYPE_NEEDS_CONSTRUCTING (parm
.frame_type
))
4473 vec
<tree
, va_gc
> *p_in
;
4474 if (CLASS_TYPE_P (parm
.frame_type
)
4475 && classtype_has_non_deleted_move_ctor (parm
.frame_type
))
4476 p_in
= make_tree_vector_single (move (arg
));
4477 else if (lvalue_p (arg
))
4478 p_in
= make_tree_vector_single (rvalue (arg
));
4480 p_in
= make_tree_vector_single (arg
);
4481 /* Construct in place or move as relevant. */
4482 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
4483 &p_in
, parm
.frame_type
,
4485 tf_warning_or_error
);
4486 release_tree_vector (p_in
);
4490 if (!same_type_p (parm
.frame_type
, DECL_ARG_TYPE (arg
)))
4491 r
= build1_loc (DECL_SOURCE_LOCATION (arg
), CONVERT_EXPR
,
4492 parm
.frame_type
, arg
);
4495 r
= build_modify_expr (fn_start
, fld_idx
, parm
.frame_type
,
4496 INIT_EXPR
, DECL_SOURCE_LOCATION (arg
), r
,
4499 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4501 if (!parm
.trivial_dtor
)
4503 if (param_dtor_list
== NULL
)
4504 param_dtor_list
= make_tree_vector ();
4505 vec_safe_push (param_dtor_list
, parm
.field_id
);
4510 /* Set up the promise. */
4512 = lookup_member (coro_frame_type
, promise_name
,
4513 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4515 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
4516 false, tf_warning_or_error
);
4518 if (TYPE_NEEDS_CONSTRUCTING (promise_type
))
4520 /* Do a placement new constructor for the promise type (we never call
4521 the new operator, just the constructor on the object in place in the
4524 First try to find a constructor with the same parameter list as the
4525 original function (if it has params), failing that find a constructor
4526 with no parameter list. */
4528 if (DECL_ARGUMENTS (orig
))
4530 r
= build_special_member_call (p
, complete_ctor_identifier
,
4531 &promise_args
, promise_type
,
4532 LOOKUP_NORMAL
, tf_none
);
4533 release_tree_vector (promise_args
);
4538 if (r
== NULL_TREE
|| r
== error_mark_node
)
4539 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
4540 promise_type
, LOOKUP_NORMAL
,
4541 tf_warning_or_error
);
4543 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4547 /* Set up a new bind context for the GRO. */
4548 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
4549 /* Make and connect the scope blocks. */
4550 tree gro_block
= make_node (BLOCK
);
4551 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
4552 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
4553 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
4554 add_stmt (gro_context_bind
);
4557 = coro_build_promise_expression (orig
, p
,
4558 coro_get_return_object_identifier
,
4559 fn_start
, NULL
, /*musthave=*/true);
4560 /* Without a return object we haven't got much clue what's going on. */
4561 if (get_ro
== error_mark_node
)
4563 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4564 DECL_SAVED_TREE (orig
) = newbody
;
4565 /* Suppress warnings about the missing return value. */
4566 TREE_NO_WARNING (orig
) = true;
4570 tree gro_context_body
= push_stmt_list ();
4571 tree gro_type
= TREE_TYPE (get_ro
);
4572 bool gro_is_void_p
= VOID_TYPE_P (gro_type
);
4574 tree gro
= NULL_TREE
;
4575 tree gro_bind_vars
= NULL_TREE
;
4576 tree gro_cleanup_stmt
= NULL_TREE
;
4577 /* We have to sequence the call to get_return_object before initial
4581 else if (same_type_p (gro_type
, fn_return_type
))
4583 /* [dcl.fct.def.coroutine] / 7
4584 The expression promise.get_return_object() is used to initialize the
4585 glvalue result or... (see below)
4586 Construct the return result directly. */
4587 if (TYPE_NEEDS_CONSTRUCTING (gro_type
))
4589 vec
<tree
, va_gc
> *arg
= make_tree_vector_single (get_ro
);
4590 r
= build_special_member_call (DECL_RESULT (orig
),
4591 complete_ctor_identifier
,
4592 &arg
, gro_type
, LOOKUP_NORMAL
,
4593 tf_warning_or_error
);
4594 release_tree_vector (arg
);
4597 r
= build2_loc (fn_start
, INIT_EXPR
, gro_type
,
4598 DECL_RESULT (orig
), get_ro
);
4602 /* ... or ... Construct an object that will be used as the single
4603 param to the CTOR for the return object. */
4604 gro
= build_lang_decl (VAR_DECL
, get_identifier ("coro.gro"), gro_type
);
4605 DECL_CONTEXT (gro
) = current_scope ();
4606 DECL_ARTIFICIAL (gro
) = true;
4607 DECL_IGNORED_P (gro
) = true;
4608 add_decl_expr (gro
);
4609 gro_bind_vars
= gro
;
4610 if (TYPE_NEEDS_CONSTRUCTING (gro_type
))
4612 vec
<tree
, va_gc
> *arg
= make_tree_vector_single (get_ro
);
4613 r
= build_special_member_call (gro
, complete_ctor_identifier
,
4614 &arg
, gro_type
, LOOKUP_NORMAL
,
4615 tf_warning_or_error
);
4616 release_tree_vector (arg
);
4619 r
= build2_loc (fn_start
, INIT_EXPR
, gro_type
, gro
, get_ro
);
4620 /* The constructed object might require a cleanup. */
4621 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type
))
4624 = build_special_member_call (gro
, complete_dtor_identifier
,
4625 NULL
, gro_type
, LOOKUP_NORMAL
,
4626 tf_warning_or_error
);
4627 gro_cleanup_stmt
= build_stmt (input_location
, CLEANUP_STMT
, NULL
,
4631 finish_expr_stmt (r
);
4633 if (gro_cleanup_stmt
)
4634 CLEANUP_BODY (gro_cleanup_stmt
) = push_stmt_list ();
4636 /* Initialize the resume_idx_name to 0, meaning "not started". */
4638 = lookup_member (coro_frame_type
, resume_idx_name
,
4639 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
4641 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
4642 tf_warning_or_error
);
4643 r
= build_int_cst (short_unsigned_type_node
, 0);
4644 r
= build2_loc (fn_start
, INIT_EXPR
, short_unsigned_type_node
, resume_idx
, r
);
4645 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
4648 /* So .. call the actor .. */
4649 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
4650 r
= maybe_cleanup_point_expr_void (r
);
4653 /* Switch to using 'input_location' as the loc, since we're now more
4654 logically doing things related to the end of the function. */
4656 /* The ramp is done, we just need the return value.
4657 [dcl.fct.def.coroutine] / 7
4658 The expression promise.get_return_object() is used to initialize the
4659 glvalue result or prvalue result object of a call to a coroutine.
4661 If the 'get return object' is non-void, then we built it before the
4662 promise was constructed. We now supply a reference to that var,
4663 either as the return value (if it's the same type) or to the CTOR
4664 for an object of the return type. */
4666 if (same_type_p (gro_type
, fn_return_type
))
4667 r
= gro_is_void_p
? NULL_TREE
: DECL_RESULT (orig
);
4670 if (CLASS_TYPE_P (fn_return_type
))
4672 /* For class type return objects, we can attempt to construct,
4673 even if the gro is void. */
4674 vec
<tree
, va_gc
> *args
= NULL
;
4675 vec
<tree
, va_gc
> **arglist
= NULL
;
4678 args
= make_tree_vector_single (rvalue (gro
));
4681 r
= build_special_member_call (NULL_TREE
,
4682 complete_ctor_identifier
, arglist
,
4683 fn_return_type
, LOOKUP_NORMAL
,
4684 tf_warning_or_error
);
4685 r
= build_cplus_new (fn_return_type
, r
, tf_warning_or_error
);
4687 release_tree_vector (args
);
4689 else if (gro_is_void_p
)
4691 /* We can't initialize a non-class return value from void. */
4692 error_at (input_location
, "cannot initialize a return object of type"
4693 " %qT with an rvalue of type %<void%>", fn_return_type
);
4694 r
= error_mark_node
;
4697 r
= build1_loc (input_location
, CONVERT_EXPR
,
4698 fn_return_type
, rvalue (gro
));
4701 finish_return_stmt (r
);
4703 if (gro_cleanup_stmt
)
4705 CLEANUP_BODY (gro_cleanup_stmt
)
4706 = pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt
));
4707 add_stmt (gro_cleanup_stmt
);
4710 /* Finish up the ramp function. */
4711 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
4712 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
4713 TREE_SIDE_EFFECTS (gro_context_bind
) = true;
4714 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
4715 TREE_SIDE_EFFECTS (ramp_bind
) = true;
4717 /* Start to build the final functions.
4719 We push_deferring_access_checks to avoid these routines being seen as
4720 nested by the middle end; we are doing the outlining here. */
4722 push_deferring_access_checks (dk_no_check
);
4724 /* Build the actor... */
4725 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
, param_uses
,
4726 &local_var_uses
, param_dtor_list
, resume_fn_field
,
4727 body_aw_points
.await_number
, frame_size
);
4730 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
4732 pop_deferring_access_checks ();
4734 DECL_SAVED_TREE (orig
) = newbody
;
4735 /* Link our new functions into the list. */
4736 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
4737 TREE_CHAIN (actor
) = destroy
;
4738 TREE_CHAIN (orig
) = actor
;
4741 *destroyer
= destroy
;
4743 delete suspend_points
;
4744 suspend_points
= NULL
;
4748 #include "gt-cp-coroutines.h"