1 /* coroutine-specific state, expansions and tests.
3 Copyright (C) 2018-2020 Free Software Foundation, Inc.
5 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
7 This file is part of GCC.
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3. If not see
21 <http://www.gnu.org/licenses/>. */
25 #include "coretypes.h"
28 #include "stringpool.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
33 #include "gcc-rich-location.h"
36 static bool coro_promise_type_found_p (tree
, location_t
);
38 /* GCC C++ coroutines implementation.
40 The user authors a function that becomes a coroutine (lazily) by
41 making use of any of the co_await, co_yield or co_return keywords.
43 Unlike a regular function, where the activation record is placed on the
44 stack, and is destroyed on function exit, a coroutine has some state that
45 persists between calls - the coroutine frame (analogous to a stack frame).
47 We transform the user's function into three pieces:
48 1. A so-called ramp function, that establishes the coroutine frame and
49 begins execution of the coroutine.
50 2. An actor function that contains the state machine corresponding to the
51 user's suspend/resume structure.
52 3. A stub function that calls the actor function in 'destroy' mode.
54 The actor function is executed:
55 * from "resume point 0" by the ramp.
56 * from resume point N ( > 0 ) for handle.resume() calls.
57 * from the destroy stub for destroy point N for handle.destroy() calls.
59 The functions in this file carry out the necessary analysis of, and
60 transforms to, the AST to perform this.
62 The C++ coroutine design makes use of some helper functions that are
63 authored in a so-called "promise" class provided by the user.
65 At parse time (or post substitution) the type of the coroutine promise
66 will be determined. At that point, we can look up the required promise
67 class methods and issue diagnostics if they are missing or incorrect. To
68 avoid repeating these actions at code-gen time, we make use of temporary
69 'proxy' variables for the coroutine handle and the promise - which will
70 eventually be instantiated in the coroutine frame.
72 Each of the keywords will expand to a code sequence (although co_yield is
73 just syntactic sugar for a co_await).
75 We defer the analysis and transformation until template expansion is
76 complete so that we have complete types at that time. */
79 /* The state that we collect during parsing (and template expansion) for
82 struct GTY((for_user
)) coroutine_info
84 tree function_decl
; /* The original function decl. */
85 tree promise_type
; /* The cached promise type for this function. */
86 tree handle_type
; /* The cached coroutine handle for this function. */
87 tree self_h_proxy
; /* A handle instance that is used as the proxy for the
88 one that will eventually be allocated in the coroutine
90 tree promise_proxy
; /* Likewise, a proxy promise instance. */
91 location_t first_coro_keyword
; /* The location of the keyword that made this
92 function into a coroutine. */
93 /* Flags to avoid repeated errors for per-function issues. */
94 bool coro_ret_type_error_emitted
;
95 bool coro_promise_error_emitted
;
98 struct coroutine_info_hasher
: ggc_ptr_hash
<coroutine_info
>
100 typedef tree compare_type
; /* We only compare the function decl. */
101 static inline hashval_t
hash (coroutine_info
*);
102 static inline hashval_t
hash (const compare_type
&);
103 static inline bool equal (coroutine_info
*, coroutine_info
*);
104 static inline bool equal (coroutine_info
*, const compare_type
&);
107 /* This table holds all the collected coroutine state for coroutines in
108 the current translation unit. */
110 static GTY (()) hash_table
<coroutine_info_hasher
> *coroutine_info_table
;
112 /* We will initialise state lazily. */
113 static bool coro_initialized
= false;
115 /* Return a hash value for the entry pointed to by INFO.
116 The compare type is a tree, but the only trees we are going use are
117 function decls. We use the DECL_UID as the hash value since that is
118 stable across PCH. */
121 coroutine_info_hasher::hash (coroutine_info
*info
)
123 return DECL_UID (info
->function_decl
);
126 /* Return a hash value for the compare value COMP. */
129 coroutine_info_hasher::hash (const compare_type
& comp
)
131 return DECL_UID (comp
);
134 /* Return true if the entries pointed to by LHS and RHS are for the
138 coroutine_info_hasher::equal (coroutine_info
*lhs
, coroutine_info
*rhs
)
140 return lhs
->function_decl
== rhs
->function_decl
;
144 coroutine_info_hasher::equal (coroutine_info
*lhs
, const compare_type
& rhs
)
146 return lhs
->function_decl
== rhs
;
149 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
150 entry does not yet exist. */
153 get_or_insert_coroutine_info (tree fn_decl
)
155 gcc_checking_assert (coroutine_info_table
!= NULL
);
157 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
158 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), INSERT
);
162 *slot
= new (ggc_cleared_alloc
<coroutine_info
> ()) coroutine_info ();
163 (*slot
)->function_decl
= fn_decl
;
169 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
172 get_coroutine_info (tree fn_decl
)
174 if (coroutine_info_table
== NULL
)
177 coroutine_info
**slot
= coroutine_info_table
->find_slot_with_hash
178 (fn_decl
, coroutine_info_hasher::hash (fn_decl
), NO_INSERT
);
184 /* We will lazily create all the identifiers that are used by coroutines
185 on the first attempt to lookup the traits. */
187 /* Identifiers that are used by all coroutines. */
189 static GTY(()) tree coro_traits_identifier
;
190 static GTY(()) tree coro_handle_identifier
;
191 static GTY(()) tree coro_promise_type_identifier
;
193 /* Required promise method name identifiers. */
195 static GTY(()) tree coro_await_transform_identifier
;
196 static GTY(()) tree coro_initial_suspend_identifier
;
197 static GTY(()) tree coro_final_suspend_identifier
;
198 static GTY(()) tree coro_return_void_identifier
;
199 static GTY(()) tree coro_return_value_identifier
;
200 static GTY(()) tree coro_yield_value_identifier
;
201 static GTY(()) tree coro_resume_identifier
;
202 static GTY(()) tree coro_address_identifier
;
203 static GTY(()) tree coro_from_address_identifier
;
204 static GTY(()) tree coro_get_return_object_identifier
;
205 static GTY(()) tree coro_gro_on_allocation_fail_identifier
;
206 static GTY(()) tree coro_unhandled_exception_identifier
;
208 /* Awaitable methods. */
210 static GTY(()) tree coro_await_ready_identifier
;
211 static GTY(()) tree coro_await_suspend_identifier
;
212 static GTY(()) tree coro_await_resume_identifier
;
214 /* Create the identifiers used by the coroutines library interfaces. */
217 coro_init_identifiers ()
219 coro_traits_identifier
= get_identifier ("coroutine_traits");
220 coro_handle_identifier
= get_identifier ("coroutine_handle");
221 coro_promise_type_identifier
= get_identifier ("promise_type");
223 coro_await_transform_identifier
= get_identifier ("await_transform");
224 coro_initial_suspend_identifier
= get_identifier ("initial_suspend");
225 coro_final_suspend_identifier
= get_identifier ("final_suspend");
226 coro_return_void_identifier
= get_identifier ("return_void");
227 coro_return_value_identifier
= get_identifier ("return_value");
228 coro_yield_value_identifier
= get_identifier ("yield_value");
229 coro_resume_identifier
= get_identifier ("resume");
230 coro_address_identifier
= get_identifier ("address");
231 coro_from_address_identifier
= get_identifier ("from_address");
232 coro_get_return_object_identifier
= get_identifier ("get_return_object");
233 coro_gro_on_allocation_fail_identifier
=
234 get_identifier ("get_return_object_on_allocation_failure");
235 coro_unhandled_exception_identifier
= get_identifier ("unhandled_exception");
237 coro_await_ready_identifier
= get_identifier ("await_ready");
238 coro_await_suspend_identifier
= get_identifier ("await_suspend");
239 coro_await_resume_identifier
= get_identifier ("await_resume");
242 /* Trees we only need to set up once. */
244 static GTY(()) tree coro_traits_templ
;
245 static GTY(()) tree coro_handle_templ
;
246 static GTY(()) tree void_coro_handle_type
;
248 /* ================= Parse, Semantics and Type checking ================= */
250 /* This initial set of routines are helper for the parsing and template
253 At the completion of this, we will have completed trees for each of the
254 keywords, but making use of proxy variables for the self-handle and the
255 promise class instance. */
257 /* [coroutine.traits]
258 Lookup the coroutine_traits template decl. */
261 find_coro_traits_template_decl (location_t kw
)
263 /* If we are missing fundmental information, such as the traits, (or the
264 declaration found is not a type template), then don't emit an error for
265 every keyword in a TU, just do it once. */
266 static bool traits_error_emitted
= false;
268 tree traits_decl
= lookup_qualified_name (std_node
, coro_traits_identifier
,
270 /*complain=*/!traits_error_emitted
);
271 if (traits_decl
== error_mark_node
272 || !DECL_TYPE_TEMPLATE_P (traits_decl
))
274 if (!traits_error_emitted
)
276 gcc_rich_location
richloc (kw
);
277 error_at (&richloc
, "coroutines require a traits template; cannot"
278 " find %<%E::%E%>", std_node
, coro_traits_identifier
);
279 inform (&richloc
, "perhaps %<#include <coroutine>%> is missing");
280 traits_error_emitted
= true;
288 /* Instantiate Coroutine traits for the function signature. */
291 instantiate_coro_traits (tree fndecl
, location_t kw
)
293 /* [coroutine.traits.primary]
294 So now build up a type list for the template <typename _R, typename...>.
295 The types are the function's arg types and _R is the function return
298 tree functyp
= TREE_TYPE (fndecl
);
299 tree arg_node
= TYPE_ARG_TYPES (functyp
);
300 tree argtypes
= make_tree_vec (list_length (arg_node
)-1);
303 while (arg_node
!= NULL_TREE
&& !VOID_TYPE_P (TREE_VALUE (arg_node
)))
305 TREE_VEC_ELT (argtypes
, p
++) = TREE_VALUE (arg_node
);
306 arg_node
= TREE_CHAIN (arg_node
);
309 tree argtypepack
= cxx_make_type (TYPE_ARGUMENT_PACK
);
310 SET_ARGUMENT_PACK_ARGS (argtypepack
, argtypes
);
312 tree targ
= make_tree_vec (2);
313 TREE_VEC_ELT (targ
, 0) = TREE_TYPE (functyp
);
314 TREE_VEC_ELT (targ
, 1) = argtypepack
;
317 = lookup_template_class (coro_traits_templ
, targ
,
318 /*in_decl=*/NULL_TREE
, /*context=*/NULL_TREE
,
319 /*entering scope=*/false, tf_warning_or_error
);
321 if (traits_class
== error_mark_node
)
323 error_at (kw
, "cannot instantiate %<coroutine traits%>");
330 /* [coroutine.handle] */
333 find_coro_handle_template_decl (location_t kw
)
335 /* As for the coroutine traits, this error is per TU, so only emit
337 static bool coro_handle_error_emitted
= false;
338 tree handle_decl
= lookup_qualified_name (std_node
, coro_handle_identifier
,
339 0, !coro_handle_error_emitted
);
340 if (handle_decl
== error_mark_node
341 || !DECL_CLASS_TEMPLATE_P (handle_decl
))
343 if (!coro_handle_error_emitted
)
344 error_at (kw
, "coroutines require a handle class template;"
345 " cannot find %<%E::%E%>", std_node
, coro_handle_identifier
);
346 coro_handle_error_emitted
= true;
353 /* Instantiate the handle template for a given promise type. */
356 instantiate_coro_handle_for_promise_type (location_t kw
, tree promise_type
)
358 /* So now build up a type list for the template, one entry, the promise. */
359 tree targ
= make_tree_vec (1);
360 TREE_VEC_ELT (targ
, 0) = promise_type
;
362 = lookup_template_class (coro_handle_identifier
, targ
,
363 /* in_decl=*/NULL_TREE
,
364 /* context=*/std_node
,
365 /* entering scope=*/false, tf_warning_or_error
);
367 if (handle_type
== error_mark_node
)
369 error_at (kw
, "cannot instantiate a %<coroutine handle%> for"
370 " promise type %qT", promise_type
);
377 /* Look for the promise_type in the instantiated traits. */
380 find_promise_type (tree traits_class
)
383 = lookup_member (traits_class
, coro_promise_type_identifier
,
384 /* protect=*/1, /*want_type=*/true, tf_warning_or_error
);
388 = complete_type_or_else (TREE_TYPE (promise_type
), promise_type
);
390 /* NULL_TREE on fail. */
395 coro_promise_type_found_p (tree fndecl
, location_t loc
)
397 gcc_assert (fndecl
!= NULL_TREE
);
399 if (!coro_initialized
)
401 /* Trees we only need to create once.
402 Set up the identifiers we will use. */
403 coro_init_identifiers ();
405 /* Coroutine traits template. */
406 coro_traits_templ
= find_coro_traits_template_decl (loc
);
407 if (coro_traits_templ
== NULL_TREE
)
410 /* coroutine_handle<> template. */
411 coro_handle_templ
= find_coro_handle_template_decl (loc
);
412 if (coro_handle_templ
== NULL_TREE
)
415 /* We can also instantiate the void coroutine_handle<> */
416 void_coro_handle_type
=
417 instantiate_coro_handle_for_promise_type (loc
, NULL_TREE
);
418 if (void_coro_handle_type
== NULL_TREE
)
421 /* A table to hold the state, per coroutine decl. */
422 gcc_checking_assert (coroutine_info_table
== NULL
);
423 coroutine_info_table
=
424 hash_table
<coroutine_info_hasher
>::create_ggc (11);
426 if (coroutine_info_table
== NULL
)
429 coro_initialized
= true;
432 /* Save the coroutine data on the side to avoid the overhead on every
433 function decl tree. */
435 coroutine_info
*coro_info
= get_or_insert_coroutine_info (fndecl
);
436 /* Without this, we cannot really proceed. */
437 gcc_checking_assert (coro_info
);
439 /* If we don't already have a current promise type, try to look it up. */
440 if (coro_info
->promise_type
== NULL_TREE
)
442 /* Get the coroutine traits template class instance for the function
443 signature we have - coroutine_traits <R, ...> */
444 tree return_type
= TREE_TYPE (TREE_TYPE (fndecl
));
445 if (!CLASS_TYPE_P (return_type
))
447 /* It makes more sense to show the function header for this, even
448 though we will have encountered it when processing a keyword.
449 Only emit the error once, not for every keyword we encounter. */
450 if (!coro_info
->coro_ret_type_error_emitted
)
451 error_at (DECL_SOURCE_LOCATION (fndecl
), "coroutine return type"
452 " %qT is not a class", return_type
);
453 coro_info
->coro_ret_type_error_emitted
= true;
457 tree templ_class
= instantiate_coro_traits (fndecl
, loc
);
459 /* Find the promise type for that. */
460 coro_info
->promise_type
= find_promise_type (templ_class
);
462 /* If we don't find it, punt on the rest. */
463 if (coro_info
->promise_type
== NULL_TREE
)
465 if (!coro_info
->coro_promise_error_emitted
)
466 error_at (loc
, "unable to find the promise type for"
468 coro_info
->coro_promise_error_emitted
= true;
472 /* Try to find the handle type for the promise. */
474 instantiate_coro_handle_for_promise_type (loc
, coro_info
->promise_type
);
475 if (handle_type
== NULL_TREE
)
478 /* Complete this, we're going to use it. */
479 coro_info
->handle_type
= complete_type_or_else (handle_type
, fndecl
);
481 /* Diagnostic would be emitted by complete_type_or_else. */
482 if (!coro_info
->handle_type
)
485 /* Build a proxy for a handle to "self" as the param to
486 await_suspend() calls. */
487 coro_info
->self_h_proxy
488 = build_lang_decl (VAR_DECL
, get_identifier ("self_h.proxy"),
489 coro_info
->handle_type
);
491 /* Build a proxy for the promise so that we can perform lookups. */
492 coro_info
->promise_proxy
493 = build_lang_decl (VAR_DECL
, get_identifier ("promise.proxy"),
494 coro_info
->promise_type
);
496 /* Note where we first saw a coroutine keyword. */
497 coro_info
->first_coro_keyword
= loc
;
503 /* These functions assumes that the caller has verified that the state for
504 the decl has been initialized, we try to minimize work here. */
507 get_coroutine_promise_type (tree decl
)
509 if (coroutine_info
*info
= get_coroutine_info (decl
))
510 return info
->promise_type
;
516 get_coroutine_handle_type (tree decl
)
518 if (coroutine_info
*info
= get_coroutine_info (decl
))
519 return info
->handle_type
;
525 get_coroutine_self_handle_proxy (tree decl
)
527 if (coroutine_info
*info
= get_coroutine_info (decl
))
528 return info
->self_h_proxy
;
534 get_coroutine_promise_proxy (tree decl
)
536 if (coroutine_info
*info
= get_coroutine_info (decl
))
537 return info
->promise_proxy
;
543 lookup_promise_method (tree fndecl
, tree member_id
, location_t loc
,
546 tree promise
= get_coroutine_promise_type (fndecl
);
548 = lookup_member (promise
, member_id
,
549 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
550 if (musthave
&& pm_memb
== NULL_TREE
)
552 error_at (loc
, "no member named %qE in %qT", member_id
, promise
);
553 return error_mark_node
;
558 /* Lookup an Awaitable member, which should be await_ready, await_suspend
562 lookup_awaitable_member (tree await_type
, tree member_id
, location_t loc
)
565 = lookup_member (await_type
, member_id
,
566 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
567 if (aw_memb
== NULL_TREE
)
569 error_at (loc
, "no member named %qE in %qT", member_id
, await_type
);
570 return error_mark_node
;
575 /* Here we check the constraints that are common to all keywords (since the
576 presence of a coroutine keyword makes the function into a coroutine). */
579 coro_common_keyword_context_valid_p (tree fndecl
, location_t kw_loc
,
582 if (fndecl
== NULL_TREE
)
584 error_at (kw_loc
, "%qs cannot be used outside a function", kw_name
);
588 /* This is arranged in order of prohibitions in the std. */
589 if (DECL_MAIN_P (fndecl
))
591 /* [basic.start.main] 3. The function main shall not be a coroutine. */
592 error_at (kw_loc
, "%qs cannot be used in the %<main%> function",
597 if (DECL_DECLARED_CONSTEXPR_P (fndecl
))
599 /* [dcl.constexpr] 3.3 it shall not be a coroutine. */
600 error_at (kw_loc
, "%qs cannot be used in a %<constexpr%> function",
602 cp_function_chain
->invalid_constexpr
= true;
606 if (FNDECL_USED_AUTO (fndecl
))
608 /* [dcl.spec.auto] 15. A function declared with a return type that uses
609 a placeholder type shall not be a coroutine. */
611 "%qs cannot be used in a function with a deduced return type",
616 if (varargs_function_p (fndecl
))
618 /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
619 coroutine shall not terminate with an ellipsis that is not part
620 of a parameter-declaration. */
622 "%qs cannot be used in a varargs function", kw_name
);
626 if (DECL_CONSTRUCTOR_P (fndecl
))
628 /* [class.ctor] 7. a constructor shall not be a coroutine. */
629 error_at (kw_loc
, "%qs cannot be used in a constructor", kw_name
);
633 if (DECL_DESTRUCTOR_P (fndecl
))
635 /* [class.dtor] 21. a destructor shall not be a coroutine. */
636 error_at (kw_loc
, "%qs cannot be used in a destructor", kw_name
);
643 /* Here we check the constraints that are not per keyword. */
646 coro_function_valid_p (tree fndecl
)
648 location_t f_loc
= DECL_SOURCE_LOCATION (fndecl
);
650 /* For cases where fundamental information cannot be found, e.g. the
651 coroutine traits are missing, we need to punt early. */
652 if (!coro_promise_type_found_p (fndecl
, f_loc
))
655 /* Since we think the function is a coroutine, that implies we parsed
656 a keyword that triggered this. Keywords check promise validity for
657 their context and thus the promise type should be known at this point. */
658 if (get_coroutine_handle_type (fndecl
) == NULL_TREE
659 || get_coroutine_promise_type (fndecl
) == NULL_TREE
)
662 if (current_function_returns_value
|| current_function_returns_null
)
664 /* TODO: record or extract positions of returns (and the first coro
665 keyword) so that we can add notes to the diagnostic about where
666 the bad keyword is and what made the function into a coro. */
667 error_at (f_loc
, "a %<return%> statement is not allowed in coroutine;"
668 " did you mean %<co_return%>?");
675 enum suspend_point_kind
{
676 CO_AWAIT_SUSPEND_POINT
= 0,
677 CO_YIELD_SUSPEND_POINT
,
678 INITIAL_SUSPEND_POINT
,
682 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
683 It is also used to build the initial and final suspend points.
685 'a', 'o' and 'e' are used as per the description in the section noted.
687 A, the original yield/await expr, is found at source location LOC.
689 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
690 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
693 build_co_await (location_t loc
, tree a
, suspend_point_kind suspend_kind
)
695 /* Try and overload of operator co_await, .... */
697 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a
)))
699 tree overload
= NULL_TREE
;
700 o
= build_new_op (loc
, CO_AWAIT_EXPR
, LOOKUP_NORMAL
, a
, NULL_TREE
,
701 NULL_TREE
, &overload
, tf_warning_or_error
);
702 /* If no viable functions are found, o is a. */
703 if (!o
|| o
== error_mark_node
)
707 o
= a
; /* This is most likely about to fail anyway. */
709 tree o_type
= TREE_TYPE (o
);
710 if (o_type
&& !VOID_TYPE_P (o_type
))
711 o_type
= complete_type_or_else (o_type
, o
);
714 return error_mark_node
;
716 if (TREE_CODE (o_type
) != RECORD_TYPE
)
718 error_at (loc
, "awaitable type %qT is not a structure",
720 return error_mark_node
;
723 /* Check for required awaitable members and their types. */
725 = lookup_awaitable_member (o_type
, coro_await_ready_identifier
, loc
);
726 if (!awrd_meth
|| awrd_meth
== error_mark_node
)
727 return error_mark_node
;
729 = lookup_awaitable_member (o_type
, coro_await_suspend_identifier
, loc
);
730 if (!awsp_meth
|| awsp_meth
== error_mark_node
)
731 return error_mark_node
;
733 /* The type of the co_await is the return type of the awaitable's
734 await_resume, so we need to look that up. */
736 = lookup_awaitable_member (o_type
, coro_await_resume_identifier
, loc
);
737 if (!awrs_meth
|| awrs_meth
== error_mark_node
)
738 return error_mark_node
;
740 /* To complete the lookups, we need an instance of 'e' which is built from
741 'o' according to [expr.await] 3.4. However, we don't want to materialize
742 'e' here (it might need to be placed in the coroutine frame) so we will
743 make a temp placeholder instead. If 'o' is a parameter or a local var,
744 then we do not need an additional var (parms and local vars are already
745 copied into the frame and will have lifetimes according to their original
747 tree e_proxy
= STRIP_NOPS (o
);
748 if (INDIRECT_REF_P (e_proxy
))
749 e_proxy
= TREE_OPERAND (e_proxy
, 0);
750 if (TREE_CODE (e_proxy
) == PARM_DECL
751 || (TREE_CODE (e_proxy
) == VAR_DECL
&& !DECL_ARTIFICIAL (e_proxy
)))
755 e_proxy
= build_lang_decl (VAR_DECL
, NULL_TREE
, o_type
);
756 DECL_ARTIFICIAL (e_proxy
) = true;
759 /* I suppose we could check that this is contextually convertible to bool. */
760 tree awrd_func
= NULL_TREE
;
762 = build_new_method_call (e_proxy
, awrd_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
763 &awrd_func
, tf_warning_or_error
);
765 if (!awrd_func
|| !awrd_call
|| awrd_call
== error_mark_node
)
766 return error_mark_node
;
768 /* The suspend method may return one of three types:
769 1. void (no special action needed).
770 2. bool (if true, we don't need to suspend).
771 3. a coroutine handle, we execute the handle.resume() call. */
772 tree awsp_func
= NULL_TREE
;
773 tree h_proxy
= get_coroutine_self_handle_proxy (current_function_decl
);
774 vec
<tree
, va_gc
> *args
= make_tree_vector_single (h_proxy
);
776 = build_new_method_call (e_proxy
, awsp_meth
, &args
, NULL_TREE
,
777 LOOKUP_NORMAL
, &awsp_func
, tf_warning_or_error
);
779 release_tree_vector (args
);
780 if (!awsp_func
|| !awsp_call
|| awsp_call
== error_mark_node
)
781 return error_mark_node
;
784 tree susp_return_type
= TREE_TYPE (TREE_TYPE (awsp_func
));
785 if (same_type_p (susp_return_type
, void_type_node
))
787 else if (same_type_p (susp_return_type
, boolean_type_node
))
789 else if (TREE_CODE (susp_return_type
) == RECORD_TYPE
790 && CLASS_TYPE_P (susp_return_type
))
792 tree tt
= CLASSTYPE_TI_TEMPLATE (susp_return_type
);
793 if (tt
== coro_handle_templ
)
799 error_at (loc
, "%<await_suspend%> must return %<void%>, %<bool%> or"
800 " a coroutine handle");
801 return error_mark_node
;
804 /* Finally, the type of e.await_resume() is the co_await's type. */
805 tree awrs_func
= NULL_TREE
;
807 = build_new_method_call (e_proxy
, awrs_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
808 &awrs_func
, tf_warning_or_error
);
810 if (!awrs_func
|| !awrs_call
|| awrs_call
== error_mark_node
)
811 return error_mark_node
;
813 /* We now have three call expressions, in terms of the promise, handle and
814 'e' proxies. Save them in the await expression for later expansion. */
816 tree awaiter_calls
= make_tree_vec (3);
817 TREE_VEC_ELT (awaiter_calls
, 0) = awrd_call
; /* await_ready(). */
818 TREE_VEC_ELT (awaiter_calls
, 1) = awsp_call
; /* await_suspend(). */
819 TREE_VEC_ELT (awaiter_calls
, 2) = awrs_call
; /* await_resume(). */
821 tree await_expr
= build5_loc (loc
, CO_AWAIT_EXPR
,
822 TREE_TYPE (TREE_TYPE (awrs_func
)),
823 a
, e_proxy
, o
, awaiter_calls
,
824 build_int_cst (integer_type_node
,
825 (int) suspend_kind
));
826 return convert_from_reference (await_expr
);
830 finish_co_await_expr (location_t kw
, tree expr
)
832 if (!expr
|| error_operand_p (expr
))
833 return error_mark_node
;
835 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
837 return error_mark_node
;
839 /* The current function has now become a coroutine, if it wasn't already. */
840 DECL_COROUTINE_P (current_function_decl
) = 1;
842 if (processing_template_decl
)
844 current_function_returns_value
= 1;
846 if (check_for_bare_parameter_packs (expr
))
847 return error_mark_node
;
849 /* If we don't know the promise type, we can't proceed. */
850 tree functype
= TREE_TYPE (current_function_decl
);
851 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
852 return build5_loc (kw
, CO_AWAIT_EXPR
, unknown_type_node
, expr
,
853 NULL_TREE
, NULL_TREE
, NULL_TREE
, integer_zero_node
);
856 /* We must be able to look up the "await_transform" method in the scope of
857 the promise type, and obtain its return type. */
858 if (!coro_promise_type_found_p (current_function_decl
, kw
))
859 return error_mark_node
;
862 The incoming cast expression might be transformed by a promise
863 'await_transform()'. */
865 = lookup_promise_method (current_function_decl
,
866 coro_await_transform_identifier
, kw
,
868 if (at_meth
== error_mark_node
)
869 return error_mark_node
;
874 /* try to build a = p.await_transform (e). */
875 tree at_fn
= NULL_TREE
;
876 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
877 a
= build_new_method_call (get_coroutine_promise_proxy (
878 current_function_decl
),
879 at_meth
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
880 &at_fn
, tf_warning_or_error
);
882 /* As I read the section.
883 We saw an await_transform method, so it's mandatory that we replace
884 expr with p.await_transform (expr), therefore if the method call fails
885 (presumably, we don't have suitable arguments) then this part of the
887 if (!at_fn
|| a
== error_mark_node
)
888 return error_mark_node
;
891 /* Now we want to build co_await a. */
892 tree op
= build_co_await (kw
, a
, CO_AWAIT_SUSPEND_POINT
);
893 if (op
!= error_mark_node
)
895 TREE_SIDE_EFFECTS (op
) = 1;
896 SET_EXPR_LOCATION (op
, kw
);
902 /* Take the EXPR given and attempt to build:
903 co_await p.yield_value (expr);
904 per [expr.yield] para 1. */
907 finish_co_yield_expr (location_t kw
, tree expr
)
909 if (!expr
|| error_operand_p (expr
))
910 return error_mark_node
;
912 /* Check the general requirements and simple syntax errors. */
913 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
915 return error_mark_node
;
917 /* The current function has now become a coroutine, if it wasn't already. */
918 DECL_COROUTINE_P (current_function_decl
) = 1;
920 if (processing_template_decl
)
922 current_function_returns_value
= 1;
924 if (check_for_bare_parameter_packs (expr
))
925 return error_mark_node
;
927 tree functype
= TREE_TYPE (current_function_decl
);
928 /* If we don't know the promise type, we can't proceed. */
929 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
930 return build2_loc (kw
, CO_YIELD_EXPR
, unknown_type_node
, expr
,
934 if (!coro_promise_type_found_p (current_function_decl
, kw
))
935 /* We must be able to look up the "yield_value" method in the scope of
936 the promise type, and obtain its return type. */
937 return error_mark_node
;
939 /* The incoming expr is "e" per [expr.yield] para 1, lookup and build a
940 call for p.yield_value(e). */
941 tree y_meth
= lookup_promise_method (current_function_decl
,
942 coro_yield_value_identifier
, kw
,
944 if (!y_meth
|| y_meth
== error_mark_node
)
945 return error_mark_node
;
947 tree yield_fn
= NULL_TREE
;
948 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
949 tree yield_call
= build_new_method_call (
950 get_coroutine_promise_proxy (current_function_decl
), y_meth
, &args
,
951 NULL_TREE
, LOOKUP_NORMAL
, &yield_fn
, tf_warning_or_error
);
953 if (!yield_fn
|| yield_call
== error_mark_node
)
954 return error_mark_node
;
956 /* So now we have the type of p.yield_value (e).
957 Now we want to build co_await p.yield_value (e).
958 Noting that for co_yield, there is no evaluation of any potential
959 promise transform_await(). */
961 tree op
= build_co_await (kw
, yield_call
, CO_YIELD_SUSPEND_POINT
);
962 if (op
!= error_mark_node
)
964 op
= build2_loc (kw
, CO_YIELD_EXPR
, TREE_TYPE (op
), expr
, op
);
965 TREE_SIDE_EFFECTS (op
) = 1;
971 /* Check that it's valid to have a co_return keyword here.
972 If it is, then check and build the p.return_{void(),value(expr)}.
973 These are built against the promise proxy, but saved for expand time. */
976 finish_co_return_stmt (location_t kw
, tree expr
)
978 if (expr
== error_mark_node
)
979 return error_mark_node
;
981 if (!coro_common_keyword_context_valid_p (current_function_decl
, kw
,
983 return error_mark_node
;
985 /* The current function has now become a coroutine, if it wasn't
987 DECL_COROUTINE_P (current_function_decl
) = 1;
989 if (processing_template_decl
)
991 current_function_returns_value
= 1;
993 if (check_for_bare_parameter_packs (expr
))
994 return error_mark_node
;
996 tree functype
= TREE_TYPE (current_function_decl
);
997 /* If we don't know the promise type, we can't proceed, return the
998 expression as it is. */
999 if (dependent_type_p (functype
) || type_dependent_expression_p (expr
))
1002 = build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, NULL_TREE
);
1003 expr
= maybe_cleanup_point_expr_void (expr
);
1004 expr
= add_stmt (expr
);
1009 if (!coro_promise_type_found_p (current_function_decl
, kw
))
1010 return error_mark_node
;
1012 if (error_operand_p (expr
))
1013 return error_mark_node
;
1015 /* Suppress -Wreturn-type for co_return, we need to check indirectly
1016 whether the promise type has a suitable return_void/return_value. */
1017 TREE_NO_WARNING (current_function_decl
) = true;
1019 if (!processing_template_decl
&& warn_sequence_point
)
1020 verify_sequence_points (expr
);
1022 /* If the promise object doesn't have the correct return call then
1023 there's a mis-match between the co_return <expr> and this. */
1024 tree co_ret_call
= NULL_TREE
;
1025 if (expr
== NULL_TREE
|| VOID_TYPE_P (TREE_TYPE (expr
)))
1028 = lookup_promise_method (current_function_decl
,
1029 coro_return_void_identifier
, kw
,
1031 if (!crv_meth
|| crv_meth
== error_mark_node
)
1032 return error_mark_node
;
1034 co_ret_call
= build_new_method_call (
1035 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, NULL
,
1036 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1041 = lookup_promise_method (current_function_decl
,
1042 coro_return_value_identifier
, kw
,
1044 if (!crv_meth
|| crv_meth
== error_mark_node
)
1045 return error_mark_node
;
1047 vec
<tree
, va_gc
> *args
= make_tree_vector_single (expr
);
1048 co_ret_call
= build_new_method_call (
1049 get_coroutine_promise_proxy (current_function_decl
), crv_meth
, &args
,
1050 NULL_TREE
, LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
1053 /* Makes no sense for a co-routine really. */
1054 if (TREE_THIS_VOLATILE (current_function_decl
))
1056 "function declared %<noreturn%> has a"
1057 " %<co_return%> statement");
1059 if (!co_ret_call
|| co_ret_call
== error_mark_node
)
1060 return error_mark_node
;
1062 expr
= build2_loc (kw
, CO_RETURN_EXPR
, void_type_node
, expr
, co_ret_call
);
1063 expr
= maybe_cleanup_point_expr_void (expr
);
1064 expr
= add_stmt (expr
);
1068 /* We need to validate the arguments to __builtin_coro_promise, since the
1069 second two must be constant, and the builtins machinery doesn't seem to
1070 deal with that properly. */
1073 coro_validate_builtin_call (tree call
, tsubst_flags_t
)
1075 tree fn
= TREE_OPERAND (CALL_EXPR_FN (call
), 0);
1077 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn
) == BUILT_IN_NORMAL
);
1078 switch (DECL_FUNCTION_CODE (fn
))
1083 case BUILT_IN_CORO_PROMISE
:
1085 /* Argument 0 is already checked by the normal built-in machinery
1086 Argument 1 must be a constant of size type. It probably makes
1087 little sense if it's not a power of 2, but that isn't specified
1089 tree arg
= CALL_EXPR_ARG (call
, 1);
1090 location_t loc
= EXPR_LOCATION (arg
);
1092 /* We expect alignof expressions in templates. */
1093 if (TREE_CODE (arg
) == NON_DEPENDENT_EXPR
1094 && TREE_CODE (TREE_OPERAND (arg
, 0)) == ALIGNOF_EXPR
)
1096 else if (!TREE_CONSTANT (arg
))
1098 error_at (loc
, "the align argument to %<__builtin_coro_promise%>"
1099 " must be a constant");
1100 return error_mark_node
;
1102 /* Argument 2 is the direction - to / from handle address to promise
1104 arg
= CALL_EXPR_ARG (call
, 2);
1105 loc
= EXPR_LOCATION (arg
);
1106 if (!TREE_CONSTANT (arg
))
1108 error_at (loc
, "the direction argument to"
1109 " %<__builtin_coro_promise%> must be a constant");
1110 return error_mark_node
;
1118 /* ================= Morph and Expand. =================
1120 The entry point here is morph_fn_to_coro () which is called from
1121 finish_function () when we have completed any template expansion.
1123 This is preceded by helper functions that implement the phases below.
1125 The process proceeds in four phases.
1128 The user's function body is wrapped in the initial and final suspend
1129 points and we begin building the coroutine frame.
1130 We build empty decls for the actor and destroyer functions at this
1132 When exceptions are enabled, the user's function body will also be
1133 wrapped in a try-catch block with the catch invoking the promise
1134 class 'unhandled_exception' method.
1137 The user's function body is analyzed to determine the suspend points,
1138 if any, and to capture local variables that might persist across such
1139 suspensions. In most cases, it is not necessary to capture compiler
1140 temporaries, since the tree-lowering nests the suspensions correctly.
1141 However, in the case of a captured reference, there is a lifetime
1142 extension to the end of the full expression - which can mean across a
1143 suspend point in which case it must be promoted to a frame variable.
1145 At the conclusion of analysis, we have a conservative frame layout and
1146 maps of the local variables to their frame entry points.
1148 C Build the ramp function.
1149 Carry out the allocation for the coroutine frame (NOTE; the actual size
1150 computation is deferred until late in the middle end to allow for future
1151 optimizations that will be allowed to elide unused frame entries).
1152 We build the return object.
1154 D Build and expand the actor and destroyer function bodies.
1155 The destroyer is a trivial shim that sets a bit to indicate that the
1156 destroy dispatcher should be used and then calls into the actor.
1158 The actor function is the implementation of the user's state machine.
1159 The current suspend point is noted in an index.
1160 Each suspend point is encoded as a pair of internal functions, one in
1161 the relevant dispatcher, and one representing the suspend point.
1163 During this process, the user's local variables and the proxies for the
1164 self-handle and the promise class instance are re-written to their
1165 coroutine frame equivalents.
1167 The complete bodies for the ramp, actor and destroy function are passed
1168 back to finish_function for folding and gimplification. */
1170 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1173 coro_build_expr_stmt (tree expr
, location_t loc
)
1175 return maybe_cleanup_point_expr_void (build_stmt (loc
, EXPR_STMT
, expr
));
1179 coro_build_cvt_void_expr_stmt (tree expr
, location_t loc
)
1181 tree t
= build1 (CONVERT_EXPR
, void_type_node
, expr
);
1182 return coro_build_expr_stmt (t
, loc
);
1185 /* Helpers for label creation:
1186 1. Create a named label in the specified context. */
1189 create_anon_label_with_ctx (location_t loc
, tree ctx
)
1191 tree lab
= build_decl (loc
, LABEL_DECL
, NULL_TREE
, void_type_node
);
1193 DECL_CONTEXT (lab
) = ctx
;
1194 DECL_ARTIFICIAL (lab
) = true;
1195 DECL_IGNORED_P (lab
) = true;
1196 TREE_USED (lab
) = true;
1200 /* 2. Create a named label in the specified context. */
1203 create_named_label_with_ctx (location_t loc
, const char *name
, tree ctx
)
1205 tree lab_id
= get_identifier (name
);
1206 tree lab
= define_label (loc
, lab_id
);
1207 DECL_CONTEXT (lab
) = ctx
;
1208 DECL_ARTIFICIAL (lab
) = true;
1209 TREE_USED (lab
) = true;
1213 struct proxy_replace
1219 replace_proxy (tree
*here
, int *do_subtree
, void *d
)
1221 proxy_replace
*data
= (proxy_replace
*) d
;
1223 if (*here
== data
->from
)
1233 /* Support for expansion of co_return statements. */
1235 struct coro_ret_data
1242 /* If this is a coreturn statement (or one wrapped in a cleanup) then
1243 return the list of statements to replace it. */
1246 coro_maybe_expand_co_return (tree co_ret_expr
, coro_ret_data
*data
)
1248 /* Look inside <(void) (expr)> cleanup */
1249 if (TREE_CODE (co_ret_expr
) == CLEANUP_POINT_EXPR
)
1250 co_ret_expr
= TREE_OPERAND (co_ret_expr
, 0);
1252 if (TREE_CODE (co_ret_expr
) != CO_RETURN_EXPR
)
1255 location_t loc
= EXPR_LOCATION (co_ret_expr
);
1256 tree expr
= TREE_OPERAND (co_ret_expr
, 0);
1257 tree call
= TREE_OPERAND (co_ret_expr
, 1);
1258 tree stmt_list
= NULL
;
1259 if (expr
&& VOID_TYPE_P (TREE_TYPE (expr
)))
1261 /* [stmt.return.coroutine], 2.2
1262 If expr is present and void, it is placed immediately before
1263 the call for return_void; */
1264 expr
= maybe_cleanup_point_expr_void (expr
);
1265 append_to_statement_list (expr
, &stmt_list
);
1268 /* Now replace the promise proxy with its real value. */
1269 proxy_replace p_data
;
1270 p_data
.from
= data
->promise_proxy
;
1271 p_data
.to
= data
->real_promise
;
1272 cp_walk_tree (&call
, replace_proxy
, &p_data
, NULL
);
1274 /* The types of p.return_void and p.return_value are not explicitly stated
1275 at least in n4835, it is expected that they will return void. */
1276 call
= maybe_cleanup_point_expr_void (call
);
1277 append_to_statement_list (call
, &stmt_list
);
1278 tree r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->fs_label
);
1279 append_to_statement_list (r
, &stmt_list
);
1283 /* Callback that rewrites co_return as per [stmt.return.coroutine]
1285 { p.return_void (); goto final_suspend; }
1286 - for co_return [void expr];
1287 { expr; p.return_void(); goto final_suspend;}
1288 - for co_return [non void expr];
1289 { p.return_value(expr); goto final_suspend; } */
1292 co_return_expander (tree
*stmt
, int *do_subtree
, void *d
)
1294 coro_ret_data
*data
= (coro_ret_data
*) d
;
1296 /* To avoid nesting statement lists, walk them and insert as needed. */
1297 if (TREE_CODE (*stmt
) == STATEMENT_LIST
)
1299 tree_stmt_iterator i
;
1300 for (i
= tsi_start (*stmt
); !tsi_end_p (i
); tsi_next (&i
))
1302 tree
*new_stmt
= tsi_stmt_ptr (i
);
1303 tree replace
= coro_maybe_expand_co_return (*new_stmt
, data
);
1304 /* If we got something, it will be list and we want to splice
1306 if (replace
!= NULL_TREE
)
1308 /* Splice it in ... */
1309 tsi_link_before (&i
, replace
, TSI_SAME_STMT
);
1310 /* ... and delete what we expanded. */
1312 /* Maybe, even likely, we replaced the last in the list. */
1316 else /* Continue the walk. */
1317 cp_walk_tree (new_stmt
, co_return_expander
, d
, NULL
);
1319 *do_subtree
= 0; /* Done subtrees. */
1323 /* We might have a single co_return statement, in which case, we do
1324 have to replace it with a list. */
1325 tree replace
= coro_maybe_expand_co_return (*stmt
, data
);
1326 if (replace
!= NULL_TREE
)
1329 *do_subtree
= 0; /* Done here. */
1335 /* Walk the original function body, rewriting co_returns. */
1338 expand_co_returns (tree
*fnbody
, tree promise_proxy
, tree promise
,
1341 coro_ret_data data
= {promise_proxy
, promise
, fs_label
};
1342 cp_walk_tree (fnbody
, co_return_expander
, &data
, NULL
);
1346 /* Support for expansion of co_await statements. */
1350 tree actor_fn
; /* Decl for context. */
1351 tree coro_fp
; /* Frame pointer var. */
1352 tree resume_idx
; /* This is the index var in the frame. */
1353 tree i_a_r_c
; /* initial suspend await_resume() was called if true. */
1354 tree self_h
; /* This is a handle to the current coro (frame var). */
1355 tree cleanup
; /* This is where to go once we complete local destroy. */
1356 tree cororet
; /* This is where to go if we suspend. */
1357 tree corocont
; /* This is where to go if we continue. */
1358 tree conthand
; /* This is the handle for a continuation. */
1359 unsigned index
; /* This is our current resume index. */
1363 co_await_find_in_subtree (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
1365 tree
**p
= (tree
**) d
;
1366 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
)
1374 /* When we come here:
1375 the first operand is the [currently unused] handle for suspend.
1376 the second operand is the var to be copy-initialized
1377 the third operand is 'o' (the initializer for the second)
1378 as defined in [await.expr] (3.3)
1379 the fourth operand is the mode as per the comment on build_co_await ().
1382 the IFN_CO_YIELD carries the labels of the resume and destroy
1383 branch targets for this await. */
1386 co_await_expander (tree
*stmt
, int * /*do_subtree*/, void *d
)
1388 if (STATEMENT_CLASS_P (*stmt
) || !EXPR_P (*stmt
))
1391 coro_aw_data
*data
= (coro_aw_data
*) d
;
1392 enum tree_code stmt_code
= TREE_CODE (*stmt
);
1393 tree stripped_stmt
= *stmt
;
1394 tree
*buried_stmt
= NULL
;
1395 tree saved_co_await
= NULL_TREE
;
1396 enum tree_code sub_code
= NOP_EXPR
;
1398 if (stmt_code
== MODIFY_EXPR
|| stmt_code
== INIT_EXPR
)
1400 sub_code
= TREE_CODE (TREE_OPERAND (stripped_stmt
, 1));
1401 if (sub_code
== CO_AWAIT_EXPR
)
1402 saved_co_await
= TREE_OPERAND (stripped_stmt
, 1); /* Get the RHS. */
1404 = cp_walk_tree (&TREE_OPERAND (stripped_stmt
, 1),
1405 co_await_find_in_subtree
, &buried_stmt
, NULL
))
1408 else if (stmt_code
== CALL_EXPR
)
1410 if (tree r
= cp_walk_tree (&stripped_stmt
, co_await_find_in_subtree
,
1411 &buried_stmt
, NULL
))
1414 else if ((stmt_code
== CONVERT_EXPR
|| stmt_code
== NOP_EXPR
)
1415 && TREE_CODE (TREE_OPERAND (stripped_stmt
, 0)) == CO_AWAIT_EXPR
)
1416 saved_co_await
= TREE_OPERAND (stripped_stmt
, 0);
1417 else if (stmt_code
== CO_AWAIT_EXPR
)
1418 saved_co_await
= stripped_stmt
;
1420 if (!saved_co_await
)
1423 /* We want to splice in the await_resume() value in some cases. */
1424 tree saved_statement
= *stmt
;
1426 tree actor
= data
->actor_fn
;
1427 location_t loc
= EXPR_LOCATION (*stmt
);
1428 tree var
= TREE_OPERAND (saved_co_await
, 1); /* frame slot. */
1429 tree expr
= TREE_OPERAND (saved_co_await
, 2); /* initializer. */
1430 tree awaiter_calls
= TREE_OPERAND (saved_co_await
, 3);
1432 tree source
= TREE_OPERAND (saved_co_await
, 4);
1434 (source
&& TREE_INT_CST_LOW (source
) == (int) INITIAL_SUSPEND_POINT
);
1435 bool is_final
= (source
1436 && TREE_INT_CST_LOW (source
) == (int) FINAL_SUSPEND_POINT
);
1437 bool needs_dtor
= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var
));
1438 int resume_point
= data
->index
;
1439 size_t bufsize
= sizeof ("destroy.") + 10;
1440 char *buf
= (char *) alloca (bufsize
);
1441 snprintf (buf
, bufsize
, "destroy.%d", resume_point
);
1442 tree destroy_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1443 snprintf (buf
, bufsize
, "resume.%d", resume_point
);
1444 tree resume_label
= create_named_label_with_ctx (loc
, buf
, actor
);
1445 tree empty_list
= build_empty_stmt (loc
);
1447 tree dtor
= NULL_TREE
;
1448 tree await_type
= TREE_TYPE (var
);
1450 dtor
= build_special_member_call (var
, complete_dtor_identifier
, NULL
,
1451 await_type
, LOOKUP_NORMAL
,
1452 tf_warning_or_error
);
1454 tree stmt_list
= NULL
;
1455 tree t_expr
= STRIP_NOPS (expr
);
1461 /* Initialize the var from the provided 'o' expression. */
1462 r
= build2 (INIT_EXPR
, await_type
, var
, expr
);
1463 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1464 append_to_statement_list (r
, &stmt_list
);
1467 /* Use the await_ready() call to test if we need to suspend. */
1468 tree ready_cond
= TREE_VEC_ELT (awaiter_calls
, 0); /* await_ready(). */
1469 ready_cond
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, ready_cond
);
1471 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, ready_cond
);
1473 tree body_list
= NULL
;
1474 tree susp_idx
= build_int_cst (short_unsigned_type_node
, data
->index
);
1475 r
= build2_loc (loc
, MODIFY_EXPR
, short_unsigned_type_node
, data
->resume_idx
,
1477 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1478 append_to_statement_list (r
, &body_list
);
1480 /* Find out what we have to do with the awaiter's suspend method.
1482 (5.1) If the result of await-ready is false, the coroutine is considered
1484 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1485 await-suspend.resume() is evaluated.
1486 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1487 and the coroutine is resumed if the result is false.
1488 (5.1.3) Otherwise, await-suspend is evaluated. */
1490 tree suspend
= TREE_VEC_ELT (awaiter_calls
, 1); /* await_suspend(). */
1491 tree susp_type
= TREE_TYPE (suspend
);
1493 bool is_cont
= false;
1494 /* NOTE: final suspend can't resume; the "resume" label in that case
1495 corresponds to implicit destruction. */
1496 if (VOID_TYPE_P (susp_type
))
1498 /* We just call await_suspend() and hit the yield. */
1499 suspend
= coro_build_cvt_void_expr_stmt (suspend
, loc
);
1500 append_to_statement_list (suspend
, &body_list
);
1502 else if (TREE_CODE (susp_type
) == BOOLEAN_TYPE
)
1504 /* Boolean return, continue if the call returns false. */
1505 suspend
= build1_loc (loc
, TRUTH_NOT_EXPR
, boolean_type_node
, suspend
);
1507 = build1_loc (loc
, CLEANUP_POINT_EXPR
, boolean_type_node
, suspend
);
1508 tree go_on
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1509 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, suspend
, go_on
,
1511 append_to_statement_list (r
, &body_list
);
1515 r
= build1_loc (loc
, CONVERT_EXPR
, void_coro_handle_type
, suspend
);
1516 r
= build2_loc (loc
, INIT_EXPR
, void_coro_handle_type
, data
->conthand
, r
);
1517 r
= build1 (CONVERT_EXPR
, void_type_node
, r
);
1518 append_to_statement_list (r
, &body_list
);
1522 tree d_l
= build_address (destroy_label
);
1523 tree r_l
= build_address (resume_label
);
1524 tree susp
= build_address (data
->cororet
);
1525 tree cont
= build_address (data
->corocont
);
1526 tree final_susp
= build_int_cst (integer_type_node
, is_final
? 1 : 0);
1528 susp_idx
= build_int_cst (integer_type_node
, data
->index
);
1530 tree sw
= begin_switch_stmt ();
1531 tree cond
= build_decl (loc
, VAR_DECL
, NULL_TREE
, integer_type_node
);
1532 DECL_ARTIFICIAL (cond
) = 1;
1533 DECL_IGNORED_P (cond
) = 1;
1534 layout_decl (cond
, 0);
1536 r
= build_call_expr_internal_loc (loc
, IFN_CO_YIELD
, integer_type_node
, 5,
1537 susp_idx
, final_susp
, r_l
, d_l
,
1539 r
= build2 (INIT_EXPR
, integer_type_node
, cond
, r
);
1540 finish_switch_cond (r
, sw
);
1541 r
= build_case_label (build_int_cst (integer_type_node
, 0), NULL_TREE
,
1542 create_anon_label_with_ctx (loc
, actor
));
1543 add_stmt (r
); /* case 0: */
1544 /* Implement the suspend, a scope exit without clean ups. */
1545 r
= build_call_expr_internal_loc (loc
, IFN_CO_SUSPN
, void_type_node
, 1,
1546 is_cont
? cont
: susp
);
1547 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1548 add_stmt (r
); /* goto ret; */
1549 r
= build_case_label (build_int_cst (integer_type_node
, 1), NULL_TREE
,
1550 create_anon_label_with_ctx (loc
, actor
));
1551 add_stmt (r
); /* case 1: */
1552 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, resume_label
);
1553 add_stmt (r
); /* goto resume; */
1554 r
= build_case_label (NULL_TREE
, NULL_TREE
,
1555 create_anon_label_with_ctx (loc
, actor
));
1556 add_stmt (r
); /* default:; */
1557 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, destroy_label
);
1558 add_stmt (r
); /* goto destroy; */
1560 /* part of finish switch. */
1561 SWITCH_STMT_BODY (sw
) = pop_stmt_list (SWITCH_STMT_BODY (sw
));
1563 tree scope
= SWITCH_STMT_SCOPE (sw
);
1564 SWITCH_STMT_SCOPE (sw
) = NULL
;
1565 r
= do_poplevel (scope
);
1566 append_to_statement_list (r
, &body_list
);
1568 destroy_label
= build_stmt (loc
, LABEL_EXPR
, destroy_label
);
1569 append_to_statement_list (destroy_label
, &body_list
);
1571 append_to_statement_list (dtor
, &body_list
);
1572 r
= build1_loc (loc
, GOTO_EXPR
, void_type_node
, data
->cleanup
);
1573 append_to_statement_list (r
, &body_list
);
1575 r
= build3_loc (loc
, COND_EXPR
, void_type_node
, ready_cond
, body_list
,
1578 append_to_statement_list (r
, &stmt_list
);
1581 resume_label
= build_stmt (loc
, LABEL_EXPR
, resume_label
);
1582 append_to_statement_list (resume_label
, &stmt_list
);
1586 /* Note that we are about to execute the await_resume() for the initial
1587 await expression. */
1588 r
= build2_loc (loc
, MODIFY_EXPR
, boolean_type_node
, data
->i_a_r_c
,
1590 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
1591 append_to_statement_list (r
, &stmt_list
);
1594 /* This will produce the value (if one is provided) from the co_await
1596 tree resume_call
= TREE_VEC_ELT (awaiter_calls
, 2); /* await_resume(). */
1597 if (REFERENCE_REF_P (resume_call
))
1598 /* Sink to await_resume call_expr. */
1599 resume_call
= TREE_OPERAND (resume_call
, 0);
1602 default: /* not likely to work .. but... */
1603 append_to_statement_list (resume_call
, &stmt_list
);
1607 TREE_OPERAND (stripped_stmt
, 0) = resume_call
;
1608 append_to_statement_list (saved_statement
, &stmt_list
);
1613 /* Replace the use of co_await by the resume expr. */
1614 if (sub_code
== CO_AWAIT_EXPR
)
1616 /* We're updating the interior of a possibly <(void) expr>cleanup. */
1617 TREE_OPERAND (stripped_stmt
, 1) = resume_call
;
1618 append_to_statement_list (saved_statement
, &stmt_list
);
1620 else if (buried_stmt
!= NULL
)
1622 *buried_stmt
= resume_call
;
1623 append_to_statement_list (saved_statement
, &stmt_list
);
1627 error_at (loc
, "failed to substitute the resume method in %qE",
1629 append_to_statement_list (saved_statement
, &stmt_list
);
1634 append_to_statement_list (dtor
, &stmt_list
);
1640 /* Suspend point hash_map. */
1642 struct suspend_point_info
1644 /* coro frame field type. */
1645 tree awaitable_type
;
1646 /* coro frame field name. */
1647 tree await_field_id
;
1650 static hash_map
<tree
, suspend_point_info
> *suspend_points
;
1652 struct await_xform_data
1654 tree actor_fn
; /* Decl for context. */
1662 /* When we built the await expressions, we didn't know the coro frame
1663 layout, therefore no idea where to find the promise or where to put
1664 the awaitables. Now we know these things, fill them in. */
1667 transform_await_expr (tree await_expr
, await_xform_data
*xform
)
1669 suspend_point_info
*si
= suspend_points
->get (await_expr
);
1670 location_t loc
= EXPR_LOCATION (await_expr
);
1673 error_at (loc
, "no suspend point info for %qD", await_expr
);
1674 return error_mark_node
;
1677 /* So, on entry, we have:
1678 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1679 We no longer need a [it had diagnostic value, maybe?]
1680 We need to replace the promise proxy in all elements
1681 We need to replace the e_proxy in the awr_call. */
1683 tree coro_frame_type
= TREE_TYPE (xform
->actor_frame
);
1685 /* If we have a frame var for the awaitable, get a reference to it. */
1687 if (si
->await_field_id
)
1690 = lookup_member (coro_frame_type
, si
->await_field_id
,
1691 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
1692 tree as
= build_class_member_access_expr (xform
->actor_frame
, as_m
,
1694 tf_warning_or_error
);
1696 /* Replace references to the instance proxy with the frame entry now
1698 data
.from
= TREE_OPERAND (await_expr
, 1);
1700 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1702 /* .. and replace. */
1703 TREE_OPERAND (await_expr
, 1) = as
;
1706 /* Now do the self_handle. */
1707 data
.from
= xform
->self_h_proxy
;
1708 data
.to
= xform
->real_self_h
;
1709 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1711 /* Now do the promise. */
1712 data
.from
= xform
->promise_proxy
;
1713 data
.to
= xform
->real_promise
;
1714 cp_walk_tree (&await_expr
, replace_proxy
, &data
, NULL
);
1719 /* A wrapper for the transform_await_expr function so that it can be a
1720 callback from cp_walk_tree. */
1723 transform_await_wrapper (tree
*stmt
, int *do_subtree
, void *d
)
1725 /* Set actor function as new DECL_CONTEXT of label_decl. */
1726 struct await_xform_data
*xform
= (struct await_xform_data
*) d
;
1727 if (TREE_CODE (*stmt
) == LABEL_DECL
1728 && DECL_CONTEXT (*stmt
) != xform
->actor_fn
)
1729 DECL_CONTEXT (*stmt
) = xform
->actor_fn
;
1731 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
&& TREE_CODE (*stmt
) != CO_YIELD_EXPR
)
1734 tree await_expr
= *stmt
;
1735 *stmt
= transform_await_expr (await_expr
, xform
);
1736 if (*stmt
== error_mark_node
)
1741 /* This caches information that we determine about function params,
1742 their uses and copies in the coroutine frame. */
1746 tree field_id
; /* The name of the copy in the coroutine frame. */
1747 vec
<tree
*> *body_uses
; /* Worklist of uses, void if there are none. */
1748 tree frame_type
; /* The type used to represent this parm in the frame. */
1749 tree orig_type
; /* The original type of the parm (not as passed). */
1750 bool by_ref
; /* Was passed by reference. */
1751 bool rv_ref
; /* Was an rvalue reference. */
1752 bool pt_ref
; /* Was a pointer to object. */
1753 bool trivial_dtor
; /* The frame type has a trivial DTOR. */
1756 struct local_var_info
1761 bool is_lambda_capture
;
1765 /* For figuring out what local variable usage we have. */
1766 struct local_vars_transform
1770 tree coro_frame_type
;
1772 hash_map
<tree
, local_var_info
> *local_var_uses
;
1776 transform_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
1778 local_vars_transform
*lvd
= (local_vars_transform
*) d
;
1780 /* For each var in this bind expr (that has a frame id, which means it was
1781 accessed), build a frame reference for each and then walk the bind expr
1782 statements, substituting the frame ref for the original var. */
1784 if (TREE_CODE (*stmt
) == BIND_EXPR
)
1787 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
1788 lvar
= DECL_CHAIN (lvar
))
1791 local_var_info
&local_var
1792 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
1793 gcc_checking_assert (existed
);
1795 /* Re-write the variable's context to be in the actor func. */
1796 DECL_CONTEXT (lvar
) = lvd
->context
;
1798 /* we need to walk some of the decl trees, which might contain
1799 references to vars replaced at a higher level. */
1800 cp_walk_tree (&DECL_INITIAL (lvar
), transform_local_var_uses
, d
,
1802 cp_walk_tree (&DECL_SIZE (lvar
), transform_local_var_uses
, d
, NULL
);
1803 cp_walk_tree (&DECL_SIZE_UNIT (lvar
), transform_local_var_uses
, d
,
1806 /* For capture proxies, this could include the decl value expr. */
1807 if (local_var
.is_lambda_capture
)
1809 tree ve
= DECL_VALUE_EXPR (lvar
);
1810 cp_walk_tree (&ve
, transform_local_var_uses
, d
, NULL
);
1811 continue; /* No frame entry for this. */
1814 /* TODO: implement selective generation of fields when vars are
1816 if (local_var
.field_id
== NULL_TREE
)
1817 continue; /* Wasn't used. */
1820 = lookup_member (lvd
->coro_frame_type
, local_var
.field_id
,
1821 /*protect=*/1, /*want_type=*/0,
1822 tf_warning_or_error
);
1823 tree fld_idx
= build3_loc (lvd
->loc
, COMPONENT_REF
, TREE_TYPE (lvar
),
1824 lvd
->actor_frame
, fld_ref
, NULL_TREE
);
1825 local_var
.field_idx
= fld_idx
;
1827 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), transform_local_var_uses
, d
, NULL
);
1829 /* Now we have processed and removed references to the original vars,
1830 we can drop those from the bind - leaving capture proxies alone. */
1831 for (tree
*pvar
= &BIND_EXPR_VARS (*stmt
); *pvar
!= NULL
;)
1834 local_var_info
&local_var
1835 = lvd
->local_var_uses
->get_or_insert (*pvar
, &existed
);
1836 gcc_checking_assert (existed
);
1838 /* Leave lambda closure captures alone, we replace the *this
1839 pointer with the frame version and let the normal process
1840 deal with the rest. */
1841 if (local_var
.is_lambda_capture
)
1843 pvar
= &DECL_CHAIN (*pvar
);
1847 /* It's not used, but we can let the optimizer deal with that. */
1848 if (local_var
.field_id
== NULL_TREE
)
1850 pvar
= &DECL_CHAIN (*pvar
);
1854 /* Discard this one, we replaced it. */
1855 *pvar
= DECL_CHAIN (*pvar
);
1858 *do_subtree
= 0; /* We've done the body already. */
1862 tree var_decl
= *stmt
;
1863 /* Look inside cleanups, we don't want to wrap a statement list in a
1865 bool needs_cleanup
= true;
1866 if (TREE_CODE (var_decl
) == CLEANUP_POINT_EXPR
)
1867 var_decl
= TREE_OPERAND (var_decl
, 0);
1869 needs_cleanup
= false;
1871 /* Look inside the decl_expr for the actual var. */
1872 bool decl_expr_p
= TREE_CODE (var_decl
) == DECL_EXPR
;
1873 if (decl_expr_p
&& TREE_CODE (DECL_EXPR_DECL (var_decl
)) == VAR_DECL
)
1874 var_decl
= DECL_EXPR_DECL (var_decl
);
1875 else if (TREE_CODE (var_decl
) != VAR_DECL
)
1878 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1879 for the promise and coroutine handle(s), to global vars or to compiler
1880 temporaries. Skip past these, we will handle them later. */
1881 local_var_info
*local_var_i
= lvd
->local_var_uses
->get (var_decl
);
1882 if (local_var_i
== NULL
)
1885 if (local_var_i
->is_lambda_capture
)
1888 /* This is our revised 'local' i.e. a frame slot. */
1889 tree revised
= local_var_i
->field_idx
;
1890 gcc_checking_assert (DECL_CONTEXT (var_decl
) == lvd
->context
);
1892 if (decl_expr_p
&& DECL_INITIAL (var_decl
))
1894 location_t loc
= DECL_SOURCE_LOCATION (var_decl
);
1896 = cp_build_modify_expr (loc
, revised
, INIT_EXPR
,
1897 DECL_INITIAL (var_decl
), tf_warning_or_error
);
1899 r
= coro_build_cvt_void_expr_stmt (r
, EXPR_LOCATION (*stmt
));
1906 *do_subtree
= 0; /* We've accounted for the nested use. */
1910 /* The actor transform. */
1913 build_actor_fn (location_t loc
, tree coro_frame_type
, tree actor
, tree fnbody
,
1914 tree orig
, hash_map
<tree
, param_info
> *param_uses
,
1915 hash_map
<tree
, local_var_info
> *local_var_uses
,
1916 vec
<tree
, va_gc
> *param_dtor_list
, tree initial_await
,
1917 tree final_await
, unsigned body_count
, tree frame_size
)
1919 verify_stmt_tree (fnbody
);
1920 /* Some things we inherit from the original function. */
1921 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
1922 tree handle_type
= get_coroutine_handle_type (orig
);
1923 tree self_h_proxy
= get_coroutine_self_handle_proxy (orig
);
1924 tree promise_type
= get_coroutine_promise_type (orig
);
1925 tree promise_proxy
= get_coroutine_promise_proxy (orig
);
1926 tree act_des_fn_type
1927 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
1928 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
1930 /* One param, the coro frame pointer. */
1931 tree actor_fp
= DECL_ARGUMENTS (actor
);
1933 /* A void return. */
1934 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
1935 DECL_ARTIFICIAL (resdecl
) = 1;
1936 DECL_IGNORED_P (resdecl
) = 1;
1937 DECL_RESULT (actor
) = resdecl
;
1938 DECL_COROUTINE_P (actor
) = 1;
1940 /* We have a definition here. */
1941 TREE_STATIC (actor
) = 1;
1943 tree actor_outer
= push_stmt_list ();
1944 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
1945 tree stmt
= begin_compound_stmt (BCS_FN_BODY
);
1947 /* ??? Can we dispense with the enclosing bind if the function body does
1948 not start with a bind_expr? (i.e. there's no contained scopes). */
1949 tree actor_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
1950 tree top_block
= make_node (BLOCK
);
1951 BIND_EXPR_BLOCK (actor_bind
) = top_block
;
1953 tree continuation
= build_lang_decl (VAR_DECL
,
1954 get_identifier ("actor.continue"),
1955 void_coro_handle_type
);
1956 DECL_ARTIFICIAL (continuation
) = 1;
1957 DECL_IGNORED_P (continuation
) = 1;
1958 DECL_CONTEXT (continuation
) = actor
;
1959 BIND_EXPR_VARS (actor_bind
) = continuation
;
1961 /* Update the block associated with the outer scope of the orig fn. */
1962 tree first
= expr_first (fnbody
);
1963 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
1965 /* We will discard this, since it's connected to the original scope
1967 tree block
= BIND_EXPR_BLOCK (first
);
1968 if (block
) /* For this to be missing is probably a bug. */
1970 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
1971 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
1972 BLOCK_SUPERCONTEXT (block
) = top_block
;
1973 BLOCK_SUBBLOCKS (top_block
) = block
;
1977 add_stmt (actor_bind
);
1978 tree actor_body
= push_stmt_list ();
1980 /* The entry point for the actor code from the ramp. */
1981 tree actor_begin_label
1982 = create_named_label_with_ctx (loc
, "actor.begin", actor
);
1983 tree actor_frame
= build1_loc (loc
, INDIRECT_REF
, coro_frame_type
, actor_fp
);
1985 /* Declare the continuation handle. */
1986 add_decl_expr (continuation
);
1988 /* Re-write param references in the body, no code should be generated
1990 if (DECL_ARGUMENTS (orig
))
1993 for (arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
; arg
= DECL_CHAIN (arg
))
1996 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
1997 if (!parm
.body_uses
)
1998 continue; /* Wasn't used in the orignal function body. */
2000 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
2001 /*protect=*/1, /*want_type=*/0,
2002 tf_warning_or_error
);
2003 tree fld_idx
= build3_loc (loc
, COMPONENT_REF
, parm
.frame_type
,
2004 actor_frame
, fld_ref
, NULL_TREE
);
2006 /* We keep these in the frame as a regular pointer, so convert that
2007 back to the type expected. */
2009 fld_idx
= build1_loc (loc
, CONVERT_EXPR
, TREE_TYPE (arg
), fld_idx
);
2011 /* We expect an rvalue ref. here. */
2013 fld_idx
= convert_to_reference (DECL_ARG_TYPE (arg
), fld_idx
,
2014 CONV_STATIC
, LOOKUP_NORMAL
,
2015 NULL_TREE
, tf_warning_or_error
);
2019 FOR_EACH_VEC_ELT (*parm
.body_uses
, i
, puse
)
2024 /* Re-write local vars, similarly. */
2025 local_vars_transform xform_vars_data
2026 = {actor
, actor_frame
, coro_frame_type
, loc
, local_var_uses
};
2027 cp_walk_tree (&fnbody
, transform_local_var_uses
, &xform_vars_data
, NULL
);
2029 tree resume_idx_name
= get_identifier ("__resume_at");
2030 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2031 tf_warning_or_error
);
2032 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, actor_frame
,
2033 rat_field
, NULL_TREE
);
2036 = create_named_label_with_ctx (loc
, "actor.suspend.ret", actor
);
2039 = create_named_label_with_ctx (loc
, "actor.continue.ret", actor
);
2041 tree lsb_if
= begin_if_stmt ();
2042 tree chkb0
= build2 (BIT_AND_EXPR
, short_unsigned_type_node
, rat
,
2043 build_int_cst (short_unsigned_type_node
, 1));
2044 chkb0
= build2 (NE_EXPR
, short_unsigned_type_node
, chkb0
,
2045 build_int_cst (short_unsigned_type_node
, 0));
2046 finish_if_stmt_cond (chkb0
, lsb_if
);
2048 tree destroy_dispatcher
= begin_switch_stmt ();
2049 finish_switch_cond (rat
, destroy_dispatcher
);
2050 tree ddeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2051 create_anon_label_with_ctx (loc
, actor
));
2053 tree b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2054 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2057 short unsigned lab_num
= 3;
2058 for (unsigned destr_pt
= 0; destr_pt
< body_count
+ 2; destr_pt
++)
2060 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2061 b
= build_case_label (l_num
, NULL_TREE
,
2062 create_anon_label_with_ctx (loc
, actor
));
2064 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2066 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2068 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (ddeflab
));
2073 /* Insert the prototype dispatcher. */
2074 finish_switch_stmt (destroy_dispatcher
);
2076 finish_then_clause (lsb_if
);
2078 tree dispatcher
= begin_switch_stmt ();
2079 finish_switch_cond (rat
, dispatcher
);
2080 b
= build_case_label (build_int_cst (short_unsigned_type_node
, 0), NULL_TREE
,
2081 create_anon_label_with_ctx (loc
, actor
));
2083 b
= build1 (GOTO_EXPR
, void_type_node
, actor_begin_label
);
2086 tree rdeflab
= build_case_label (NULL_TREE
, NULL_TREE
,
2087 create_anon_label_with_ctx (loc
, actor
));
2089 b
= build_call_expr_loc (loc
, builtin_decl_explicit (BUILT_IN_TRAP
), 0);
2090 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2094 /* The final resume should be made to hit the default (trap, UB) entry. */
2095 for (unsigned resu_pt
= 0; resu_pt
< body_count
+ 1; resu_pt
++)
2097 tree l_num
= build_int_cst (short_unsigned_type_node
, lab_num
);
2098 b
= build_case_label (l_num
, NULL_TREE
,
2099 create_anon_label_with_ctx (loc
, actor
));
2101 b
= build_call_expr_internal_loc (loc
, IFN_CO_ACTOR
, void_type_node
, 1,
2103 b
= coro_build_cvt_void_expr_stmt (b
, loc
);
2105 b
= build1 (GOTO_EXPR
, void_type_node
, CASE_LABEL (rdeflab
));
2110 /* Insert the prototype dispatcher. */
2111 finish_switch_stmt (dispatcher
);
2113 finish_if_stmt (lsb_if
);
2115 tree r
= build_stmt (loc
, LABEL_EXPR
, actor_begin_label
);
2118 /* actor's version of the promise. */
2119 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
2120 tf_warning_or_error
);
2121 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
, false,
2122 tf_warning_or_error
);
2124 /* actor's coroutine 'self handle'. */
2125 tree ash_m
= lookup_member (coro_frame_type
, get_identifier ("__self_h"), 1,
2126 0, tf_warning_or_error
);
2127 tree ash
= build_class_member_access_expr (actor_frame
, ash_m
, NULL_TREE
,
2128 false, tf_warning_or_error
);
2129 /* So construct the self-handle from the frame address. */
2130 tree hfa_m
= lookup_member (handle_type
, coro_from_address_identifier
, 1,
2131 0, tf_warning_or_error
);
2133 r
= build1 (CONVERT_EXPR
, build_pointer_type (void_type_node
), actor_fp
);
2134 vec
<tree
, va_gc
> *args
= make_tree_vector_single (r
);
2135 tree hfa
= build_new_method_call (ash
, hfa_m
, &args
, NULL_TREE
, LOOKUP_NORMAL
,
2136 NULL
, tf_warning_or_error
);
2137 r
= build2 (INIT_EXPR
, handle_type
, ash
, hfa
);
2138 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2140 release_tree_vector (args
);
2142 /* Now we know the real promise, and enough about the frame layout to
2143 decide where to put things. */
2145 await_xform_data xform
2146 = {actor
, actor_frame
, promise_proxy
, ap
, self_h_proxy
, ash
};
2148 /* Get a reference to the initial suspend var in the frame. */
2149 transform_await_expr (initial_await
, &xform
);
2150 tree initial_await_stmt
= coro_build_expr_stmt (initial_await
, loc
);
2152 /* co_return branches to the final_suspend label, so declare that now. */
2153 tree fs_label
= create_named_label_with_ctx (loc
, "final.suspend", actor
);
2155 /* Expand co_returns in the saved function body */
2156 fnbody
= expand_co_returns (&fnbody
, promise_proxy
, ap
, fs_label
);
2158 /* n4849 adds specific behaviour to treat exceptions thrown by the
2159 await_resume () of the initial suspend expression. In order to
2160 implement this, we need to treat the initial_suspend expression
2161 as if it were part of the user-authored function body. This
2162 only applies if exceptions are enabled. */
2163 if (flag_exceptions
)
2165 tree outer
= fnbody
;
2166 if (TREE_CODE (outer
) == BIND_EXPR
)
2167 outer
= BIND_EXPR_BODY (outer
);
2168 gcc_checking_assert (TREE_CODE (outer
) == TRY_BLOCK
);
2169 tree sl
= TRY_STMTS (outer
);
2170 if (TREE_CODE (sl
) == STATEMENT_LIST
)
2172 tree_stmt_iterator si
= tsi_start (sl
);
2173 tsi_link_before (&si
, initial_await_stmt
, TSI_NEW_STMT
);
2177 tree new_try
= NULL_TREE
;
2178 append_to_statement_list (initial_await_stmt
, &new_try
);
2179 append_to_statement_list (sl
, &new_try
);
2180 TRY_STMTS (outer
) = new_try
;
2184 add_stmt (initial_await_stmt
);
2186 /* Transform the await expressions in the function body. Only do each
2188 hash_set
<tree
> pset
;
2189 cp_walk_tree (&fnbody
, transform_await_wrapper
, &xform
, &pset
);
2191 /* Add in our function body with the co_returns rewritten to final form. */
2194 /* Final suspend starts here. */
2195 r
= build_stmt (loc
, LABEL_EXPR
, fs_label
);
2198 /* Set the actor pointer to null, so that 'done' will work.
2199 Resume from here is UB anyway - although a 'ready' await will
2200 branch to the final resume, and fall through to the destroy. */
2202 = lookup_member (coro_frame_type
, get_identifier ("__resume"),
2203 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2204 tree res_x
= build_class_member_access_expr (actor_frame
, resume_m
, NULL_TREE
,
2205 false, tf_warning_or_error
);
2206 r
= build1 (CONVERT_EXPR
, act_des_fn_ptr
, integer_zero_node
);
2207 r
= build2 (INIT_EXPR
, act_des_fn_ptr
, res_x
, r
);
2208 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2211 /* Get a reference to the final suspend var in the frame. */
2212 transform_await_expr (final_await
, &xform
);
2213 r
= coro_build_expr_stmt (final_await
, loc
);
2216 /* now do the tail of the function. */
2217 tree del_promise_label
2218 = create_named_label_with_ctx (loc
, "coro.delete.promise", actor
);
2219 r
= build_stmt (loc
, LABEL_EXPR
, del_promise_label
);
2222 /* Destructors for the things we built explicitly. */
2223 r
= build_special_member_call (ap
, complete_dtor_identifier
, NULL
,
2224 promise_type
, LOOKUP_NORMAL
,
2225 tf_warning_or_error
);
2228 tree del_frame_label
2229 = create_named_label_with_ctx (loc
, "coro.delete.frame", actor
);
2230 r
= build_stmt (loc
, LABEL_EXPR
, del_frame_label
);
2233 /* Here deallocate the frame (if we allocated it), which we will have at
2236 = lookup_member (coro_frame_type
, get_identifier ("__frame_needs_free"), 1,
2237 0, tf_warning_or_error
);
2238 tree fnf2_x
= build_class_member_access_expr (actor_frame
, fnf_m
, NULL_TREE
,
2239 false, tf_warning_or_error
);
2241 tree need_free_if
= begin_if_stmt ();
2242 fnf2_x
= build1 (CONVERT_EXPR
, integer_type_node
, fnf2_x
);
2243 tree cmp
= build2 (NE_EXPR
, integer_type_node
, fnf2_x
, integer_zero_node
);
2244 finish_if_stmt_cond (cmp
, need_free_if
);
2245 if (param_dtor_list
!= NULL
)
2249 FOR_EACH_VEC_ELT (*param_dtor_list
, i
, pid
)
2252 = lookup_member (coro_frame_type
, pid
, 1, 0, tf_warning_or_error
);
2253 tree a
= build_class_member_access_expr (actor_frame
, m
, NULL_TREE
,
2254 false, tf_warning_or_error
);
2255 tree t
= TREE_TYPE (a
);
2258 = build_special_member_call (a
, complete_dtor_identifier
, NULL
, t
,
2259 LOOKUP_NORMAL
, tf_warning_or_error
);
2264 /* n4849 [dcl.fct.def.coroutine] / 12
2265 The deallocation function’s name is looked up in the scope of the promise
2266 type. If this lookup fails, the deallocation function’s name is looked up
2267 in the global scope. If deallocation function lookup finds both a usual
2268 deallocation function with only a pointer parameter and a usual
2269 deallocation function with both a pointer parameter and a size parameter,
2270 then the selected deallocation function shall be the one with two
2271 parameters. Otherwise, the selected deallocation function shall be the
2272 function with one parameter. If no usual deallocation function is found
2273 the program is ill-formed. The selected deallocation function shall be
2274 called with the address of the block of storage to be reclaimed as its
2275 first argument. If a deallocation function with a parameter of type
2276 std::size_t is used, the size of the block is passed as the corresponding
2279 tree del_coro_fr
= NULL_TREE
;
2280 tree frame_arg
= build1 (CONVERT_EXPR
, ptr_type_node
, actor_fp
);
2282 tree delname
= ovl_op_identifier (false, DELETE_EXPR
);
2283 tree fns
= lookup_promise_method (orig
, delname
, loc
, /*musthave=*/false);
2284 if (fns
&& BASELINK_P (fns
))
2286 /* Look for sized version first, since this takes precedence. */
2287 vec
<tree
, va_gc
> *args
= make_tree_vector ();
2288 vec_safe_push (args
, frame_arg
);
2289 vec_safe_push (args
, frame_size
);
2290 tree dummy_promise
= build_dummy_object (promise_type
);
2292 /* It's OK to fail for this one... */
2293 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2294 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2297 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2299 release_tree_vector (args
);
2300 args
= make_tree_vector_single (frame_arg
);
2301 del_coro_fr
= build_new_method_call (dummy_promise
, fns
, &args
,
2302 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
2306 /* But one of them must succeed, or the program is ill-formed. */
2307 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2309 error_at (loc
, "%qE is provided by %qT but is not usable with"
2310 " the function signature %qD", delname
, promise_type
, orig
);
2311 del_coro_fr
= error_mark_node
;
2316 del_coro_fr
= build_op_delete_call (DELETE_EXPR
, frame_arg
, frame_size
,
2317 /*global_p=*/true, /*placement=*/NULL
,
2319 tf_warning_or_error
);
2320 if (!del_coro_fr
|| del_coro_fr
== error_mark_node
)
2321 del_coro_fr
= error_mark_node
;
2324 del_coro_fr
= coro_build_cvt_void_expr_stmt (del_coro_fr
, loc
);
2325 add_stmt (del_coro_fr
);
2326 finish_then_clause (need_free_if
);
2327 tree scope
= IF_SCOPE (need_free_if
);
2328 IF_SCOPE (need_free_if
) = NULL
;
2329 r
= do_poplevel (scope
);
2333 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2334 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2335 r
= maybe_cleanup_point_expr_void (r
);
2338 /* This is the suspend return point. */
2339 r
= build_stmt (loc
, LABEL_EXPR
, ret_label
);
2342 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2343 TREE_NO_WARNING (r
) |= 1; /* We don't want a warning about this. */
2344 r
= maybe_cleanup_point_expr_void (r
);
2347 /* This is the 'continuation' return point. For such a case we have a coro
2348 handle (from the await_suspend() call) and we want handle.resume() to
2349 execute as a tailcall allowing arbitrary chaining of coroutines. */
2350 r
= build_stmt (loc
, LABEL_EXPR
, continue_label
);
2353 /* We want to force a tail-call even for O0/1, so this expands the resume
2354 call into its underlying implementation. */
2355 tree addr
= lookup_member (void_coro_handle_type
, coro_address_identifier
,
2356 1, 0, tf_warning_or_error
);
2357 addr
= build_new_method_call (continuation
, addr
, NULL
, NULL_TREE
,
2358 LOOKUP_NORMAL
, NULL
, tf_warning_or_error
);
2359 tree resume
= build_call_expr_loc
2360 (loc
, builtin_decl_explicit (BUILT_IN_CORO_RESUME
), 1, addr
);
2362 /* Now we have the actual call, and we can mark it as a tail. */
2363 CALL_EXPR_TAILCALL (resume
) = true;
2364 /* ... and for optimisation levels 0..1, mark it as requiring a tail-call
2365 for correctness. It seems that doing this for optimisation levels that
2366 normally perform tail-calling, confuses the ME (or it would be logical
2367 to put this on unilaterally). */
2369 CALL_EXPR_MUST_TAIL_CALL (resume
) = true;
2370 resume
= coro_build_cvt_void_expr_stmt (resume
, loc
);
2373 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2374 gcc_checking_assert (maybe_cleanup_point_expr_void (r
) == r
);
2377 /* We will need to know which resume point number should be encoded. */
2379 = lookup_member (coro_frame_type
, resume_idx_name
,
2380 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2381 tree resume_pt_number
2382 = build_class_member_access_expr (actor_frame
, res_idx_m
, NULL_TREE
, false,
2383 tf_warning_or_error
);
2385 /* Boolean value to flag that the initial suspend expression's
2386 await_resume () has been called, and therefore we are in the user's
2387 function body for the purposes of handing exceptions. */
2389 = lookup_member (coro_frame_type
, get_identifier ("__i_a_r_c"),
2390 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
2392 = build_class_member_access_expr (actor_frame
, i_a_r_c_m
, NULL_TREE
,
2393 false, tf_warning_or_error
);
2395 /* We've now rewritten the tree and added the initial and final
2396 co_awaits. Now pass over the tree and expand the co_awaits. */
2398 coro_aw_data data
= {actor
, actor_fp
, resume_pt_number
, i_a_r_c
,
2399 ash
, del_promise_label
, ret_label
,
2400 continue_label
, continuation
, 2};
2401 cp_walk_tree (&actor_body
, co_await_expander
, &data
, NULL
);
2403 actor_body
= pop_stmt_list (actor_body
);
2404 BIND_EXPR_BODY (actor_bind
) = actor_body
;
2406 finish_compound_stmt (stmt
);
2407 DECL_SAVED_TREE (actor
) = pop_stmt_list (actor_outer
);
2408 verify_stmt_tree (DECL_SAVED_TREE (actor
));
2411 /* The prototype 'destroy' function :
2412 frame->__resume_at |= 1;
2416 build_destroy_fn (location_t loc
, tree coro_frame_type
, tree destroy
,
2419 /* One param, the coro frame pointer. */
2420 tree destr_fp
= DECL_ARGUMENTS (destroy
);
2422 /* A void return. */
2423 tree resdecl
= build_decl (loc
, RESULT_DECL
, 0, void_type_node
);
2424 DECL_ARTIFICIAL (resdecl
) = 1;
2425 DECL_IGNORED_P (resdecl
) = 1;
2426 DECL_RESULT (destroy
) = resdecl
;
2428 /* We have a definition here. */
2429 TREE_STATIC (destroy
) = 1;
2430 DECL_COROUTINE_P (destroy
) = 1;
2432 tree destr_outer
= push_stmt_list ();
2433 current_stmt_tree ()->stmts_are_full_exprs_p
= 1;
2434 tree dstr_stmt
= begin_compound_stmt (BCS_FN_BODY
);
2436 tree destr_frame
= build1 (INDIRECT_REF
, coro_frame_type
, destr_fp
);
2438 tree resume_idx_name
= get_identifier ("__resume_at");
2439 tree rat_field
= lookup_member (coro_frame_type
, resume_idx_name
, 1, 0,
2440 tf_warning_or_error
);
2441 tree rat
= build3 (COMPONENT_REF
, short_unsigned_type_node
, destr_frame
,
2442 rat_field
, NULL_TREE
);
2444 /* _resume_at |= 1 */
2445 tree dstr_idx
= build2 (BIT_IOR_EXPR
, short_unsigned_type_node
, rat
,
2446 build_int_cst (short_unsigned_type_node
, 1));
2447 tree r
= build2 (MODIFY_EXPR
, short_unsigned_type_node
, rat
, dstr_idx
);
2448 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2451 /* So .. call the actor .. */
2452 r
= build_call_expr_loc (loc
, actor
, 1, destr_fp
);
2453 r
= coro_build_cvt_void_expr_stmt (r
, loc
);
2457 r
= build_stmt (loc
, RETURN_EXPR
, NULL
);
2458 r
= maybe_cleanup_point_expr_void (r
);
2461 finish_compound_stmt (dstr_stmt
);
2462 DECL_SAVED_TREE (destroy
) = pop_stmt_list (destr_outer
);
2465 /* Helper that returns an identifier for an appended extension to the
2466 current un-mangled function name. */
2469 get_fn_local_identifier (tree orig
, const char *append
)
2471 /* Figure out the bits we need to generate names for the outlined things
2472 For consistency, this needs to behave the same way as
2473 ASM_FORMAT_PRIVATE_NAME does. */
2474 tree nm
= DECL_NAME (orig
);
2475 const char *sep
, *pfx
= "";
2476 #ifndef NO_DOT_IN_LABEL
2479 #ifndef NO_DOLLAR_IN_LABEL
2488 if (DECL_ASSEMBLER_NAME (orig
))
2489 an
= ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig
)), sep
, append
,
2491 else if (DECL_USE_TEMPLATE (orig
) && DECL_TEMPLATE_INFO (orig
)
2492 && DECL_TI_ARGS (orig
))
2494 tree tpl_args
= DECL_TI_ARGS (orig
);
2495 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), (char *) 0));
2496 for (int i
= 0; i
< TREE_VEC_LENGTH (tpl_args
); ++i
)
2498 tree typ
= DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args
, i
)));
2499 an
= ACONCAT ((an
, sep
, IDENTIFIER_POINTER (typ
), (char *) 0));
2501 an
= ACONCAT ((an
, sep
, append
, (char *) 0));
2504 an
= ACONCAT ((pfx
, IDENTIFIER_POINTER (nm
), sep
, append
, (char *) 0));
2506 return get_identifier (an
);
2510 build_init_or_final_await (location_t loc
, bool is_final
)
2512 tree suspend_alt
= is_final
? coro_final_suspend_identifier
2513 : coro_initial_suspend_identifier
;
2514 tree setup_meth
= lookup_promise_method (current_function_decl
, suspend_alt
,
2515 loc
, /*musthave=*/true);
2516 if (!setup_meth
|| setup_meth
== error_mark_node
)
2517 return error_mark_node
;
2519 tree s_fn
= NULL_TREE
;
2520 tree setup_call
= build_new_method_call (
2521 get_coroutine_promise_proxy (current_function_decl
), setup_meth
, NULL
,
2522 NULL_TREE
, LOOKUP_NORMAL
, &s_fn
, tf_warning_or_error
);
2524 if (!s_fn
|| setup_call
== error_mark_node
)
2525 return error_mark_node
;
2527 /* So build the co_await for this */
2528 /* For initial/final suspends the call is "a" per [expr.await] 3.2. */
2529 return build_co_await (loc
, setup_call
, (is_final
? FINAL_SUSPEND_POINT
2530 : INITIAL_SUSPEND_POINT
));
2533 /* Callback to record the essential data for each await point found in the
2537 register_await_info (tree await_expr
, tree aw_type
, tree aw_nam
)
2540 suspend_point_info
&s
2541 = suspend_points
->get_or_insert (await_expr
, &seen
);
2544 error_at (EXPR_LOCATION (await_expr
), "duplicate info for %qE",
2548 s
.awaitable_type
= aw_type
;
2549 s
.await_field_id
= aw_nam
;
2553 /* Small helper for the repetitive task of adding a new field to the coro
2557 coro_make_frame_entry (tree
*field_list
, const char *name
, tree fld_type
,
2560 tree id
= get_identifier (name
);
2561 tree decl
= build_decl (loc
, FIELD_DECL
, id
, fld_type
);
2562 DECL_CHAIN (decl
) = *field_list
;
2567 struct susp_frame_data
2571 hash_set
<tree
> captured_temps
;
2572 vec
<tree
, va_gc
> *to_replace
;
2573 vec
<tree
, va_gc
> *block_stack
;
2575 unsigned saw_awaits
;
2576 bool captures_temporary
;
2579 /* Walk the sub-tree looking for call expressions that both capture
2580 references and have compiler-temporaries as parms. */
2583 captures_temporary (tree
*stmt
, int *do_subtree
, void *d
)
2585 /* Stop recursing if we see an await expression, the subtrees
2586 of that will be handled when it is processed. */
2587 if (TREE_CODE (*stmt
) == CO_AWAIT_EXPR
|| TREE_CODE (*stmt
) == CO_YIELD_EXPR
)
2593 /* We're only interested in calls. */
2594 if (TREE_CODE (*stmt
) != CALL_EXPR
)
2597 /* Does this call capture references?
2598 Strip the ADDRESS_EXPR to get the fn decl and inspect it. */
2599 tree fn
= TREE_OPERAND (CALL_EXPR_FN (*stmt
), 0);
2600 bool is_meth
= TREE_CODE (TREE_TYPE (fn
)) == METHOD_TYPE
;
2601 tree arg
= TYPE_ARG_TYPES (TREE_TYPE (fn
));
2602 unsigned offset
= 3;
2603 for (unsigned anum
= 0; arg
!= NULL
; arg
= TREE_CHAIN (arg
), anum
++)
2605 tree parm_type
= TREE_VALUE (arg
);
2606 if (anum
== 0 && is_meth
&& INDIRECT_TYPE_P (parm_type
))
2608 /* Account for 'this' when the fn is a method. Unless it
2609 belongs to a CTOR or DTOR. */
2610 if (DECL_CONSTRUCTOR_P (fn
) || DECL_DESTRUCTOR_P (fn
))
2613 else if (!TYPE_REF_P (parm_type
))
2614 /* If it's not a reference, we don't care. */
2617 /* Fetch the value presented to the fn. */
2618 tree parm
= TREE_OPERAND (*stmt
, anum
+ offset
);
2620 while (TREE_CODE (parm
) == NOP_EXPR
)
2621 parm
= TREE_OPERAND (parm
, 0);
2623 /* We only care if we're taking the addr of a temporary. */
2624 if (TREE_CODE (parm
) != ADDR_EXPR
)
2627 parm
= TREE_OPERAND (parm
, 0);
2629 /* In case of component_ref, we need to capture the object of base
2630 class as if it is temporary object. There are two possibilities:
2631 (*base).field and base->field. */
2632 while (TREE_CODE (parm
) == COMPONENT_REF
)
2634 parm
= TREE_OPERAND (parm
, 0);
2635 if (TREE_CODE (parm
) == INDIRECT_REF
)
2636 parm
= TREE_OPERAND (parm
, 0);
2637 parm
= STRIP_NOPS (parm
);
2640 /* This isn't a temporary. */
2641 if ((TREE_CODE (parm
) == VAR_DECL
&& !DECL_ARTIFICIAL (parm
))
2642 || TREE_CODE (parm
) == PARM_DECL
2643 || TREE_CODE (parm
) == NON_LVALUE_EXPR
)
2646 if (TREE_CODE (parm
) == TARGET_EXPR
)
2648 /* We're taking the address of a temporary and using it as a ref. */
2649 tree tvar
= TREE_OPERAND (parm
, 0);
2650 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2652 susp_frame_data
*data
= (susp_frame_data
*) d
;
2653 data
->captures_temporary
= true;
2654 /* Record this one so we don't duplicate, and on the first
2655 occurrence note the target expr to be replaced. */
2656 if (!data
->captured_temps
.add (tvar
))
2657 vec_safe_push (data
->to_replace
, parm
);
2658 /* Now see if the initializer contains any more cases. */
2659 hash_set
<tree
> visited
;
2660 tree res
= cp_walk_tree (&TREE_OPERAND (parm
, 1),
2661 captures_temporary
, d
, &visited
);
2664 /* Otherwise, we're done with sub-trees for this. */
2666 else if (TREE_CODE (parm
) == CO_AWAIT_EXPR
)
2668 /* CO_AWAIT expressions behave in a similar manner to target
2669 expressions when the await_resume call is contained in one. */
2670 tree awr
= TREE_OPERAND (parm
, 3); /* call vector. */
2671 awr
= TREE_VEC_ELT (awr
, 2); /* resume call. */
2672 if (TREE_CODE (awr
) == TARGET_EXPR
)
2674 tree tvar
= TREE_OPERAND (awr
, 0);
2675 gcc_checking_assert (DECL_ARTIFICIAL (tvar
));
2677 susp_frame_data
*data
= (susp_frame_data
*) d
;
2678 data
->captures_temporary
= true;
2679 /* Use this as a place-holder. */
2680 if (!data
->captured_temps
.add (tvar
))
2681 vec_safe_push (data
->to_replace
, parm
);
2683 /* We will walk the sub-trees of this co_await separately. */
2688 /* As far as it's necessary, we've walked the subtrees of the call
2694 /* If this is an await, then register it and decide on what coro
2695 frame storage is needed.
2696 If this is a co_yield (which embeds an await), drop the yield
2697 and record the await (the yield was kept for diagnostics only). */
2700 register_awaits (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
2702 susp_frame_data
*data
= (susp_frame_data
*) d
;
2704 if (TREE_CODE (*stmt
) != CO_AWAIT_EXPR
&& TREE_CODE (*stmt
) != CO_YIELD_EXPR
)
2707 /* co_yield is syntactic sugar, re-write it to co_await. */
2708 tree aw_expr
= *stmt
;
2709 location_t aw_loc
= EXPR_LOCATION (aw_expr
); /* location of the co_xxxx. */
2710 if (TREE_CODE (aw_expr
) == CO_YIELD_EXPR
)
2712 aw_expr
= TREE_OPERAND (aw_expr
, 1);
2716 /* Count how many awaits full expression contains. This is not the same
2717 as the counter used for the function-wide await point number. */
2720 /* If the awaitable is a parm or a local variable, then we already have
2721 a frame copy, so don't make a new one. */
2722 tree aw
= TREE_OPERAND (aw_expr
, 1);
2723 tree aw_field_type
= TREE_TYPE (aw
);
2724 tree aw_field_nam
= NULL_TREE
;
2725 if (INDIRECT_REF_P (aw
))
2726 aw
= TREE_OPERAND (aw
, 0);
2727 if (TREE_CODE (aw
) == PARM_DECL
2728 || (TREE_CODE (aw
) == VAR_DECL
&& !DECL_ARTIFICIAL (aw
)))
2729 ; /* Don't make an additional copy. */
2732 /* The required field has the same type as the proxy stored in the
2734 char *nam
= xasprintf ("__aw_s.%d", data
->count
);
2735 aw_field_nam
= coro_make_frame_entry (data
->field_list
, nam
,
2736 aw_field_type
, aw_loc
);
2740 register_await_info (aw_expr
, aw_field_type
, aw_field_nam
);
2742 data
->count
++; /* Each await suspend context is unique. */
2744 /* We now need to know if to take special action on lifetime extension
2745 of temporaries captured by reference. This can only happen if such
2746 a case appears in the initializer for the awaitable. The callback
2747 records captured temporaries including subtrees of initializers. */
2748 hash_set
<tree
> visited
;
2749 tree res
= cp_walk_tree (&TREE_OPERAND (aw_expr
, 2), captures_temporary
, d
,
2754 /* The gimplifier correctly extends the lifetime of temporaries captured
2755 by reference (per. [class.temporary] (6.9) "A temporary object bound
2756 to a reference parameter in a function call persists until the completion
2757 of the full-expression containing the call"). However, that is not
2758 sufficient to work across a suspension - and we need to promote such
2759 temporaries to be regular vars that will then get a coro frame slot.
2760 We don't want to incur the effort of checking for this unless we have
2761 an await expression in the current full expression. */
2764 maybe_promote_captured_temps (tree
*stmt
, void *d
)
2766 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2767 hash_set
<tree
> visited
;
2768 awpts
->saw_awaits
= 0;
2770 /* When register_awaits sees an await, it walks the initializer for
2771 that await looking for temporaries captured by reference and notes
2772 them in awpts->captured_temps. We only need to take any action here
2773 if the statement contained any awaits, and any of those had temporaries
2774 captured by reference in the initializers for their class. */
2776 tree res
= cp_walk_tree (stmt
, register_awaits
, d
, &visited
);
2777 if (!res
&& awpts
->saw_awaits
> 0 && !awpts
->captured_temps
.is_empty ())
2779 location_t sloc
= EXPR_LOCATION (*stmt
);
2781 = build3_loc (sloc
, BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
2783 /* Any cleanup point expression might no longer be necessary, since we
2784 are removing one or more temporaries. */
2785 tree aw_statement_current
= *stmt
;
2786 if (TREE_CODE (aw_statement_current
) == CLEANUP_POINT_EXPR
)
2787 aw_statement_current
= TREE_OPERAND (aw_statement_current
, 0);
2789 /* Collected the scope vars we need move the temps to regular. */
2790 tree aw_bind_body
= push_stmt_list ();
2791 tree varlist
= NULL_TREE
;
2793 while (!awpts
->to_replace
->is_empty ())
2795 size_t bufsize
= sizeof ("__aw_.tmp.") + 20;
2796 char *buf
= (char *) alloca (bufsize
);
2797 snprintf (buf
, bufsize
, "__aw_%d.tmp.%d", awpts
->count
, ++vnum
);
2798 tree to_replace
= awpts
->to_replace
->pop ();
2800 if (TREE_CODE (to_replace
) == CO_AWAIT_EXPR
)
2802 orig_temp
= TREE_OPERAND (to_replace
, 3);
2803 orig_temp
= TREE_VEC_ELT (orig_temp
, 2);
2804 orig_temp
= TREE_OPERAND (orig_temp
, 0);
2807 orig_temp
= TREE_OPERAND (to_replace
, 0);
2809 tree var_type
= TREE_TYPE (orig_temp
);
2810 gcc_assert (same_type_p (TREE_TYPE (to_replace
), var_type
));
2812 = build_lang_decl (VAR_DECL
, get_identifier (buf
), var_type
);
2813 DECL_CONTEXT (newvar
) = DECL_CONTEXT (orig_temp
);
2814 if (DECL_SOURCE_LOCATION (orig_temp
))
2815 sloc
= DECL_SOURCE_LOCATION (orig_temp
);
2816 DECL_SOURCE_LOCATION (newvar
) = sloc
;
2817 DECL_CHAIN (newvar
) = varlist
;
2818 varlist
= newvar
; /* Chain it onto the list for the bind expr. */
2819 /* Declare and initialze it in the new bind scope. */
2820 add_decl_expr (newvar
);
2822 = build2_loc (sloc
, INIT_EXPR
, var_type
, newvar
, to_replace
);
2823 stmt
= coro_build_cvt_void_expr_stmt (stmt
, sloc
);
2825 proxy_replace pr
= {to_replace
, newvar
};
2826 /* Replace all instances of that temp in the original expr. */
2827 cp_walk_tree (&aw_statement_current
, replace_proxy
, &pr
, NULL
);
2830 /* What's left should be the original statement with any co_await
2831 captured temporaries broken out. Other temporaries might remain
2832 so see if we need to wrap the revised statement in a cleanup. */
2833 aw_statement_current
=
2834 maybe_cleanup_point_expr_void (aw_statement_current
);
2835 add_stmt (aw_statement_current
);
2836 BIND_EXPR_BODY (aw_bind
) = pop_stmt_list (aw_bind_body
);
2837 awpts
->captured_temps
.empty ();
2839 BIND_EXPR_VARS (aw_bind
) = nreverse (varlist
);
2840 tree b_block
= make_node (BLOCK
);
2841 if (!awpts
->block_stack
->is_empty ())
2843 tree s_block
= awpts
->block_stack
->last ();
2846 BLOCK_SUPERCONTEXT (b_block
) = s_block
;
2847 BLOCK_CHAIN (b_block
) = BLOCK_SUBBLOCKS (s_block
);
2848 BLOCK_SUBBLOCKS (s_block
) = b_block
;
2851 BIND_EXPR_BLOCK (aw_bind
) = b_block
;
2859 await_statement_walker (tree
*stmt
, int *do_subtree
, void *d
)
2861 tree res
= NULL_TREE
;
2862 susp_frame_data
*awpts
= (susp_frame_data
*) d
;
2864 /* We might need to insert a new bind expression, and want to link it
2865 into the correct scope, so keep a note of the current block scope. */
2866 if (TREE_CODE (*stmt
) == BIND_EXPR
)
2868 tree
*body
= &BIND_EXPR_BODY (*stmt
);
2869 tree blk
= BIND_EXPR_BLOCK (*stmt
);
2870 vec_safe_push (awpts
->block_stack
, blk
);
2872 if (TREE_CODE (*body
) == STATEMENT_LIST
)
2874 tree_stmt_iterator i
;
2875 for (i
= tsi_start (*body
); !tsi_end_p (i
); tsi_next (&i
))
2877 tree
*new_stmt
= tsi_stmt_ptr (i
);
2878 if (STATEMENT_CLASS_P (*new_stmt
) || !EXPR_P (*new_stmt
)
2879 || TREE_CODE (*new_stmt
) == BIND_EXPR
)
2880 res
= cp_walk_tree (new_stmt
, await_statement_walker
, d
, NULL
);
2882 res
= maybe_promote_captured_temps (new_stmt
, d
);
2886 *do_subtree
= 0; /* Done subtrees. */
2888 else if (!STATEMENT_CLASS_P (*body
) && EXPR_P (*body
)
2889 && TREE_CODE (*body
) != BIND_EXPR
)
2891 res
= maybe_promote_captured_temps (body
, d
);
2892 *do_subtree
= 0; /* Done subtrees. */
2894 awpts
->block_stack
->pop ();
2896 else if (!STATEMENT_CLASS_P (*stmt
) && EXPR_P (*stmt
)
2897 && TREE_CODE (*stmt
) != BIND_EXPR
)
2899 res
= maybe_promote_captured_temps (stmt
, d
);
2900 *do_subtree
= 0; /* Done subtrees. */
2902 /* If it wasn't a statement list, or a single statement, continue. */
2906 /* For figuring out what param usage we have. */
2908 struct param_frame_data
2911 hash_map
<tree
, param_info
> *param_uses
;
2912 hash_set
<tree
*> *visited
;
2918 register_param_uses (tree
*stmt
, int *do_subtree ATTRIBUTE_UNUSED
, void *d
)
2920 param_frame_data
*data
= (param_frame_data
*) d
;
2922 /* For lambda closure content, we have to look specifically. */
2923 if (TREE_CODE (*stmt
) == VAR_DECL
&& DECL_HAS_VALUE_EXPR_P (*stmt
))
2925 tree t
= DECL_VALUE_EXPR (*stmt
);
2926 return cp_walk_tree (&t
, register_param_uses
, d
, NULL
);
2929 if (TREE_CODE (*stmt
) != PARM_DECL
)
2932 /* If we already saw the containing expression, then we're done. */
2933 if (data
->visited
->add (stmt
))
2937 param_info
&parm
= data
->param_uses
->get_or_insert (*stmt
, &existed
);
2938 gcc_checking_assert (existed
);
2940 if (!parm
.body_uses
)
2942 vec_alloc (parm
.body_uses
, 4);
2943 parm
.body_uses
->quick_push (stmt
);
2944 data
->param_seen
= true;
2947 parm
.body_uses
->safe_push (stmt
);
2952 /* For figuring out what local variable usage we have. */
2954 struct local_vars_frame_data
2957 hash_map
<tree
, local_var_info
> *local_var_uses
;
2958 unsigned int nest_depth
, bind_indx
;
2961 bool local_var_seen
;
2965 register_local_var_uses (tree
*stmt
, int *do_subtree
, void *d
)
2967 local_vars_frame_data
*lvd
= (local_vars_frame_data
*) d
;
2969 /* As we enter a bind expression - record the vars there and then recurse.
2970 As we exit drop the nest depth.
2971 The bind index is a growing count of how many bind indices we've seen.
2972 We build a space in the frame for each local var. */
2974 if (TREE_CODE (*stmt
) == BIND_EXPR
)
2979 for (lvar
= BIND_EXPR_VARS (*stmt
); lvar
!= NULL
;
2980 lvar
= DECL_CHAIN (lvar
))
2983 local_var_info
&local_var
2984 = lvd
->local_var_uses
->get_or_insert (lvar
, &existed
);
2985 gcc_checking_assert (!existed
);
2986 local_var
.def_loc
= DECL_SOURCE_LOCATION (lvar
);
2987 tree lvtype
= TREE_TYPE (lvar
);
2988 local_var
.frame_type
= lvtype
;
2989 local_var
.field_idx
= local_var
.field_id
= NULL_TREE
;
2990 lvd
->local_var_seen
= true;
2991 /* If this var is a lambda capture proxy, we want to leave it alone,
2992 and later rewrite the DECL_VALUE_EXPR to indirect through the
2993 frame copy of the pointer to the lambda closure object. */
2994 local_var
.is_lambda_capture
= is_capture_proxy (lvar
);
2995 if (local_var
.is_lambda_capture
)
2998 /* Make names depth+index unique, so that we can support nested
2999 scopes with identically named locals. */
3000 tree lvname
= DECL_NAME (lvar
);
3002 if (lvname
!= NULL_TREE
)
3003 buf
= xasprintf ("__lv.%u.%u.%s", lvd
->bind_indx
, lvd
->nest_depth
,
3004 IDENTIFIER_POINTER (lvname
));
3006 buf
= xasprintf ("__lv.%u.%u.D%u", lvd
->bind_indx
, lvd
->nest_depth
,
3008 /* TODO: Figure out if we should build a local type that has any
3009 excess alignment or size from the original decl. */
3011 = coro_make_frame_entry (lvd
->field_list
, buf
, lvtype
, lvd
->loc
);
3013 /* We don't walk any of the local var sub-trees, they won't contain
3016 cp_walk_tree (&BIND_EXPR_BODY (*stmt
), register_local_var_uses
, d
, NULL
);
3017 *do_subtree
= 0; /* We've done this. */
3023 /* Build, return FUNCTION_DECL node with its coroutine frame pointer argument
3024 for either actor or destroy functions. */
3027 act_des_fn (tree orig
, tree fn_type
, tree coro_frame_ptr
, const char* name
)
3029 tree fn_name
= get_fn_local_identifier (orig
, name
);
3030 tree fn
= build_lang_decl (FUNCTION_DECL
, fn_name
, fn_type
);
3031 DECL_CONTEXT (fn
) = DECL_CONTEXT (orig
);
3032 DECL_INITIAL (fn
) = error_mark_node
;
3033 tree id
= get_identifier ("frame_ptr");
3034 tree fp
= build_lang_decl (PARM_DECL
, id
, coro_frame_ptr
);
3035 DECL_CONTEXT (fp
) = fn
;
3036 DECL_ARG_TYPE (fp
) = type_passed_as (coro_frame_ptr
);
3037 DECL_ARGUMENTS (fn
) = fp
;
3042 a) Check that the function and promise type are valid for a
3044 b) Carry out the initial morph to create the skeleton of the
3045 coroutine ramp function and the rewritten body.
3049 1. We only hit this code once all dependencies are resolved.
3050 2. The function body will be either a bind expr or a statement list
3051 3. That cfun and current_function_decl are valid for the case we're
3053 4. 'input_location' will be of the final brace for the function.
3055 We do something like this:
3056 declare a dummy coro frame.
3058 using handle_type = coro::coroutine_handle<coro1::promise_type>;
3059 void (*__resume)(_R_frame *);
3060 void (*__destroy)(_R_frame *);
3061 coro1::promise_type __p;
3062 bool frame_needs_free; free the coro frame mem if set.
3063 bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
3065 handle_type self_handle;
3066 (maybe) parameter copies.
3067 coro1::suspend_never_prt __is;
3068 coro1::suspend_always_prt __fs;
3069 (maybe) local variables saved
3070 (maybe) trailing space.
3074 morph_fn_to_coro (tree orig
, tree
*resumer
, tree
*destroyer
)
3076 gcc_checking_assert (orig
&& TREE_CODE (orig
) == FUNCTION_DECL
);
3078 if (!coro_function_valid_p (orig
))
3081 /* The ramp function does return a value. */
3082 current_function_returns_value
= 1;
3084 /* We can't validly get here with an empty statement list, since there's no
3085 way for the FE to decide it's a coroutine in the absence of any code. */
3086 tree fnbody
= pop_stmt_list (DECL_SAVED_TREE (orig
));
3087 if (fnbody
== NULL_TREE
)
3090 /* We don't have the locus of the opening brace - it's filled in later (and
3091 there doesn't really seem to be any easy way to get at it).
3092 The closing brace is assumed to be input_location. */
3093 location_t fn_start
= DECL_SOURCE_LOCATION (orig
);
3094 gcc_rich_location
fn_start_loc (fn_start
);
3096 /* Initial processing of the function-body.
3097 If we have no expressions or just an error then punt. */
3098 tree body_start
= expr_first (fnbody
);
3099 if (body_start
== NULL_TREE
|| body_start
== error_mark_node
)
3101 DECL_SAVED_TREE (orig
) = push_stmt_list ();
3102 append_to_statement_list (DECL_SAVED_TREE (orig
), &fnbody
);
3106 /* So, we've tied off the original body. Now start the replacement.
3107 If we encounter a fatal error we might return a now-empty body.
3108 TODO: determine if it would help to restore the original.
3109 determine if looking for more errors in coro_function_valid_p()
3110 and stashing types is a better solution. */
3112 tree newbody
= push_stmt_list ();
3113 DECL_SAVED_TREE (orig
) = newbody
;
3115 /* If our original body is noexcept, then that's what we apply to our
3116 generated functions. Remember that we're NOEXCEPT and fish out the
3117 contained list (we tied off to the top level already). */
3118 bool is_noexcept
= TREE_CODE (body_start
) == MUST_NOT_THROW_EXPR
;
3121 /* Simplified abstract from begin_eh_spec_block, since we already
3122 know the outcome. */
3123 fnbody
= TREE_OPERAND (body_start
, 0); /* Stash the original... */
3124 add_stmt (body_start
); /* ... and start the new. */
3125 TREE_OPERAND (body_start
, 0) = push_stmt_list ();
3128 /* Create the coro frame type, as far as it can be known at this stage.
3129 1. Types we already know. */
3131 tree fn_return_type
= TREE_TYPE (TREE_TYPE (orig
));
3132 gcc_assert (!VOID_TYPE_P (fn_return_type
));
3133 tree handle_type
= get_coroutine_handle_type (orig
);
3134 tree promise_type
= get_coroutine_promise_type (orig
);
3136 /* 2. Types we need to define or look up. */
3138 /* We need to know, and inspect, each suspend point in the function
3139 in several places. It's convenient to place this map out of line
3140 since it's used from tree walk callbacks. */
3141 suspend_points
= new hash_map
<tree
, suspend_point_info
>;
3143 /* Initial and final suspend types are special in that the co_awaits for
3144 them are synthetic. We need to find the type for each awaiter from
3145 the coroutine promise. */
3146 tree initial_await
= build_init_or_final_await (fn_start
, false);
3147 if (initial_await
== error_mark_node
)
3149 /* The type of the frame var for this is the type of its temp proxy. */
3150 tree initial_suspend_type
= TREE_TYPE (TREE_OPERAND (initial_await
, 1));
3152 tree final_await
= build_init_or_final_await (fn_start
, true);
3153 if (final_await
== error_mark_node
)
3156 /* The type of the frame var for this is the type of its temp proxy. */
3157 tree final_suspend_type
= TREE_TYPE (TREE_OPERAND (final_await
, 1));
3159 tree fr_name
= get_fn_local_identifier (orig
, "frame");
3160 tree coro_frame_type
= xref_tag (record_type
, fr_name
, ts_current
, false);
3161 DECL_CONTEXT (TYPE_NAME (coro_frame_type
)) = current_scope ();
3162 tree coro_frame_ptr
= build_pointer_type (coro_frame_type
);
3163 tree act_des_fn_type
3164 = build_function_type_list (void_type_node
, coro_frame_ptr
, NULL_TREE
);
3165 tree act_des_fn_ptr
= build_pointer_type (act_des_fn_type
);
3167 /* Declare the actor and destroyer function. */
3168 tree actor
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "actor");
3169 tree destroy
= act_des_fn (orig
, act_des_fn_type
, coro_frame_ptr
, "destroy");
3171 /* Build our dummy coro frame layout. */
3172 coro_frame_type
= begin_class_definition (coro_frame_type
);
3174 tree field_list
= NULL_TREE
;
3176 = coro_make_frame_entry (&field_list
, "__resume", act_des_fn_ptr
, fn_start
);
3177 tree destroy_name
= coro_make_frame_entry (&field_list
, "__destroy",
3178 act_des_fn_ptr
, fn_start
);
3180 = coro_make_frame_entry (&field_list
, "__p", promise_type
, fn_start
);
3181 tree fnf_name
= coro_make_frame_entry (&field_list
, "__frame_needs_free",
3182 boolean_type_node
, fn_start
);
3183 tree iarc_name
= coro_make_frame_entry (&field_list
, "__i_a_r_c",
3184 boolean_type_node
, fn_start
);
3185 tree resume_idx_name
3186 = coro_make_frame_entry (&field_list
, "__resume_at",
3187 short_unsigned_type_node
, fn_start
);
3189 /* We need a handle to this coroutine, which is passed to every
3190 await_suspend(). There's no point in creating it over and over. */
3191 (void) coro_make_frame_entry (&field_list
, "__self_h", handle_type
, fn_start
);
3193 /* Now add in fields for function params (if there are any).
3194 We do not attempt elision of copies at this stage, we do analyse the
3195 uses and build worklists to replace those when the state machine is
3198 hash_map
<tree
, param_info
> *param_uses
= NULL
;
3199 if (DECL_ARGUMENTS (orig
))
3201 /* Build a hash map with an entry for each param.
3202 The key is the param tree.
3203 Then we have an entry for the frame field name.
3204 Then a cache for the field ref when we come to use it.
3205 Then a tree list of the uses.
3206 The second two entries start out empty - and only get populated
3207 when we see uses. */
3208 param_uses
= new hash_map
<tree
, param_info
>;
3210 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3211 arg
= DECL_CHAIN (arg
))
3214 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3215 gcc_checking_assert (!existed
);
3216 parm
.body_uses
= NULL
;
3217 tree actual_type
= TREE_TYPE (arg
);
3218 actual_type
= complete_type_or_else (actual_type
, orig
);
3219 if (actual_type
== NULL_TREE
)
3220 actual_type
= error_mark_node
;
3221 parm
.orig_type
= actual_type
;
3222 parm
.by_ref
= parm
.rv_ref
= parm
.pt_ref
= false;
3223 if (TREE_CODE (actual_type
) == REFERENCE_TYPE
3224 && TYPE_REF_IS_RVALUE (DECL_ARG_TYPE (arg
)))
3227 actual_type
= TREE_TYPE (actual_type
);
3228 parm
.frame_type
= actual_type
;
3230 else if (TREE_CODE (actual_type
) == REFERENCE_TYPE
)
3232 /* If the user passes by reference, then we will save the
3233 pointer to the original. As noted in
3234 [dcl.fct.def.coroutine] / 13, if the lifetime of the
3235 referenced item ends and then the coroutine is resumed,
3236 we have UB; well, the user asked for it. */
3237 actual_type
= build_pointer_type (TREE_TYPE (actual_type
));
3238 parm
.frame_type
= actual_type
;
3241 else if (TYPE_REF_P (DECL_ARG_TYPE (arg
)))
3244 parm
.frame_type
= actual_type
;
3247 parm
.frame_type
= actual_type
;
3249 parm
.trivial_dtor
= TYPE_HAS_TRIVIAL_DESTRUCTOR (parm
.frame_type
);
3250 tree pname
= DECL_NAME (arg
);
3251 char *buf
= xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname
));
3252 parm
.field_id
= coro_make_frame_entry
3253 (&field_list
, buf
, actual_type
, DECL_SOURCE_LOCATION (arg
));
3257 /* We want to record every instance of param's use, so don't include
3258 a 'visited' hash_set on the tree walk, but only record a containing
3260 hash_set
<tree
*> visited
;
3261 param_frame_data param_data
3262 = {&field_list
, param_uses
, &visited
, fn_start
, false};
3263 cp_walk_tree (&fnbody
, register_param_uses
, ¶m_data
, NULL
);
3266 /* Initial suspend is mandated. */
3267 tree init_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.is",
3268 initial_suspend_type
, fn_start
);
3270 register_await_info (initial_await
, initial_suspend_type
, init_susp_name
);
3272 /* Now insert the data for any body await points, at this time we also need
3273 to promote any temporaries that are captured by reference (to regular
3274 vars) they will get added to the coro frame along with other locals. */
3275 susp_frame_data body_aw_points
3276 = {&field_list
, handle_type
, hash_set
<tree
> (), NULL
, NULL
, 0, 0, false};
3277 body_aw_points
.to_replace
= make_tree_vector ();
3278 body_aw_points
.block_stack
= make_tree_vector ();
3279 cp_walk_tree (&fnbody
, await_statement_walker
, &body_aw_points
, NULL
);
3281 /* Final suspend is mandated. */
3282 tree fin_susp_name
= coro_make_frame_entry (&field_list
, "__aw_s.fs",
3283 final_suspend_type
, fn_start
);
3285 register_await_info (final_await
, final_suspend_type
, fin_susp_name
);
3287 /* 4. Now make space for local vars, this is conservative again, and we
3288 would expect to delete unused entries later. */
3289 hash_map
<tree
, local_var_info
> local_var_uses
;
3290 local_vars_frame_data local_vars_data
3291 = {&field_list
, &local_var_uses
, 0, 0, fn_start
, false, false};
3292 cp_walk_tree (&fnbody
, register_local_var_uses
, &local_vars_data
, NULL
);
3294 /* Tie off the struct for now, so that we can build offsets to the
3296 TYPE_FIELDS (coro_frame_type
) = field_list
;
3297 TYPE_BINFO (coro_frame_type
) = make_tree_binfo (0);
3298 BINFO_OFFSET (TYPE_BINFO (coro_frame_type
)) = size_zero_node
;
3299 BINFO_TYPE (TYPE_BINFO (coro_frame_type
)) = coro_frame_type
;
3301 coro_frame_type
= finish_struct (coro_frame_type
, NULL_TREE
);
3304 /* Now build the ramp function pieces. */
3305 tree ramp_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3306 add_stmt (ramp_bind
);
3307 tree ramp_body
= push_stmt_list ();
3308 tree empty_list
= build_empty_stmt (fn_start
);
3310 tree coro_fp
= build_lang_decl (VAR_DECL
, get_identifier ("coro.frameptr"),
3312 tree varlist
= coro_fp
;
3314 /* Collected the scope vars we need ... only one for now. */
3315 BIND_EXPR_VARS (ramp_bind
) = nreverse (varlist
);
3317 /* We're now going to create a new top level scope block for the ramp
3319 tree top_block
= make_node (BLOCK
);
3321 BIND_EXPR_BLOCK (ramp_bind
) = top_block
;
3322 BLOCK_VARS (top_block
) = BIND_EXPR_VARS (ramp_bind
);
3323 BLOCK_SUBBLOCKS (top_block
) = NULL_TREE
;
3325 /* The decl_expr for the coro frame pointer, initialize to zero so that we
3326 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
3327 directly apparently). This avoids a "used uninitialized" warning. */
3328 tree r
= build_stmt (fn_start
, DECL_EXPR
, coro_fp
);
3329 tree zeroinit
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3330 r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, zeroinit
);
3331 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3334 /* The CO_FRAME internal function is a mechanism to allow the middle end
3335 to adjust the allocation in response to optimisations. We provide the
3336 current conservative estimate of the frame size (as per the current)
3338 tree frame_size
= TYPE_SIZE_UNIT (coro_frame_type
);
3340 = build_call_expr_internal_loc (fn_start
, IFN_CO_FRAME
, size_type_node
, 2,
3341 frame_size
, coro_fp
);
3343 /* n4849 [dcl.fct.def.coroutine] / 10 (part1)
3344 The unqualified-id get_return_object_on_allocation_failure is looked up
3345 in the scope of the promise type by class member access lookup. */
3348 = lookup_promise_method (orig
, coro_gro_on_allocation_fail_identifier
,
3349 fn_start
, /*musthave=*/false);
3351 tree grooaf
= NULL_TREE
;
3352 tree dummy_promise
= build_dummy_object (get_coroutine_promise_type (orig
));
3354 /* We don't require this, so lookup_promise_method can return NULL... */
3355 if (grooaf_meth
&& BASELINK_P (grooaf_meth
))
3357 /* ... but, if the lookup succeeds, then the function must be
3359 build_new_method_call () wants a valid pointer to (an empty) args
3360 list in this case. */
3361 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3362 grooaf
= build_new_method_call (dummy_promise
, grooaf_meth
, &args
,
3363 NULL_TREE
, LOOKUP_NORMAL
, NULL
,
3364 tf_warning_or_error
);
3365 release_tree_vector (args
);
3368 /* Allocate the frame, this has several possibilities:
3369 n4849 [dcl.fct.def.coroutine] / 9 (part 1)
3370 The allocation function’s name is looked up in the scope of the promise
3371 type. It's not a failure for it to be absent see part 4, below. */
3372 tree nwname
= ovl_op_identifier (false, NEW_EXPR
);
3373 tree fns
= lookup_promise_method (orig
, nwname
, fn_start
,
3374 /*musthave=*/false);
3375 tree new_fn
= NULL_TREE
;
3376 if (fns
&& BASELINK_P (fns
))
3378 /* n4849 [dcl.fct.def.coroutine] / 9 (part 2)
3379 If the lookup finds an allocation function in the scope of the promise
3380 type, overload resolution is performed on a function call created by
3381 assembling an argument list. The first argument is the amount of space
3382 requested, and has type std::size_t. The succeeding arguments are
3383 those of the original function. */
3384 vec
<tree
, va_gc
> *args
= make_tree_vector ();
3385 vec_safe_push (args
, resizeable
); /* Space needed. */
3386 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3387 arg
= DECL_CHAIN (arg
))
3388 vec_safe_push (args
, arg
);
3390 /* We might need to check that the provided function is nothrow. */
3392 /* Failure is OK for the first attempt. */
3393 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
, NULL
,
3394 LOOKUP_NORMAL
, &func
, tf_none
);
3395 release_tree_vector (args
);
3397 if (!new_fn
|| new_fn
== error_mark_node
)
3399 /* n4849 [dcl.fct.def.coroutine] / 9 (part 3)
3400 If no viable function is found, overload resolution is performed
3401 again on a function call created by passing just the amount of
3402 space required as an argument of type std::size_t. */
3403 args
= make_tree_vector ();
3404 vec_safe_push (args
, resizeable
); /* Space needed. */
3405 new_fn
= build_new_method_call (dummy_promise
, fns
, &args
,
3406 NULL_TREE
, LOOKUP_NORMAL
, &func
,
3408 release_tree_vector (args
);
3411 /* However, if the initial lookup succeeded, then one of these two
3412 options must be available. */
3413 if (!new_fn
|| new_fn
== error_mark_node
)
3415 error_at (fn_start
, "%qE is provided by %qT but is not usable with"
3416 " the function signature %qD", nwname
, promise_type
, orig
);
3417 new_fn
= error_mark_node
;
3419 else if (grooaf
&& !TYPE_NOTHROW_P (TREE_TYPE (func
)))
3420 error_at (fn_start
, "%qE is provided by %qT but %qE is not marked"
3421 " %<throw()%> or %<noexcept%>", grooaf
, promise_type
, nwname
);
3425 /* n4849 [dcl.fct.def.coroutine] / 9 (part 4)
3426 If this lookup fails, the allocation function’s name is looked up in
3427 the global scope. */
3429 vec
<tree
, va_gc
> *args
;
3430 /* build_operator_new_call () will insert size needed as element 0 of
3431 this, and we might need to append the std::nothrow constant. */
3432 vec_alloc (args
, 2);
3436 /* n4849 [dcl.fct.def.coroutine] / 10 (part 2)
3437 If any declarations (of the get return on allocation fail) are
3438 found, then the result of a call to an allocation function used
3439 to obtain storage for the coroutine state is assumed to return
3440 nullptr if it fails to obtain storage and, if a global allocation
3441 function is selected, the ::operator new(size_t, nothrow_t) form
3442 is used. The allocation function used in this case shall have a
3443 non-throwing noexcept-specification. So we need std::nothrow. */
3444 tree std_nt
= lookup_qualified_name (std_node
,
3445 get_identifier ("nothrow"),
3446 0, /*complain=*/true, false);
3447 vec_safe_push (args
, std_nt
);
3450 /* If we get to this point, we must succeed in looking up the global
3451 operator new for the params provided. Extract a simplified version
3452 of the machinery from build_operator_new_call. This can update the
3455 new_fn
= build_operator_new_call (nwname
, &args
, &frame_size
, &cookie
,
3457 /*size_check=*/NULL
, /*fn=*/NULL
,
3458 tf_warning_or_error
);
3459 resizeable
= build_call_expr_internal_loc
3460 (fn_start
, IFN_CO_FRAME
, size_type_node
, 2, frame_size
, coro_fp
);
3461 CALL_EXPR_ARG (new_fn
, 0) = resizeable
;
3463 release_tree_vector (args
);
3466 tree allocated
= build1 (CONVERT_EXPR
, coro_frame_ptr
, new_fn
);
3467 r
= build2 (INIT_EXPR
, TREE_TYPE (coro_fp
), coro_fp
, allocated
);
3468 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3471 /* If the user provided a method to return an object on alloc fail, then
3472 check the returned pointer and call the func if it's null.
3473 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
3477 /* n4849 [dcl.fct.def.coroutine] / 10 (part 3)
3478 If the allocation function returns nullptr,the coroutine returns
3479 control to the caller of the coroutine and the return value is
3480 obtained by a call to T::get_return_object_on_allocation_failure(),
3481 where T is the promise type. */
3483 = create_named_label_with_ctx (fn_start
, "coro.frame.active",
3485 tree early_ret_list
= NULL
;
3486 /* init the retval using the user's func. */
3487 r
= build2 (INIT_EXPR
, TREE_TYPE (DECL_RESULT (orig
)), DECL_RESULT (orig
),
3489 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3490 append_to_statement_list (r
, &early_ret_list
);
3491 /* We know it's the correct type. */
3492 r
= DECL_RESULT (orig
);
3493 r
= build_stmt (fn_start
, RETURN_EXPR
, r
);
3494 TREE_NO_WARNING (r
) |= 1;
3495 r
= maybe_cleanup_point_expr_void (r
);
3496 append_to_statement_list (r
, &early_ret_list
);
3498 tree goto_st
= NULL
;
3499 r
= build1 (GOTO_EXPR
, void_type_node
, cfra_label
);
3500 append_to_statement_list (r
, &goto_st
);
3502 tree ckk
= build1 (CONVERT_EXPR
, coro_frame_ptr
, integer_zero_node
);
3503 tree ckz
= build2 (EQ_EXPR
, boolean_type_node
, coro_fp
, ckk
);
3504 r
= build3 (COND_EXPR
, void_type_node
, ckz
, early_ret_list
, empty_list
);
3507 cfra_label
= build_stmt (fn_start
, LABEL_EXPR
, cfra_label
);
3508 add_stmt (cfra_label
);
3511 /* deref the frame pointer, to use in member access code. */
3512 tree deref_fp
= build_x_arrow (fn_start
, coro_fp
, tf_warning_or_error
);
3514 /* For now, once allocation has succeeded we always assume that this needs
3515 destruction, there's no impl. for frame allocation elision. */
3517 = lookup_member (coro_frame_type
, fnf_name
, 1, 0, tf_warning_or_error
);
3518 tree fnf_x
= build_class_member_access_expr (deref_fp
, fnf_m
, NULL_TREE
,
3519 false, tf_warning_or_error
);
3520 r
= build2 (INIT_EXPR
, boolean_type_node
, fnf_x
, boolean_true_node
);
3521 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3524 /* Put the resumer and destroyer functions in. */
3526 tree actor_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, actor
);
3528 = lookup_member (coro_frame_type
, resume_name
,
3529 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
3530 tree resume_x
= build_class_member_access_expr (deref_fp
, resume_m
, NULL_TREE
,
3531 false, tf_warning_or_error
);
3532 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, resume_x
, actor_addr
);
3533 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3536 tree destroy_addr
= build1 (ADDR_EXPR
, act_des_fn_ptr
, destroy
);
3538 = lookup_member (coro_frame_type
, destroy_name
,
3539 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
3541 = build_class_member_access_expr (deref_fp
, destroy_m
, NULL_TREE
, false,
3542 tf_warning_or_error
);
3543 r
= build2_loc (fn_start
, INIT_EXPR
, act_des_fn_ptr
, destroy_x
, destroy_addr
);
3544 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3547 /* n4849 [dcl.fct.def.coroutine] /13
3548 When a coroutine is invoked, a copy is created for each coroutine
3549 parameter. Each such copy is an object with automatic storage duration
3550 that is direct-initialized from an lvalue referring to the corresponding
3551 parameter if the parameter is an lvalue reference, and from an xvalue
3552 referring to it otherwise. A reference to a parameter in the function-
3553 body of the coroutine and in the call to the coroutine promise
3554 constructor is replaced by a reference to its copy. */
3556 vec
<tree
, va_gc
> *promise_args
= NULL
; /* So that we can adjust refs. */
3558 /* The initialization and destruction of each parameter copy occurs in the
3559 context of the called coroutine. Initializations of parameter copies are
3560 sequenced before the call to the coroutine promise constructor and
3561 indeterminately sequenced with respect to each other. The lifetime of
3562 parameter copies ends immediately after the lifetime of the coroutine
3563 promise object ends. */
3565 vec
<tree
, va_gc
> *param_dtor_list
= NULL
;
3567 if (DECL_ARGUMENTS (orig
))
3569 promise_args
= make_tree_vector ();
3570 for (tree arg
= DECL_ARGUMENTS (orig
); arg
!= NULL
;
3571 arg
= DECL_CHAIN (arg
))
3574 param_info
&parm
= param_uses
->get_or_insert (arg
, &existed
);
3576 tree fld_ref
= lookup_member (coro_frame_type
, parm
.field_id
,
3577 /*protect=*/1, /*want_type=*/0,
3578 tf_warning_or_error
);
3580 = build_class_member_access_expr (deref_fp
, fld_ref
, NULL_TREE
,
3581 false, tf_warning_or_error
);
3583 /* Add this to the promise CTOR arguments list, accounting for
3586 vec_safe_push (promise_args
, fld_idx
);
3587 else if (parm
.rv_ref
)
3588 vec_safe_push (promise_args
, rvalue (fld_idx
));
3590 vec_safe_push (promise_args
, arg
);
3592 if (TYPE_NEEDS_CONSTRUCTING (parm
.frame_type
))
3594 vec
<tree
, va_gc
> *p_in
;
3596 && classtype_has_non_deleted_move_ctor (parm
.frame_type
)
3597 && !classtype_has_non_deleted_copy_ctor (parm
.frame_type
))
3598 p_in
= make_tree_vector_single (rvalue (arg
));
3600 p_in
= make_tree_vector_single (arg
);
3601 /* Construct in place or move as relevant. */
3602 r
= build_special_member_call (fld_idx
, complete_ctor_identifier
,
3603 &p_in
, parm
.frame_type
,
3605 tf_warning_or_error
);
3606 release_tree_vector (p_in
);
3611 r
= convert_from_reference (arg
);
3612 else if (!same_type_p (parm
.frame_type
, DECL_ARG_TYPE (arg
)))
3613 r
= build1_loc (DECL_SOURCE_LOCATION (arg
), CONVERT_EXPR
,
3614 parm
.frame_type
, arg
);
3617 r
= build_modify_expr (fn_start
, fld_idx
, parm
.frame_type
,
3618 INIT_EXPR
, DECL_SOURCE_LOCATION (arg
), r
,
3621 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3623 if (!parm
.trivial_dtor
)
3625 if (param_dtor_list
== NULL
)
3626 param_dtor_list
= make_tree_vector ();
3627 vec_safe_push (param_dtor_list
, parm
.field_id
);
3632 /* Set up the promise. */
3634 = lookup_member (coro_frame_type
, promise_name
,
3635 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
3637 tree p
= build_class_member_access_expr (deref_fp
, promise_m
, NULL_TREE
,
3638 false, tf_warning_or_error
);
3640 if (TYPE_NEEDS_CONSTRUCTING (promise_type
))
3642 /* Do a placement new constructor for the promise type (we never call
3643 the new operator, just the constructor on the object in place in the
3646 First try to find a constructor with the same parameter list as the
3647 original function (if it has params), failing that find a constructor
3648 with no parameter list. */
3650 if (DECL_ARGUMENTS (orig
))
3652 r
= build_special_member_call (p
, complete_ctor_identifier
,
3653 &promise_args
, promise_type
,
3654 LOOKUP_NORMAL
, tf_none
);
3655 release_tree_vector (promise_args
);
3660 if (r
== NULL_TREE
|| r
== error_mark_node
)
3661 r
= build_special_member_call (p
, complete_ctor_identifier
, NULL
,
3662 promise_type
, LOOKUP_NORMAL
,
3663 tf_warning_or_error
);
3665 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3669 /* Set up a new bind context for the GRO. */
3670 tree gro_context_bind
= build3 (BIND_EXPR
, void_type_node
, NULL
, NULL
, NULL
);
3671 /* Make and connect the scope blocks. */
3672 tree gro_block
= make_node (BLOCK
);
3673 BLOCK_SUPERCONTEXT (gro_block
) = top_block
;
3674 BLOCK_SUBBLOCKS (top_block
) = gro_block
;
3675 BIND_EXPR_BLOCK (gro_context_bind
) = gro_block
;
3676 add_stmt (gro_context_bind
);
3678 tree gro_meth
= lookup_promise_method (orig
,
3679 coro_get_return_object_identifier
,
3680 fn_start
, /*musthave=*/true );
3682 = build_new_method_call (p
, gro_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
3683 tf_warning_or_error
);
3684 /* Without a return object we haven't got much clue what's going on. */
3685 if (get_ro
== error_mark_node
)
3687 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
3688 DECL_SAVED_TREE (orig
) = newbody
;
3692 tree gro_context_body
= push_stmt_list ();
3693 tree gro
, gro_bind_vars
;
3694 if (same_type_p (TREE_TYPE (get_ro
), fn_return_type
))
3696 gro
= DECL_RESULT (orig
);
3697 gro_bind_vars
= NULL_TREE
; /* We don't need a separate var. */
3701 gro
= build_lang_decl (VAR_DECL
, get_identifier ("coro.gro"),
3702 TREE_TYPE (TREE_OPERAND (get_ro
, 0)));
3703 DECL_CONTEXT (gro
) = current_scope ();
3704 r
= build_stmt (fn_start
, DECL_EXPR
, gro
);
3706 gro_bind_vars
= gro
; /* We need a temporary var. */
3709 /* Initialize our actual var. */
3710 r
= build2_loc (fn_start
, INIT_EXPR
, TREE_TYPE (gro
), gro
, get_ro
);
3711 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3714 /* Initialize the resume_idx_name to 0, meaning "not started". */
3716 = lookup_member (coro_frame_type
, resume_idx_name
,
3717 /*protect=*/1, /*want_type=*/0, tf_warning_or_error
);
3719 = build_class_member_access_expr (deref_fp
, resume_idx_m
, NULL_TREE
, false,
3720 tf_warning_or_error
);
3721 r
= build_int_cst (short_unsigned_type_node
, 0);
3722 r
= build2_loc (fn_start
, INIT_EXPR
, short_unsigned_type_node
, resume_idx
, r
);
3723 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3726 /* Initialize 'initial-await-resume-called' as per
3727 [dcl.fct.def.coroutine] / 5.3 */
3729 = lookup_member (coro_frame_type
, iarc_name
, 1, 0, tf_warning_or_error
);
3730 tree i_a_r_c
= build_class_member_access_expr (deref_fp
, i_a_r_c_m
,
3732 tf_warning_or_error
);
3733 r
= build2 (INIT_EXPR
, boolean_type_node
, i_a_r_c
, boolean_false_node
);
3734 r
= coro_build_cvt_void_expr_stmt (r
, fn_start
);
3737 /* So .. call the actor .. */
3738 r
= build_call_expr_loc (fn_start
, actor
, 1, coro_fp
);
3739 r
= maybe_cleanup_point_expr_void (r
);
3742 /* Switch to using 'input_location' as the loc, since we're now more
3743 logically doing things related to the end of the function. */
3745 /* The ramp is done, we just need the return value. */
3746 if (!same_type_p (TREE_TYPE (gro
), fn_return_type
))
3748 /* construct the return value with a single GRO param. */
3749 vec
<tree
, va_gc
> *args
= make_tree_vector_single (gro
);
3750 r
= build_special_member_call (DECL_RESULT (orig
),
3751 complete_ctor_identifier
, &args
,
3752 fn_return_type
, LOOKUP_NORMAL
,
3753 tf_warning_or_error
);
3754 r
= coro_build_cvt_void_expr_stmt (r
, input_location
);
3756 release_tree_vector (args
);
3758 /* Else the GRO is the return and we already built it in place. */
3761 r
= check_return_expr (DECL_RESULT (orig
), &no_warning
);
3762 if (error_operand_p (r
) && warn_return_type
)
3763 /* Suppress -Wreturn-type for the ramp. */
3764 TREE_NO_WARNING (orig
) = true;
3766 r
= build_stmt (input_location
, RETURN_EXPR
, DECL_RESULT (orig
));
3767 TREE_NO_WARNING (r
) |= no_warning
;
3768 r
= maybe_cleanup_point_expr_void (r
);
3770 BIND_EXPR_VARS (gro_context_bind
) = gro_bind_vars
;
3771 BIND_EXPR_BODY (gro_context_bind
) = pop_stmt_list (gro_context_body
);
3772 BIND_EXPR_BODY (ramp_bind
) = pop_stmt_list (ramp_body
);
3774 /* We know the "real" promise and have a frame layout with a slot for each
3775 suspend point, so we can build an actor function (which contains the
3776 functionality for both 'resume' and 'destroy').
3778 wrap the function body in a try {} catch (...) {} block, if exceptions
3781 /* First make a new block for the body - that will be embedded in the
3782 re-written function. */
3783 tree first
= expr_first (fnbody
);
3784 bool orig_fn_has_outer_bind
= false;
3785 tree replace_blk
= NULL_TREE
;
3786 if (first
&& TREE_CODE (first
) == BIND_EXPR
)
3788 orig_fn_has_outer_bind
= true;
3789 tree block
= BIND_EXPR_BLOCK (first
);
3790 replace_blk
= make_node (BLOCK
);
3791 if (block
) /* missing block is probably an error. */
3793 gcc_assert (BLOCK_SUPERCONTEXT (block
) == NULL_TREE
);
3794 gcc_assert (BLOCK_CHAIN (block
) == NULL_TREE
);
3795 BLOCK_VARS (replace_blk
) = BLOCK_VARS (block
);
3796 BLOCK_SUBBLOCKS (replace_blk
) = BLOCK_SUBBLOCKS (block
);
3797 for (tree b
= BLOCK_SUBBLOCKS (replace_blk
); b
; b
= BLOCK_CHAIN (b
))
3798 BLOCK_SUPERCONTEXT (b
) = replace_blk
;
3800 BIND_EXPR_BLOCK (first
) = replace_blk
;
3803 /* actor's version of the promise. */
3804 tree actor_frame
= build1_loc (fn_start
, INDIRECT_REF
, coro_frame_type
,
3805 DECL_ARGUMENTS (actor
));
3806 tree ap_m
= lookup_member (coro_frame_type
, get_identifier ("__p"), 1, 0,
3807 tf_warning_or_error
);
3808 tree ap
= build_class_member_access_expr (actor_frame
, ap_m
, NULL_TREE
,
3809 false, tf_warning_or_error
);
3811 /* Now we've built the promise etc, process fnbody for co_returns.
3812 We want the call to return_void () below and it has no params so
3813 we can create it once here.
3814 Calls to return_value () will have to be checked and created as
3817 tree return_void
= NULL_TREE
;
3819 = lookup_promise_method (orig
, coro_return_void_identifier
, fn_start
,
3820 /*musthave=*/false);
3821 if (rvm
&& rvm
!= error_mark_node
)
3823 = build_new_method_call (ap
, rvm
, NULL
, NULL_TREE
, LOOKUP_NORMAL
, NULL
,
3824 tf_warning_or_error
);
3826 /* [stmt.return.coroutine] (2.2 : 3) if p.return_void() is a valid
3827 expression, flowing off the end of a coroutine is equivalent to
3828 co_return; otherwise UB.
3829 We just inject the call to p.return_void() here, and fall through to
3830 the final_suspend: label (eliding the goto). If the function body has
3831 a co_return, then this statement will be unreachable and DCEd. */
3832 if (return_void
!= NULL_TREE
)
3834 tree append
= push_stmt_list ();
3836 add_stmt (return_void
);
3837 fnbody
= pop_stmt_list(append
);
3840 if (flag_exceptions
)
3843 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
3844 fn_start
, /*musthave=*/true);
3845 /* Build promise.unhandled_exception(); */
3847 = build_new_method_call (ap
, ueh_meth
, NULL
, NULL_TREE
, LOOKUP_NORMAL
,
3848 NULL
, tf_warning_or_error
);
3850 /* The try block is just the original function, there's no real
3851 need to call any function to do this. */
3852 fnbody
= build_stmt (fn_start
, TRY_BLOCK
, fnbody
, NULL_TREE
);
3853 TRY_HANDLERS (fnbody
) = push_stmt_list ();
3854 /* Mimic what the parser does for the catch. */
3855 tree handler
= begin_handler ();
3856 finish_handler_parms (NULL_TREE
, handler
); /* catch (...) */
3858 /* Get the initial await resume called value. */
3859 tree i_a_r_c
= build_class_member_access_expr (actor_frame
, i_a_r_c_m
,
3861 tf_warning_or_error
);
3862 tree not_iarc_if
= begin_if_stmt ();
3863 tree not_iarc
= build1_loc (fn_start
, TRUTH_NOT_EXPR
,
3864 boolean_type_node
, i_a_r_c
);
3865 finish_if_stmt_cond (not_iarc
, not_iarc_if
);
3866 /* If the initial await resume called value is false, rethrow... */
3867 tree rethrow
= build_throw (fn_start
, NULL_TREE
);
3868 TREE_NO_WARNING (rethrow
) = true;
3869 finish_expr_stmt (rethrow
);
3870 finish_then_clause (not_iarc_if
);
3871 tree iarc_scope
= IF_SCOPE (not_iarc_if
);
3872 IF_SCOPE (not_iarc_if
) = NULL
;
3873 not_iarc_if
= do_poplevel (iarc_scope
);
3874 add_stmt (not_iarc_if
);
3875 /* ... else call the promise unhandled exception method. */
3876 ueh
= maybe_cleanup_point_expr_void (ueh
);
3878 finish_handler (handler
);
3879 TRY_HANDLERS (fnbody
) = pop_stmt_list (TRY_HANDLERS (fnbody
));
3880 /* If the function starts with a BIND_EXPR, then we need to create
3881 one here to contain the try-catch and to link up the scopes. */
3882 if (orig_fn_has_outer_bind
)
3884 fnbody
= build3 (BIND_EXPR
, void_type_node
, NULL
, fnbody
, NULL
);
3885 /* Make and connect the scope blocks. */
3886 tree tcb_block
= make_node (BLOCK
);
3887 /* .. and connect it here. */
3888 BLOCK_SUPERCONTEXT (replace_blk
) = tcb_block
;
3889 BLOCK_SUBBLOCKS (tcb_block
) = replace_blk
;
3890 BIND_EXPR_BLOCK (fnbody
) = tcb_block
;
3895 /* We still try to look for the promise method and warn if it's not
3898 = lookup_promise_method (orig
, coro_unhandled_exception_identifier
,
3899 fn_start
, /*musthave=*/false);
3900 if (!ueh_meth
|| ueh_meth
== error_mark_node
)
3901 warning_at (fn_start
, 0, "no member named %qE in %qT",
3902 coro_unhandled_exception_identifier
,
3903 get_coroutine_promise_type (orig
));
3905 /* Else we don't check and don't care if the method is missing. */
3907 /* Start to build the final functions.
3909 We push_deferring_access_checks to avoid these routines being seen as
3910 nested by the middle end; we are doing the outlining here. */
3912 push_deferring_access_checks (dk_no_check
);
3915 build_actor_fn (fn_start
, coro_frame_type
, actor
, fnbody
, orig
, param_uses
,
3916 &local_var_uses
, param_dtor_list
, initial_await
, final_await
,
3917 body_aw_points
.count
, frame_size
);
3920 build_destroy_fn (fn_start
, coro_frame_type
, destroy
, actor
);
3922 pop_deferring_access_checks ();
3924 DECL_SAVED_TREE (orig
) = newbody
;
3925 /* Link our new functions into the list. */
3926 TREE_CHAIN (destroy
) = TREE_CHAIN (orig
);
3927 TREE_CHAIN (actor
) = destroy
;
3928 TREE_CHAIN (orig
) = actor
;
3931 *destroyer
= destroy
;
3933 delete suspend_points
;
3934 suspend_points
= NULL
;
3938 #include "gt-cp-coroutines.h"