1 /* coroutine-specific state, expansions and tests.
2 
3    Copyright (C) 2018-2021 Free Software Foundation, Inc.
4 
5  Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.
6 
7 This file is part of GCC.
8 
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
12 version.
13 
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
17 for more details.
18 
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/>.  */
22 
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "target.h"
27 #include "cp-tree.h"
28 #include "stringpool.h"
29 #include "stmt.h"
30 #include "stor-layout.h"
31 #include "tree-iterator.h"
32 #include "tree.h"
33 #include "gcc-rich-location.h"
34 #include "hash-map.h"
35 
36 static bool coro_promise_type_found_p (tree, location_t);
37 
38 /* GCC C++ coroutines implementation.
39 
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.
42 
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).
46 
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.
53 
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.
58 
59   The functions in this file carry out the necessary analysis of, and
60   transforms to, the AST to perform this.
61 
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.
64 
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.
71 
72   Each of the keywords will expand to a code sequence (although co_yield is
73   just syntactic sugar for a co_await).
74 
75   We defer the analysis and transformation until template expansion is
76   complete so that we have complete types at that time.  */
77 
78 
79 /* The state that we collect during parsing (and template expansion) for
80    a coroutine.  */
81 
82 struct GTY((for_user)) coroutine_info
83 {
84   tree function_decl; /* The original function decl.  */
85   tree actor_decl;    /* The synthesized actor function.  */
86   tree destroy_decl;  /* The synthesized destroy function.  */
87   tree promise_type;  /* The cached promise type for this function.  */
88   tree handle_type;   /* The cached coroutine handle for this function.  */
89   tree self_h_proxy;  /* A handle instance that is used as the proxy for the
90 			 one that will eventually be allocated in the coroutine
91 			 frame.  */
92   tree promise_proxy; /* Likewise, a proxy promise instance.  */
93   tree return_void;   /* The expression for p.return_void() if it exists.  */
94   location_t first_coro_keyword; /* The location of the keyword that made this
95 				    function into a coroutine.  */
96   /* Flags to avoid repeated errors for per-function issues.  */
97   bool coro_ret_type_error_emitted;
98   bool coro_promise_error_emitted;
99   bool coro_co_return_error_emitted;
100 };
101 
102 struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
103 {
104   typedef tree compare_type; /* We only compare the function decl.  */
105   static inline hashval_t hash (coroutine_info *);
106   static inline hashval_t hash (const compare_type &);
107   static inline bool equal (coroutine_info *, coroutine_info *);
108   static inline bool equal (coroutine_info *, const compare_type &);
109 };
110 
111 /* This table holds all the collected coroutine state for coroutines in
112    the current translation unit.  */
113 
114 static GTY (()) hash_table<coroutine_info_hasher> *coroutine_info_table;
115 
116 /* We will initialize state lazily.  */
117 static bool coro_initialized = false;
118 
119 /* Return a hash value for the entry pointed to by INFO.
120    The compare type is a tree, but the only trees we are going use are
121    function decls.  We use the DECL_UID as the hash value since that is
122    stable across PCH.  */
123 
124 hashval_t
hash(coroutine_info * info)125 coroutine_info_hasher::hash (coroutine_info *info)
126 {
127   return DECL_UID (info->function_decl);
128 }
129 
130 /* Return a hash value for the compare value COMP.  */
131 
132 hashval_t
hash(const compare_type & comp)133 coroutine_info_hasher::hash (const compare_type& comp)
134 {
135   return DECL_UID (comp);
136 }
137 
138 /* Return true if the entries pointed to by LHS and RHS are for the
139    same coroutine.  */
140 
141 bool
equal(coroutine_info * lhs,coroutine_info * rhs)142 coroutine_info_hasher::equal (coroutine_info *lhs, coroutine_info *rhs)
143 {
144   return lhs->function_decl == rhs->function_decl;
145 }
146 
147 bool
equal(coroutine_info * lhs,const compare_type & rhs)148 coroutine_info_hasher::equal (coroutine_info *lhs, const compare_type& rhs)
149 {
150   return lhs->function_decl == rhs;
151 }
152 
153 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
154    entry does not yet exist.  */
155 
156 coroutine_info *
get_or_insert_coroutine_info(tree fn_decl)157 get_or_insert_coroutine_info (tree fn_decl)
158 {
159   gcc_checking_assert (coroutine_info_table != NULL);
160 
161   coroutine_info **slot = coroutine_info_table->find_slot_with_hash
162     (fn_decl, coroutine_info_hasher::hash (fn_decl), INSERT);
163 
164   if (*slot == NULL)
165     {
166       *slot = new (ggc_cleared_alloc<coroutine_info> ()) coroutine_info ();
167       (*slot)->function_decl = fn_decl;
168     }
169 
170   return *slot;
171 }
172 
173 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist.  */
174 
175 coroutine_info *
get_coroutine_info(tree fn_decl)176 get_coroutine_info (tree fn_decl)
177 {
178   if (coroutine_info_table == NULL)
179     return NULL;
180 
181   coroutine_info **slot = coroutine_info_table->find_slot_with_hash
182     (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
183   if (slot)
184     return *slot;
185   return NULL;
186 }
187 
188 /* We will lazily create all the identifiers that are used by coroutines
189    on the first attempt to lookup the traits.  */
190 
191 /* Identifiers that are used by all coroutines.  */
192 
193 static GTY(()) tree coro_traits_identifier;
194 static GTY(()) tree coro_handle_identifier;
195 static GTY(()) tree coro_promise_type_identifier;
196 
197 /* Required promise method name identifiers.  */
198 
199 static GTY(()) tree coro_await_transform_identifier;
200 static GTY(()) tree coro_initial_suspend_identifier;
201 static GTY(()) tree coro_final_suspend_identifier;
202 static GTY(()) tree coro_return_void_identifier;
203 static GTY(()) tree coro_return_value_identifier;
204 static GTY(()) tree coro_yield_value_identifier;
205 static GTY(()) tree coro_resume_identifier;
206 static GTY(()) tree coro_address_identifier;
207 static GTY(()) tree coro_from_address_identifier;
208 static GTY(()) tree coro_get_return_object_identifier;
209 static GTY(()) tree coro_gro_on_allocation_fail_identifier;
210 static GTY(()) tree coro_unhandled_exception_identifier;
211 
212 /* Awaitable methods.  */
213 
214 static GTY(()) tree coro_await_ready_identifier;
215 static GTY(()) tree coro_await_suspend_identifier;
216 static GTY(()) tree coro_await_resume_identifier;
217 
218 /* Create the identifiers used by the coroutines library interfaces.  */
219 
220 static void
coro_init_identifiers()221 coro_init_identifiers ()
222 {
223   coro_traits_identifier = get_identifier ("coroutine_traits");
224   coro_handle_identifier = get_identifier ("coroutine_handle");
225   coro_promise_type_identifier = get_identifier ("promise_type");
226 
227   coro_await_transform_identifier = get_identifier ("await_transform");
228   coro_initial_suspend_identifier = get_identifier ("initial_suspend");
229   coro_final_suspend_identifier = get_identifier ("final_suspend");
230   coro_return_void_identifier = get_identifier ("return_void");
231   coro_return_value_identifier = get_identifier ("return_value");
232   coro_yield_value_identifier = get_identifier ("yield_value");
233   coro_resume_identifier = get_identifier ("resume");
234   coro_address_identifier = get_identifier ("address");
235   coro_from_address_identifier = get_identifier ("from_address");
236   coro_get_return_object_identifier = get_identifier ("get_return_object");
237   coro_gro_on_allocation_fail_identifier =
238     get_identifier ("get_return_object_on_allocation_failure");
239   coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
240 
241   coro_await_ready_identifier = get_identifier ("await_ready");
242   coro_await_suspend_identifier = get_identifier ("await_suspend");
243   coro_await_resume_identifier = get_identifier ("await_resume");
244 }
245 
246 /* Trees we only need to set up once.  */
247 
248 static GTY(()) tree coro_traits_templ;
249 static GTY(()) tree coro_handle_templ;
250 static GTY(()) tree void_coro_handle_type;
251 
252 /* ================= Parse, Semantics and Type checking ================= */
253 
254 /* This initial set of routines are helper for the parsing and template
255    expansion phases.
256 
257    At the completion of this, we will have completed trees for each of the
258    keywords, but making use of proxy variables for the self-handle and the
259    promise class instance.  */
260 
261 /* [coroutine.traits]
262    Lookup the coroutine_traits template decl.  */
263 
264 static tree
find_coro_traits_template_decl(location_t kw)265 find_coro_traits_template_decl (location_t kw)
266 {
267   /* If we are missing fundamental information, such as the traits, (or the
268      declaration found is not a type template), then don't emit an error for
269      every keyword in a TU, just do it once.  */
270   static bool traits_error_emitted = false;
271 
272   tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
273 					    LOOK_want::NORMAL,
274 					    /*complain=*/!traits_error_emitted);
275   if (traits_decl == error_mark_node
276       || !DECL_TYPE_TEMPLATE_P (traits_decl))
277     {
278       if (!traits_error_emitted)
279 	{
280 	  gcc_rich_location richloc (kw);
281 	  error_at (&richloc, "coroutines require a traits template; cannot"
282 		    " find %<%E::%E%>", std_node, coro_traits_identifier);
283 	  inform (&richloc, "perhaps %<#include <coroutine>%> is missing");
284 	  traits_error_emitted = true;
285 	}
286       return NULL_TREE;
287     }
288   else
289     return traits_decl;
290 }
291 
292 /*  Instantiate Coroutine traits for the function signature.  */
293 
294 static tree
instantiate_coro_traits(tree fndecl,location_t kw)295 instantiate_coro_traits (tree fndecl, location_t kw)
296 {
297   /* [coroutine.traits.primary]
298      So now build up a type list for the template <typename _R, typename...>.
299      The types are the function's arg types and _R is the function return
300      type.  */
301 
302   tree functyp = TREE_TYPE (fndecl);
303   tree arg = DECL_ARGUMENTS (fndecl);
304   tree arg_node = TYPE_ARG_TYPES (functyp);
305   tree argtypes = make_tree_vec (list_length (arg_node)-1);
306   unsigned p = 0;
307 
308   while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
309     {
310       if (is_this_parameter (arg)
311 	  || DECL_NAME (arg) == closure_identifier)
312 	{
313 	  /* We pass a reference to *this to the param preview.  */
314 	  tree ct = TREE_TYPE (TREE_TYPE (arg));
315 	  TREE_VEC_ELT (argtypes, p++) = cp_build_reference_type (ct, false);
316 	}
317       else
318 	TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
319 
320       arg_node = TREE_CHAIN (arg_node);
321       arg = DECL_CHAIN (arg);
322     }
323 
324   tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
325   SET_ARGUMENT_PACK_ARGS (argtypepack, argtypes);
326 
327   tree targ = make_tree_vec (2);
328   TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
329   TREE_VEC_ELT (targ, 1) = argtypepack;
330 
331   tree traits_class
332     = lookup_template_class (coro_traits_templ, targ,
333 			     /*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
334 			     /*entering scope=*/false, tf_warning_or_error);
335 
336   if (traits_class == error_mark_node)
337     {
338       error_at (kw, "cannot instantiate %<coroutine traits%>");
339       return NULL_TREE;
340     }
341 
342   return traits_class;
343 }
344 
345 /* [coroutine.handle] */
346 
347 static tree
find_coro_handle_template_decl(location_t kw)348 find_coro_handle_template_decl (location_t kw)
349 {
350   /* As for the coroutine traits, this error is per TU, so only emit
351     it once.  */
352   static bool coro_handle_error_emitted = false;
353   tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
354 					    LOOK_want::NORMAL,
355 					    !coro_handle_error_emitted);
356   if (handle_decl == error_mark_node
357       || !DECL_CLASS_TEMPLATE_P (handle_decl))
358     {
359       if (!coro_handle_error_emitted)
360 	error_at (kw, "coroutines require a handle class template;"
361 		  " cannot find %<%E::%E%>", std_node, coro_handle_identifier);
362       coro_handle_error_emitted = true;
363       return NULL_TREE;
364     }
365   else
366     return handle_decl;
367 }
368 
369 /* Instantiate the handle template for a given promise type.  */
370 
371 static tree
instantiate_coro_handle_for_promise_type(location_t kw,tree promise_type)372 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
373 {
374   /* So now build up a type list for the template, one entry, the promise.  */
375   tree targ = make_tree_vec (1);
376   TREE_VEC_ELT (targ, 0) = promise_type;
377   tree handle_type
378     = lookup_template_class (coro_handle_identifier, targ,
379 			     /* in_decl=*/NULL_TREE,
380 			     /* context=*/std_node,
381 			     /* entering scope=*/false, tf_warning_or_error);
382 
383   if (handle_type == error_mark_node)
384     {
385       error_at (kw, "cannot instantiate a %<coroutine handle%> for"
386 		" promise type %qT", promise_type);
387       return NULL_TREE;
388     }
389 
390   return handle_type;
391 }
392 
393 /* Look for the promise_type in the instantiated traits.  */
394 
395 static tree
find_promise_type(tree traits_class)396 find_promise_type (tree traits_class)
397 {
398   tree promise_type
399     = lookup_member (traits_class, coro_promise_type_identifier,
400 		     /* protect=*/1, /*want_type=*/true, tf_warning_or_error);
401 
402   if (promise_type)
403     promise_type
404       = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
405 
406   /* NULL_TREE on fail.  */
407   return promise_type;
408 }
409 
410 static bool
coro_promise_type_found_p(tree fndecl,location_t loc)411 coro_promise_type_found_p (tree fndecl, location_t loc)
412 {
413   gcc_assert (fndecl != NULL_TREE);
414 
415   if (!coro_initialized)
416     {
417       /* Trees we only need to create once.
418 	 Set up the identifiers we will use.  */
419       coro_init_identifiers ();
420 
421       /* Coroutine traits template.  */
422       coro_traits_templ = find_coro_traits_template_decl (loc);
423       if (coro_traits_templ == NULL_TREE)
424 	return false;
425 
426       /*  coroutine_handle<> template.  */
427       coro_handle_templ = find_coro_handle_template_decl (loc);
428       if (coro_handle_templ == NULL_TREE)
429 	return false;
430 
431       /*  We can also instantiate the void coroutine_handle<>  */
432       void_coro_handle_type =
433 	instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
434       if (void_coro_handle_type == NULL_TREE)
435 	return false;
436 
437       /* A table to hold the state, per coroutine decl.  */
438       gcc_checking_assert (coroutine_info_table == NULL);
439       coroutine_info_table =
440 	hash_table<coroutine_info_hasher>::create_ggc (11);
441 
442       if (coroutine_info_table == NULL)
443 	return false;
444 
445       coro_initialized = true;
446     }
447 
448   /* Save the coroutine data on the side to avoid the overhead on every
449      function decl tree.  */
450 
451   coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
452   /* Without this, we cannot really proceed.  */
453   gcc_checking_assert (coro_info);
454 
455   /* If we don't already have a current promise type, try to look it up.  */
456   if (coro_info->promise_type == NULL_TREE)
457     {
458       /* Get the coroutine traits template class instance for the function
459 	 signature we have - coroutine_traits <R, ...>  */
460 
461       tree templ_class = instantiate_coro_traits (fndecl, loc);
462 
463       /* Find the promise type for that.  */
464       coro_info->promise_type = find_promise_type (templ_class);
465 
466       /* If we don't find it, punt on the rest.  */
467       if (coro_info->promise_type == NULL_TREE)
468 	{
469 	  if (!coro_info->coro_promise_error_emitted)
470 	    error_at (loc, "unable to find the promise type for"
471 		      " this coroutine");
472 	  coro_info->coro_promise_error_emitted = true;
473 	  return false;
474 	}
475 
476       /* Test for errors in the promise type that can be determined now.  */
477       tree has_ret_void = lookup_member (coro_info->promise_type,
478 					 coro_return_void_identifier,
479 					 /*protect=*/1, /*want_type=*/0,
480 					 tf_none);
481       tree has_ret_val = lookup_member (coro_info->promise_type,
482 					coro_return_value_identifier,
483 					/*protect=*/1, /*want_type=*/0,
484 					tf_none);
485       if (has_ret_void && has_ret_val)
486 	{
487 	  location_t ploc = DECL_SOURCE_LOCATION (fndecl);
488 	  if (!coro_info->coro_co_return_error_emitted)
489 	    error_at (ploc, "the coroutine promise type %qT declares both"
490 		      " %<return_value%> and %<return_void%>",
491 		      coro_info->promise_type);
492 	  inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_void)),
493 		  "%<return_void%> declared here");
494 	  inform (DECL_SOURCE_LOCATION (BASELINK_FUNCTIONS (has_ret_val)),
495 		  "%<return_value%> declared here");
496 	  coro_info->coro_co_return_error_emitted = true;
497 	  return false;
498 	}
499 
500       /* Try to find the handle type for the promise.  */
501       tree handle_type =
502 	instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
503       if (handle_type == NULL_TREE)
504 	return false;
505 
506       /* Complete this, we're going to use it.  */
507       coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
508 
509       /* Diagnostic would be emitted by complete_type_or_else.  */
510       if (!coro_info->handle_type)
511 	return false;
512 
513       /* Build a proxy for a handle to "self" as the param to
514 	 await_suspend() calls.  */
515       coro_info->self_h_proxy
516 	= build_lang_decl (VAR_DECL, get_identifier ("self_h.proxy"),
517 			   coro_info->handle_type);
518 
519       /* Build a proxy for the promise so that we can perform lookups.  */
520       coro_info->promise_proxy
521 	= build_lang_decl (VAR_DECL, get_identifier ("promise.proxy"),
522 			   coro_info->promise_type);
523 
524       /* Note where we first saw a coroutine keyword.  */
525       coro_info->first_coro_keyword = loc;
526     }
527 
528   return true;
529 }
530 
531 /* Map from actor or destroyer to ramp.  */
532 static GTY(()) hash_map<tree, tree> *to_ramp;
533 
534 /* Given a tree that is an actor or destroy, find the ramp function.  */
535 
536 tree
coro_get_ramp_function(tree decl)537 coro_get_ramp_function (tree decl)
538 {
539   if (!to_ramp)
540     return NULL_TREE;
541   tree *p = to_ramp->get (decl);
542   if (p)
543     return *p;
544   return NULL_TREE;
545 }
546 
547 /* Given the DECL for a ramp function (the user's original declaration) return
548    the actor function if it has been defined.  */
549 
550 tree
coro_get_actor_function(tree decl)551 coro_get_actor_function (tree decl)
552 {
553   if (coroutine_info *info = get_coroutine_info (decl))
554     return info->actor_decl;
555 
556   return NULL_TREE;
557 }
558 
559 /* Given the DECL for a ramp function (the user's original declaration) return
560    the destroy function if it has been defined.  */
561 
562 tree
coro_get_destroy_function(tree decl)563 coro_get_destroy_function (tree decl)
564 {
565   if (coroutine_info *info = get_coroutine_info (decl))
566     return info->destroy_decl;
567 
568   return NULL_TREE;
569 }
570 
571 /* These functions assumes that the caller has verified that the state for
572    the decl has been initialized, we try to minimize work here.  */
573 
574 static tree
get_coroutine_promise_type(tree decl)575 get_coroutine_promise_type (tree decl)
576 {
577   if (coroutine_info *info = get_coroutine_info (decl))
578     return info->promise_type;
579 
580   return NULL_TREE;
581 }
582 
583 static tree
get_coroutine_handle_type(tree decl)584 get_coroutine_handle_type (tree decl)
585 {
586   if (coroutine_info *info = get_coroutine_info (decl))
587     return info->handle_type;
588 
589   return NULL_TREE;
590 }
591 
592 static tree
get_coroutine_self_handle_proxy(tree decl)593 get_coroutine_self_handle_proxy (tree decl)
594 {
595   if (coroutine_info *info = get_coroutine_info (decl))
596     return info->self_h_proxy;
597 
598   return NULL_TREE;
599 }
600 
601 static tree
get_coroutine_promise_proxy(tree decl)602 get_coroutine_promise_proxy (tree decl)
603 {
604   if (coroutine_info *info = get_coroutine_info (decl))
605     return info->promise_proxy;
606 
607   return NULL_TREE;
608 }
609 
610 static tree
lookup_promise_method(tree fndecl,tree member_id,location_t loc,bool musthave)611 lookup_promise_method (tree fndecl, tree member_id, location_t loc,
612 		       bool musthave)
613 {
614   tree promise = get_coroutine_promise_type (fndecl);
615   tree pm_memb
616     = lookup_member (promise, member_id,
617 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
618   if (musthave && pm_memb == NULL_TREE)
619     {
620       error_at (loc, "no member named %qE in %qT", member_id, promise);
621       return error_mark_node;
622     }
623   return pm_memb;
624 }
625 
626 /* Build an expression of the form p.method (args) where the p is a promise
627    object for the current coroutine.
628    OBJECT is the promise object instance to use, it may be NULL, in which case
629    we will use the promise_proxy instance for this coroutine.
630    ARGS may be NULL, for empty parm lists.  */
631 
632 static tree
coro_build_promise_expression(tree fn,tree promise_obj,tree member_id,location_t loc,vec<tree,va_gc> ** args,bool musthave)633 coro_build_promise_expression (tree fn, tree promise_obj, tree member_id,
634 			       location_t loc, vec<tree, va_gc> **args,
635 			       bool musthave)
636 {
637   tree meth = lookup_promise_method (fn, member_id, loc, musthave);
638   if (meth == error_mark_node)
639     return error_mark_node;
640 
641   /* If we don't find it, and it isn't needed, an empty return is OK.  */
642   if (!meth)
643     return NULL_TREE;
644 
645   tree promise
646     = promise_obj ? promise_obj
647 		  : get_coroutine_promise_proxy (current_function_decl);
648   tree expr;
649   if (BASELINK_P (meth))
650     expr = build_new_method_call (promise, meth, args, NULL_TREE,
651 				  LOOKUP_NORMAL, NULL, tf_warning_or_error);
652   else
653     {
654       expr = build_class_member_access_expr (promise, meth, NULL_TREE,
655 					     true, tf_warning_or_error);
656       vec<tree, va_gc> *real_args;
657       if (!args)
658 	real_args = make_tree_vector ();
659       else
660 	real_args = *args;
661       expr = build_op_call (expr, &real_args, tf_warning_or_error);
662     }
663   return expr;
664 }
665 
666 /* Caching get for the expression p.return_void ().  */
667 
668 static tree
get_coroutine_return_void_expr(tree decl,location_t loc,bool musthave)669 get_coroutine_return_void_expr (tree decl, location_t loc, bool musthave)
670 {
671   if (coroutine_info *info = get_coroutine_info (decl))
672     {
673       /* If we don't have it try to build it.  */
674       if (!info->return_void)
675 	info->return_void
676 	  = coro_build_promise_expression (current_function_decl, NULL,
677 					   coro_return_void_identifier,
678 					   loc, NULL, musthave);
679       /* Don't return an error if it's an optional call.  */
680       if (!musthave && info->return_void == error_mark_node)
681 	return NULL_TREE;
682       return info->return_void;
683     }
684   return musthave ? error_mark_node : NULL_TREE;
685 }
686 
687 /* Lookup an Awaitable member, which should be await_ready, await_suspend
688    or await_resume.  */
689 
690 static tree
lookup_awaitable_member(tree await_type,tree member_id,location_t loc)691 lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
692 {
693   tree aw_memb
694     = lookup_member (await_type, member_id,
695 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
696   if (aw_memb == NULL_TREE)
697     {
698       error_at (loc, "no member named %qE in %qT", member_id, await_type);
699       return error_mark_node;
700     }
701   return aw_memb;
702 }
703 
704 /* Here we check the constraints that are common to all keywords (since the
705    presence of a coroutine keyword makes the function into a coroutine).  */
706 
707 static bool
coro_common_keyword_context_valid_p(tree fndecl,location_t kw_loc,const char * kw_name)708 coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
709 				     const char *kw_name)
710 {
711   if (fndecl == NULL_TREE)
712     {
713       error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
714       return false;
715     }
716 
717   /* This is arranged in order of prohibitions in the std.  */
718   if (DECL_MAIN_P (fndecl))
719     {
720       /* [basic.start.main] 3. The function main shall not be a coroutine.  */
721       error_at (kw_loc, "%qs cannot be used in the %<main%> function",
722 		kw_name);
723       return false;
724     }
725 
726   if (DECL_DECLARED_CONSTEXPR_P (fndecl))
727     {
728       cp_function_chain->invalid_constexpr = true;
729       if (!is_instantiation_of_constexpr (fndecl))
730 	{
731 	  /* [dcl.constexpr] 3.3 it shall not be a coroutine.  */
732 	  error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
733 		    kw_name);
734 	  return false;
735 	}
736     }
737 
738   if (FNDECL_USED_AUTO (fndecl))
739     {
740       /* [dcl.spec.auto] 15. A function declared with a return type that uses
741 	 a placeholder type shall not be a coroutine.  */
742       error_at (kw_loc,
743 		"%qs cannot be used in a function with a deduced return type",
744 		kw_name);
745       return false;
746     }
747 
748   if (varargs_function_p (fndecl))
749     {
750       /* [dcl.fct.def.coroutine] The parameter-declaration-clause of the
751 	 coroutine shall not terminate with an ellipsis that is not part
752 	 of a parameter-declaration.  */
753       error_at (kw_loc,
754 		"%qs cannot be used in a varargs function", kw_name);
755       return false;
756     }
757 
758   if (DECL_CONSTRUCTOR_P (fndecl))
759     {
760       /* [class.ctor] 7. a constructor shall not be a coroutine.  */
761       error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
762       return false;
763     }
764 
765   if (DECL_DESTRUCTOR_P (fndecl))
766     {
767       /* [class.dtor] 21. a destructor shall not be a coroutine.  */
768       error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
769       return false;
770     }
771 
772   return true;
773 }
774 
775 /* Here we check the constraints that are not per keyword.  */
776 
777 static bool
coro_function_valid_p(tree fndecl)778 coro_function_valid_p (tree fndecl)
779 {
780   location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
781 
782   /* For cases where fundamental information cannot be found, e.g. the
783      coroutine traits are missing, we need to punt early.  */
784   if (!coro_promise_type_found_p (fndecl, f_loc))
785     return false;
786 
787   /* Since we think the function is a coroutine, that implies we parsed
788      a keyword that triggered this.  Keywords check promise validity for
789      their context and thus the promise type should be known at this point.  */
790   if (get_coroutine_handle_type (fndecl) == NULL_TREE
791       || get_coroutine_promise_type (fndecl) == NULL_TREE)
792     return false;
793 
794   if (current_function_returns_value || current_function_returns_null)
795     {
796        /* TODO: record or extract positions of returns (and the first coro
797 	  keyword) so that we can add notes to the diagnostic about where
798 	  the bad keyword is and what made the function into a coro.  */
799       error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
800 			" did you mean %<co_return%>?");
801       return false;
802     }
803 
804   return true;
805 }
806 
807 enum suspend_point_kind {
808   CO_AWAIT_SUSPEND_POINT = 0,
809   CO_YIELD_SUSPEND_POINT,
810   INITIAL_SUSPEND_POINT,
811   FINAL_SUSPEND_POINT
812 };
813 
814 /* Helper function to build a named variable for the temps we use for each
815    await point.  The root of the name is determined by SUSPEND_KIND, and
816    the variable is of type V_TYPE.  The awaitable number is reset each time
817    we encounter a final suspend.  */
818 
819 static tree
get_awaitable_var(suspend_point_kind suspend_kind,tree v_type)820 get_awaitable_var (suspend_point_kind suspend_kind, tree v_type)
821 {
822   static int awn = 0;
823   char *buf;
824   switch (suspend_kind)
825     {
826       default: buf = xasprintf ("Aw%d", awn++); break;
827       case CO_YIELD_SUSPEND_POINT: buf =  xasprintf ("Yd%d", awn++); break;
828       case INITIAL_SUSPEND_POINT: buf =  xasprintf ("Is"); break;
829       case FINAL_SUSPEND_POINT: buf =  xasprintf ("Fs"); awn = 0; break;
830   }
831   tree ret = get_identifier (buf);
832   free (buf);
833   ret = build_lang_decl (VAR_DECL, ret, v_type);
834   DECL_ARTIFICIAL (ret) = true;
835   return ret;
836 }
837 
838 /* Helpers to diagnose missing noexcept on final await expressions.  */
839 
840 static bool
coro_diagnose_throwing_fn(tree fndecl)841 coro_diagnose_throwing_fn (tree fndecl)
842 {
843   if (!TYPE_NOTHROW_P (TREE_TYPE (fndecl)))
844     {
845       location_t f_loc = cp_expr_loc_or_loc (fndecl,
846 					     DECL_SOURCE_LOCATION (fndecl));
847       error_at (f_loc, "the expression %qE is required to be non-throwing",
848 		fndecl);
849       inform (f_loc, "must be declared with %<noexcept(true)%>");
850       return true;
851     }
852   return false;
853 }
854 
855 static bool
coro_diagnose_throwing_final_aw_expr(tree expr)856 coro_diagnose_throwing_final_aw_expr (tree expr)
857 {
858   tree t = TARGET_EXPR_INITIAL (expr);
859   tree fn = NULL_TREE;
860   if (TREE_CODE (t) == CALL_EXPR)
861     fn = CALL_EXPR_FN(t);
862   else if (TREE_CODE (t) == AGGR_INIT_EXPR)
863     fn = AGGR_INIT_EXPR_FN (t);
864   else if (TREE_CODE (t) == CONSTRUCTOR)
865     return false;
866   else
867     {
868       gcc_checking_assert (0 && "unhandled expression type");
869       return false;
870     }
871   fn = TREE_OPERAND (fn, 0);
872   return coro_diagnose_throwing_fn (fn);
873 }
874 
875 /*  This performs [expr.await] bullet 3.3 and validates the interface obtained.
876     It is also used to build the initial and final suspend points.
877 
878     'a', 'o' and 'e' are used as per the description in the section noted.
879 
880     A, the original yield/await expr, is found at source location LOC.
881 
882     We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
883     the four suspend_point_kind kinds.  This is indicated by SUSPEND_KIND.  */
884 
885 static tree
build_co_await(location_t loc,tree a,suspend_point_kind suspend_kind)886 build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
887 {
888   /* Try and overload of operator co_await, .... */
889   tree o;
890   if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
891     {
892       o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
893 			NULL_TREE, NULL, tf_warning_or_error);
894       /* If no viable functions are found, o is a.  */
895       if (!o || o == error_mark_node)
896 	o = a;
897       else if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
898 	{
899 	  /* We found an overload for co_await(), diagnose throwing cases.  */
900 	  if (TREE_CODE (o) == TARGET_EXPR
901 	      && coro_diagnose_throwing_final_aw_expr (o))
902 	    return error_mark_node;
903 
904 	  /* We now know that the final suspend object is distinct from the
905 	     final awaiter, so check for a non-throwing DTOR where needed.  */
906 	  tree a_type = TREE_TYPE (a);
907 	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (a_type))
908 	    if (tree dummy
909 		= build_special_member_call (a, complete_dtor_identifier,
910 					     NULL, a_type, LOOKUP_NORMAL,
911 					     tf_none))
912 	      {
913 		if (CONVERT_EXPR_P (dummy))
914 		  dummy = TREE_OPERAND (dummy, 0);
915 		dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
916 		if (coro_diagnose_throwing_fn (dummy))
917 		  return error_mark_node;
918 	      }
919 	}
920     }
921   else
922     o = a; /* This is most likely about to fail anyway.  */
923 
924   tree o_type = TREE_TYPE (o);
925   if (o_type && !VOID_TYPE_P (o_type))
926     o_type = complete_type_or_else (o_type, o);
927 
928   if (!o_type)
929     return error_mark_node;
930 
931   if (TREE_CODE (o_type) != RECORD_TYPE)
932     {
933       error_at (loc, "awaitable type %qT is not a structure",
934 		o_type);
935       return error_mark_node;
936     }
937 
938   /* Check for required awaitable members and their types.  */
939   tree awrd_meth
940     = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
941   if (!awrd_meth || awrd_meth == error_mark_node)
942     return error_mark_node;
943   tree awsp_meth
944     = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
945   if (!awsp_meth || awsp_meth == error_mark_node)
946     return error_mark_node;
947 
948   /* The type of the co_await is the return type of the awaitable's
949      await_resume, so we need to look that up.  */
950   tree awrs_meth
951     = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
952   if (!awrs_meth || awrs_meth == error_mark_node)
953     return error_mark_node;
954 
955   /* To complete the lookups, we need an instance of 'e' which is built from
956      'o' according to [expr.await] 3.4.
957 
958      If we need to materialize this as a temporary, then that will have to be
959      'promoted' to a coroutine frame var.  However, if the awaitable is a
960      user variable, parameter or comes from a scope outside this function,
961      then we must use it directly - or we will see unnecessary copies.
962 
963      If o is a variable, find the underlying var.  */
964   tree e_proxy = STRIP_NOPS (o);
965   if (INDIRECT_REF_P (e_proxy))
966     e_proxy = TREE_OPERAND (e_proxy, 0);
967   while (TREE_CODE (e_proxy) == COMPONENT_REF)
968     {
969       e_proxy = TREE_OPERAND (e_proxy, 0);
970       if (INDIRECT_REF_P (e_proxy))
971 	e_proxy = TREE_OPERAND (e_proxy, 0);
972       if (TREE_CODE (e_proxy) == CALL_EXPR)
973 	{
974 	  /* We could have operator-> here too.  */
975 	  tree op = TREE_OPERAND (CALL_EXPR_FN (e_proxy), 0);
976 	  if (DECL_OVERLOADED_OPERATOR_P (op)
977 	      && DECL_OVERLOADED_OPERATOR_IS (op, COMPONENT_REF))
978 	    {
979 	      e_proxy = CALL_EXPR_ARG (e_proxy, 0);
980 	      STRIP_NOPS (e_proxy);
981 	      gcc_checking_assert (TREE_CODE (e_proxy) == ADDR_EXPR);
982 	      e_proxy = TREE_OPERAND (e_proxy, 0);
983 	    }
984 	}
985       STRIP_NOPS (e_proxy);
986     }
987 
988   /* Only build a temporary if we need it.  */
989   if (TREE_CODE (e_proxy) == PARM_DECL
990       || (VAR_P (e_proxy) && !is_local_temp (e_proxy)))
991     {
992       e_proxy = o;
993       o = NULL_TREE; /* The var is already present.  */
994     }
995   else if (type_build_ctor_call (o_type))
996     {
997       e_proxy = get_awaitable_var (suspend_kind, o_type);
998       releasing_vec arg (make_tree_vector_single (rvalue (o)));
999       o = build_special_member_call (e_proxy, complete_ctor_identifier,
1000 				     &arg, o_type, LOOKUP_NORMAL,
1001 				     tf_warning_or_error);
1002     }
1003   else
1004     {
1005       e_proxy = get_awaitable_var (suspend_kind, o_type);
1006       o = build2 (INIT_EXPR, o_type, e_proxy, rvalue (o));
1007     }
1008 
1009   /* I suppose we could check that this is contextually convertible to bool.  */
1010   tree awrd_func = NULL_TREE;
1011   tree awrd_call
1012     = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1013 			     &awrd_func, tf_warning_or_error);
1014 
1015   if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
1016     return error_mark_node;
1017 
1018   /* The suspend method may return one of three types:
1019       1. void (no special action needed).
1020       2. bool (if true, we don't need to suspend).
1021       3. a coroutine handle, we execute the handle.resume() call.  */
1022   tree awsp_func = NULL_TREE;
1023   tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
1024   vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
1025   tree awsp_call
1026     = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
1027 			     LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
1028 
1029   release_tree_vector (args);
1030   if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
1031     return error_mark_node;
1032 
1033   bool ok = false;
1034   tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
1035   if (same_type_p (susp_return_type, void_type_node))
1036     ok = true;
1037   else if (same_type_p (susp_return_type, boolean_type_node))
1038     ok = true;
1039   else if (TREE_CODE (susp_return_type) == RECORD_TYPE
1040 	   && CLASS_TYPE_P (susp_return_type))
1041     {
1042       tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
1043       if (tt == coro_handle_templ)
1044 	ok = true;
1045     }
1046 
1047   if (!ok)
1048     {
1049       error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
1050 		     " a coroutine handle");
1051       return error_mark_node;
1052     }
1053 
1054   /* Finally, the type of e.await_resume() is the co_await's type.  */
1055   tree awrs_func = NULL_TREE;
1056   tree awrs_call
1057     = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
1058 			     &awrs_func, tf_warning_or_error);
1059 
1060   if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
1061     return error_mark_node;
1062 
1063   if (flag_exceptions && suspend_kind == FINAL_SUSPEND_POINT)
1064     {
1065       if (coro_diagnose_throwing_fn (awrd_func))
1066 	return error_mark_node;
1067       if (coro_diagnose_throwing_fn (awsp_func))
1068 	return error_mark_node;
1069       if (coro_diagnose_throwing_fn (awrs_func))
1070 	return error_mark_node;
1071       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (o_type))
1072 	if (tree dummy
1073 	    = build_special_member_call (e_proxy, complete_dtor_identifier,
1074 					 NULL, o_type, LOOKUP_NORMAL,
1075 					 tf_none))
1076 	  {
1077 	    if (CONVERT_EXPR_P (dummy))
1078 	      dummy = TREE_OPERAND (dummy, 0);
1079 	    dummy = TREE_OPERAND (CALL_EXPR_FN (dummy), 0);
1080 	    if (coro_diagnose_throwing_fn (dummy))
1081 	      return error_mark_node;
1082 	  }
1083     }
1084 
1085   /* We now have three call expressions, in terms of the promise, handle and
1086      'e' proxies.  Save them in the await expression for later expansion.  */
1087 
1088   tree awaiter_calls = make_tree_vec (3);
1089   TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready().  */
1090   TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend().  */
1091   tree te = NULL_TREE;
1092   if (TREE_CODE (awrs_call) == TARGET_EXPR)
1093     {
1094       te = awrs_call;
1095       awrs_call = TREE_OPERAND (awrs_call, 1);
1096     }
1097   TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume().  */
1098 
1099   tree await_expr = build5_loc (loc, CO_AWAIT_EXPR,
1100 				TREE_TYPE (TREE_TYPE (awrs_func)),
1101 				a, e_proxy, o, awaiter_calls,
1102 				build_int_cst (integer_type_node,
1103 					       (int) suspend_kind));
1104   if (te)
1105     {
1106       TREE_OPERAND (te, 1) = await_expr;
1107       await_expr = te;
1108     }
1109   tree t = convert_from_reference (await_expr);
1110   return t;
1111 }
1112 
1113 tree
finish_co_await_expr(location_t kw,tree expr)1114 finish_co_await_expr (location_t kw, tree expr)
1115 {
1116   if (!expr || error_operand_p (expr))
1117     return error_mark_node;
1118 
1119   if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1120 					    "co_await"))
1121     return error_mark_node;
1122 
1123   /* The current function has now become a coroutine, if it wasn't already.  */
1124   DECL_COROUTINE_P (current_function_decl) = 1;
1125 
1126   /* This function will appear to have no return statement, even if it
1127      is declared to return non-void (most likely).  This is correct - we
1128      synthesize the return for the ramp in the compiler.  So suppress any
1129      extraneous warnings during substitution.  */
1130   TREE_NO_WARNING (current_function_decl) = true;
1131 
1132   /* If we don't know the promise type, we can't proceed, build the
1133      co_await with the expression unchanged.  */
1134   tree functype = TREE_TYPE (current_function_decl);
1135   if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1136     return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr,
1137 		       NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node);
1138 
1139   /* We must be able to look up the "await_transform" method in the scope of
1140      the promise type, and obtain its return type.  */
1141   if (!coro_promise_type_found_p (current_function_decl, kw))
1142     return error_mark_node;
1143 
1144   /* [expr.await] 3.2
1145      The incoming cast expression might be transformed by a promise
1146      'await_transform()'.  */
1147   tree at_meth
1148     = lookup_promise_method (current_function_decl,
1149 			     coro_await_transform_identifier, kw,
1150 			     /*musthave=*/false);
1151   if (at_meth == error_mark_node)
1152     return error_mark_node;
1153 
1154   tree a = expr;
1155   if (at_meth)
1156     {
1157       /* try to build a = p.await_transform (e). */
1158       vec<tree, va_gc> *args = make_tree_vector_single (expr);
1159       a = build_new_method_call (get_coroutine_promise_proxy (
1160 				   current_function_decl),
1161 				 at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
1162 				 NULL, tf_warning_or_error);
1163 
1164       /* As I read the section.
1165 	 We saw an await_transform method, so it's mandatory that we replace
1166 	 expr with p.await_transform (expr), therefore if the method call fails
1167 	 (presumably, we don't have suitable arguments) then this part of the
1168 	 process fails.  */
1169       if (a == error_mark_node)
1170 	return error_mark_node;
1171     }
1172 
1173   /* Now we want to build co_await a.  */
1174   tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
1175   if (op != error_mark_node)
1176     {
1177       TREE_SIDE_EFFECTS (op) = 1;
1178       SET_EXPR_LOCATION (op, kw);
1179     }
1180 
1181   return op;
1182 }
1183 
1184 /* Take the EXPR given and attempt to build:
1185      co_await p.yield_value (expr);
1186    per [expr.yield] para 1. */
1187 
1188 tree
finish_co_yield_expr(location_t kw,tree expr)1189 finish_co_yield_expr (location_t kw, tree expr)
1190 {
1191   if (!expr || error_operand_p (expr))
1192     return error_mark_node;
1193 
1194   /* Check the general requirements and simple syntax errors.  */
1195   if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1196 					    "co_yield"))
1197     return error_mark_node;
1198 
1199   /* The current function has now become a coroutine, if it wasn't already.  */
1200   DECL_COROUTINE_P (current_function_decl) = 1;
1201 
1202   /* This function will appear to have no return statement, even if it
1203      is declared to return non-void (most likely).  This is correct - we
1204      synthesize the return for the ramp in the compiler.  So suppress any
1205      extraneous warnings during substitution.  */
1206   TREE_NO_WARNING (current_function_decl) = true;
1207 
1208   /* If we don't know the promise type, we can't proceed, build the
1209      co_await with the expression unchanged.  */
1210   tree functype = TREE_TYPE (current_function_decl);
1211   if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1212     return build2_loc (kw, CO_YIELD_EXPR, unknown_type_node, expr, NULL_TREE);
1213 
1214   if (!coro_promise_type_found_p (current_function_decl, kw))
1215     /* We must be able to look up the "yield_value" method in the scope of
1216        the promise type, and obtain its return type.  */
1217     return error_mark_node;
1218 
1219   /* [expr.yield] / 1
1220      Let e be the operand of the yield-expression and p be an lvalue naming
1221      the promise object of the enclosing coroutine, then the yield-expression
1222      is equivalent to the expression co_await p.yield_value(e).
1223      build p.yield_value(e):  */
1224   vec<tree, va_gc> *args = make_tree_vector_single (expr);
1225   tree yield_call
1226     = coro_build_promise_expression (current_function_decl, NULL,
1227 				     coro_yield_value_identifier, kw,
1228 				     &args, /*musthave=*/true);
1229   release_tree_vector (args);
1230 
1231   /* Now build co_await p.yield_value (e).
1232      Noting that for co_yield, there is no evaluation of any potential
1233      promise transform_await(), so we call build_co_await directly.  */
1234 
1235   tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
1236   if (op != error_mark_node)
1237     {
1238       if (REFERENCE_REF_P (op))
1239 	op = TREE_OPERAND (op, 0);
1240       /* If the await expression is wrapped in a TARGET_EXPR, then transfer
1241 	 that wrapper to the CO_YIELD_EXPR, since this is just a proxy for
1242 	 its contained await.  Otherwise, just build the CO_YIELD_EXPR.  */
1243       if (TREE_CODE (op) == TARGET_EXPR)
1244 	{
1245 	  tree t = TREE_OPERAND (op, 1);
1246 	  t = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (t), expr, t);
1247 	  TREE_OPERAND (op, 1) = t;
1248 	}
1249       else
1250 	op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
1251       TREE_SIDE_EFFECTS (op) = 1;
1252       op = convert_from_reference (op);
1253     }
1254 
1255   return op;
1256 }
1257 
1258 /* Check and build a co_return statement.
1259    First that it's valid to have a co_return keyword here.
1260    If it is, then check and build the p.return_{void(),value(expr)}.
1261    These are built against a proxy for the promise, which will be filled
1262    in with the actual frame version when the function is transformed.  */
1263 
1264 tree
finish_co_return_stmt(location_t kw,tree expr)1265 finish_co_return_stmt (location_t kw, tree expr)
1266 {
1267   if (expr)
1268     STRIP_ANY_LOCATION_WRAPPER (expr);
1269 
1270   if (error_operand_p (expr))
1271     return error_mark_node;
1272 
1273   /* If it fails the following test, the function is not permitted to be a
1274      coroutine, so the co_return statement is erroneous.  */
1275   if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
1276 					    "co_return"))
1277     return error_mark_node;
1278 
1279   /* The current function has now become a coroutine, if it wasn't
1280      already.  */
1281   DECL_COROUTINE_P (current_function_decl) = 1;
1282 
1283   /* This function will appear to have no return statement, even if it
1284      is declared to return non-void (most likely).  This is correct - we
1285      synthesize the return for the ramp in the compiler.  So suppress any
1286      extraneous warnings during substitution.  */
1287   TREE_NO_WARNING (current_function_decl) = true;
1288 
1289   if (processing_template_decl
1290       && check_for_bare_parameter_packs (expr))
1291     return error_mark_node;
1292 
1293   /* If we don't know the promise type, we can't proceed, build the
1294      co_return with the expression unchanged.  */
1295   tree functype = TREE_TYPE (current_function_decl);
1296   if (dependent_type_p (functype) || type_dependent_expression_p (expr))
1297     {
1298       /* co_return expressions are always void type, regardless of the
1299 	 expression type.  */
1300       expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node,
1301 			 expr, NULL_TREE);
1302       expr = maybe_cleanup_point_expr_void (expr);
1303       return add_stmt (expr);
1304     }
1305 
1306   if (!coro_promise_type_found_p (current_function_decl, kw))
1307     return error_mark_node;
1308 
1309   /* Suppress -Wreturn-type for co_return, we need to check indirectly
1310      whether the promise type has a suitable return_void/return_value.  */
1311   TREE_NO_WARNING (current_function_decl) = true;
1312 
1313   if (!processing_template_decl && warn_sequence_point)
1314     verify_sequence_points (expr);
1315 
1316   if (expr)
1317     {
1318       /* If we had an id-expression obfuscated by force_paren_expr, we need
1319 	 to undo it so we can try to treat it as an rvalue below.  */
1320       expr = maybe_undo_parenthesized_ref (expr);
1321 
1322       if (processing_template_decl)
1323 	expr = build_non_dependent_expr (expr);
1324 
1325       if (error_operand_p (expr))
1326 	return error_mark_node;
1327     }
1328 
1329   /* If the promise object doesn't have the correct return call then
1330      there's a mis-match between the co_return <expr> and this.  */
1331   tree co_ret_call = error_mark_node;
1332   if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
1333     co_ret_call
1334       = get_coroutine_return_void_expr (current_function_decl, kw, true);
1335   else
1336     {
1337       /* [class.copy.elision] / 3.
1338 	 An implicitly movable entity is a variable of automatic storage
1339 	 duration that is either a non-volatile object or an rvalue reference
1340 	 to a non-volatile object type.  For such objects in the context of
1341 	 the co_return, the overload resolution should be carried out first
1342 	 treating the object as an rvalue, if that fails, then we fall back
1343 	 to regular overload resolution.  */
1344 
1345       tree arg = expr;
1346       if (tree moved = treat_lvalue_as_rvalue_p (expr, /*return*/true))
1347 	arg = moved;
1348 
1349       releasing_vec args = make_tree_vector_single (arg);
1350       co_ret_call
1351 	= coro_build_promise_expression (current_function_decl, NULL,
1352 					 coro_return_value_identifier, kw,
1353 					 &args, /*musthave=*/true);
1354     }
1355 
1356   /* Makes no sense for a co-routine really. */
1357   if (TREE_THIS_VOLATILE (current_function_decl))
1358     warning_at (kw, 0,
1359 		"function declared %<noreturn%> has a"
1360 		" %<co_return%> statement");
1361 
1362   expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
1363   expr = maybe_cleanup_point_expr_void (expr);
1364   return add_stmt (expr);
1365 }
1366 
1367 /* We need to validate the arguments to __builtin_coro_promise, since the
1368    second two must be constant, and the builtins machinery doesn't seem to
1369    deal with that properly.  */
1370 
1371 tree
coro_validate_builtin_call(tree call,tsubst_flags_t)1372 coro_validate_builtin_call (tree call, tsubst_flags_t)
1373 {
1374   tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
1375 
1376   gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
1377   switch (DECL_FUNCTION_CODE (fn))
1378     {
1379     default:
1380       return call;
1381 
1382     case BUILT_IN_CORO_PROMISE:
1383       {
1384 	/* Argument 0 is already checked by the normal built-in machinery
1385 	   Argument 1 must be a constant of size type.  It probably makes
1386 	   little sense if it's not a power of 2, but that isn't specified
1387 	   formally.  */
1388 	tree arg = CALL_EXPR_ARG (call, 1);
1389 	location_t loc = EXPR_LOCATION (arg);
1390 
1391 	/* We expect alignof expressions in templates.  */
1392 	if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
1393 	    && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
1394 	  ;
1395 	else if (!TREE_CONSTANT (arg))
1396 	  {
1397 	    error_at (loc, "the align argument to %<__builtin_coro_promise%>"
1398 			   " must be a constant");
1399 	    return error_mark_node;
1400 	  }
1401 	/* Argument 2 is the direction - to / from handle address to promise
1402 	   address.  */
1403 	arg = CALL_EXPR_ARG (call, 2);
1404 	loc = EXPR_LOCATION (arg);
1405 	if (!TREE_CONSTANT (arg))
1406 	  {
1407 	    error_at (loc, "the direction argument to"
1408 			   " %<__builtin_coro_promise%> must be a constant");
1409 	    return error_mark_node;
1410 	  }
1411 	return call;
1412 	break;
1413       }
1414     }
1415 }
1416 
1417 /* ================= Morph and Expand. =================
1418 
1419    The entry point here is morph_fn_to_coro () which is called from
1420    finish_function () when we have completed any template expansion.
1421 
1422    This is preceded by helper functions that implement the phases below.
1423 
1424    The process proceeds in four phases.
1425 
1426    A Initial framing.
1427      The user's function body is wrapped in the initial and final suspend
1428      points and we begin building the coroutine frame.
1429      We build empty decls for the actor and destroyer functions at this
1430      time too.
1431      When exceptions are enabled, the user's function body will also be
1432      wrapped in a try-catch block with the catch invoking the promise
1433      class 'unhandled_exception' method.
1434 
1435    B Analysis.
1436      The user's function body is analyzed to determine the suspend points,
1437      if any, and to capture local variables that might persist across such
1438      suspensions.  In most cases, it is not necessary to capture compiler
1439      temporaries, since the tree-lowering nests the suspensions correctly.
1440      However, in the case of a captured reference, there is a lifetime
1441      extension to the end of the full expression - which can mean across a
1442      suspend point in which case it must be promoted to a frame variable.
1443 
1444      At the conclusion of analysis, we have a conservative frame layout and
1445      maps of the local variables to their frame entry points.
1446 
1447    C Build the ramp function.
1448      Carry out the allocation for the coroutine frame (NOTE; the actual size
1449      computation is deferred until late in the middle end to allow for future
1450      optimizations that will be allowed to elide unused frame entries).
1451      We build the return object.
1452 
1453    D Build and expand the actor and destroyer function bodies.
1454      The destroyer is a trivial shim that sets a bit to indicate that the
1455      destroy dispatcher should be used and then calls into the actor.
1456 
1457      The actor function is the implementation of the user's state machine.
1458      The current suspend point is noted in an index.
1459      Each suspend point is encoded as a pair of internal functions, one in
1460      the relevant dispatcher, and one representing the suspend point.
1461 
1462      During this process, the user's local variables and the proxies for the
1463      self-handle and the promise class instance are re-written to their
1464      coroutine frame equivalents.
1465 
1466      The complete bodies for the ramp, actor and destroy function are passed
1467      back to finish_function for folding and gimplification.  */
1468 
1469 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops.  */
1470 
1471 static tree
coro_build_expr_stmt(tree expr,location_t loc)1472 coro_build_expr_stmt (tree expr, location_t loc)
1473 {
1474   return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
1475 }
1476 
1477 static tree
coro_build_cvt_void_expr_stmt(tree expr,location_t loc)1478 coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
1479 {
1480   tree t = build1 (CONVERT_EXPR, void_type_node, expr);
1481   return coro_build_expr_stmt (t, loc);
1482 }
1483 
1484 /* Helpers for label creation:
1485    1. Create a named label in the specified context.  */
1486 
1487 static tree
create_anon_label_with_ctx(location_t loc,tree ctx)1488 create_anon_label_with_ctx (location_t loc, tree ctx)
1489 {
1490   tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
1491 
1492   DECL_CONTEXT (lab) = ctx;
1493   DECL_ARTIFICIAL (lab) = true;
1494   DECL_IGNORED_P (lab) = true;
1495   TREE_USED (lab) = true;
1496   return lab;
1497 }
1498 
1499 /*  2. Create a named label in the specified context.  */
1500 
1501 static tree
create_named_label_with_ctx(location_t loc,const char * name,tree ctx)1502 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
1503 {
1504   tree lab_id = get_identifier (name);
1505   tree lab = define_label (loc, lab_id);
1506   DECL_CONTEXT (lab) = ctx;
1507   DECL_ARTIFICIAL (lab) = true;
1508   TREE_USED (lab) = true;
1509   return lab;
1510 }
1511 
1512 struct proxy_replace
1513 {
1514   tree from, to;
1515 };
1516 
1517 static tree
replace_proxy(tree * here,int * do_subtree,void * d)1518 replace_proxy (tree *here, int *do_subtree, void *d)
1519 {
1520   proxy_replace *data = (proxy_replace *) d;
1521 
1522   if (*here == data->from)
1523     {
1524       *here = data->to;
1525       *do_subtree = 0;
1526     }
1527   else
1528     *do_subtree = 1;
1529   return NULL_TREE;
1530 }
1531 
1532 /* Support for expansion of co_await statements.  */
1533 
1534 struct coro_aw_data
1535 {
1536   tree actor_fn;   /* Decl for context.  */
1537   tree coro_fp;    /* Frame pointer var.  */
1538   tree resume_idx; /* This is the index var in the frame.  */
1539   tree i_a_r_c;    /* initial suspend await_resume() was called if true.  */
1540   tree self_h;     /* This is a handle to the current coro (frame var).  */
1541   tree cleanup;    /* This is where to go once we complete local destroy.  */
1542   tree cororet;    /* This is where to go if we suspend.  */
1543   tree corocont;   /* This is where to go if we continue.  */
1544   tree conthand;   /* This is the handle for a continuation.  */
1545   unsigned index;  /* This is our current resume index.  */
1546 };
1547 
1548 /* Lightweight search for the first await expression in tree-walk order.
1549    returns:
1550      The first await expression found in STMT.
1551      NULL_TREE if there are none.
1552    So can be used to determine if the statement needs to be processed for
1553    awaits.  */
1554 
1555 static tree
co_await_find_in_subtree(tree * stmt,int *,void * d)1556 co_await_find_in_subtree (tree *stmt, int *, void *d)
1557 {
1558   tree **p = (tree **) d;
1559   if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
1560     {
1561       *p = stmt;
1562       return *stmt;
1563     }
1564   return NULL_TREE;
1565 }
1566 
1567 /* Starting with a statement:
1568 
1569    stmt => some tree containing one or more await expressions.
1570 
1571    We replace the statement with:
1572    <STATEMENT_LIST> {
1573       initialize awaitable
1574       if (!ready)
1575 	{
1576 	  suspension context.
1577 	}
1578       resume:
1579 	revised statement with one await expression rewritten to its
1580 	await_resume() return value.
1581    }
1582 
1583    We then recurse into the initializer and the revised statement
1584    repeating this replacement until there are no more await expressions
1585    in either.  */
1586 
1587 static tree *
expand_one_await_expression(tree * stmt,tree * await_expr,void * d)1588 expand_one_await_expression (tree *stmt, tree *await_expr, void *d)
1589 {
1590   coro_aw_data *data = (coro_aw_data *) d;
1591 
1592   tree saved_statement = *stmt;
1593   tree saved_co_await = *await_expr;
1594 
1595   tree actor = data->actor_fn;
1596   location_t loc = EXPR_LOCATION (*stmt);
1597   tree var = TREE_OPERAND (saved_co_await, 1);  /* frame slot. */
1598   tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer.  */
1599   tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
1600 
1601   tree source = TREE_OPERAND (saved_co_await, 4);
1602   bool is_final = (source
1603 		   && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
1604   bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
1605   int resume_point = data->index;
1606   size_t bufsize = sizeof ("destroy.") + 10;
1607   char *buf = (char *) alloca (bufsize);
1608   snprintf (buf, bufsize, "destroy.%d", resume_point);
1609   tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
1610   snprintf (buf, bufsize, "resume.%d", resume_point);
1611   tree resume_label = create_named_label_with_ctx (loc, buf, actor);
1612   tree empty_list = build_empty_stmt (loc);
1613 
1614   tree await_type = TREE_TYPE (var);
1615   tree stmt_list = NULL;
1616   tree r;
1617   tree *await_init = NULL;
1618 
1619   if (!expr)
1620     needs_dtor = false; /* No need, the var's lifetime is managed elsewhere.  */
1621   else
1622     {
1623       r = coro_build_cvt_void_expr_stmt (expr, loc);
1624       append_to_statement_list_force (r, &stmt_list);
1625       /* We have an initializer, which might itself contain await exprs.  */
1626       await_init = tsi_stmt_ptr (tsi_last (stmt_list));
1627     }
1628 
1629   /* Use the await_ready() call to test if we need to suspend.  */
1630   tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready().  */
1631   /* Convert to bool, if necessary.  */
1632   if (TREE_CODE (TREE_TYPE (ready_cond)) != BOOLEAN_TYPE)
1633     ready_cond = cp_convert (boolean_type_node, ready_cond,
1634 			     tf_warning_or_error);
1635   /* Be aggressive in folding here, since there are a significant number of
1636      cases where the ready condition is constant.  */
1637   ready_cond = invert_truthvalue_loc (loc, ready_cond);
1638   ready_cond
1639     = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
1640 
1641   tree body_list = NULL;
1642   tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
1643   r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
1644 		  susp_idx);
1645   r = coro_build_cvt_void_expr_stmt (r, loc);
1646   append_to_statement_list (r, &body_list);
1647 
1648   /* Find out what we have to do with the awaiter's suspend method.
1649      [expr.await]
1650      (5.1) If the result of await-ready is false, the coroutine is considered
1651 	   suspended. Then:
1652      (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
1653 	     await-suspend.resume() is evaluated.
1654      (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
1655 	     and the coroutine is resumed if the result is false.
1656      (5.1.3) Otherwise, await-suspend is evaluated.  */
1657 
1658   tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend().  */
1659   tree susp_type = TREE_TYPE (suspend);
1660 
1661   bool is_cont = false;
1662   /* NOTE: final suspend can't resume; the "resume" label in that case
1663      corresponds to implicit destruction.  */
1664   if (VOID_TYPE_P (susp_type))
1665     {
1666       /* We just call await_suspend() and hit the yield.  */
1667       suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
1668       append_to_statement_list (suspend, &body_list);
1669     }
1670   else if (TREE_CODE (susp_type) == BOOLEAN_TYPE)
1671     {
1672       /* Boolean return, continue if the call returns false.  */
1673       suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
1674       suspend
1675 	= build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
1676       tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1677       r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
1678 		      empty_list);
1679       append_to_statement_list (r, &body_list);
1680     }
1681   else
1682     {
1683       r = build1_loc (loc, CONVERT_EXPR, void_coro_handle_type, suspend);
1684       r = build2_loc (loc, INIT_EXPR, void_coro_handle_type, data->conthand, r);
1685       r = build1 (CONVERT_EXPR, void_type_node, r);
1686       append_to_statement_list (r, &body_list);
1687       is_cont = true;
1688     }
1689 
1690   tree d_l = build_address (destroy_label);
1691   tree r_l = build_address (resume_label);
1692   tree susp = build_address (data->cororet);
1693   tree cont = build_address (data->corocont);
1694   tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
1695 
1696   susp_idx = build_int_cst (integer_type_node, data->index);
1697 
1698   tree sw = begin_switch_stmt ();
1699   tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
1700   DECL_ARTIFICIAL (cond) = 1;
1701   DECL_IGNORED_P (cond) = 1;
1702   layout_decl (cond, 0);
1703 
1704   r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
1705 				    susp_idx, final_susp, r_l, d_l,
1706 				    data->coro_fp);
1707   r = build2 (INIT_EXPR, integer_type_node, cond, r);
1708   finish_switch_cond (r, sw);
1709   r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
1710 			create_anon_label_with_ctx (loc, actor));
1711   add_stmt (r); /* case 0: */
1712   /* Implement the suspend, a scope exit without clean ups.  */
1713   r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1,
1714 				    is_cont ? cont : susp);
1715   r = coro_build_cvt_void_expr_stmt (r, loc);
1716   add_stmt (r); /*   goto ret;  */
1717   r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
1718 			create_anon_label_with_ctx (loc, actor));
1719   add_stmt (r); /* case 1:  */
1720   r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1721   add_stmt (r); /*  goto resume;  */
1722   r = build_case_label (NULL_TREE, NULL_TREE,
1723 			create_anon_label_with_ctx (loc, actor));
1724   add_stmt (r); /* default:;  */
1725   r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
1726   add_stmt (r); /* goto destroy;  */
1727 
1728   /* part of finish switch.  */
1729   SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
1730   pop_switch ();
1731   tree scope = SWITCH_STMT_SCOPE (sw);
1732   SWITCH_STMT_SCOPE (sw) = NULL;
1733   r = do_poplevel (scope);
1734   append_to_statement_list (r, &body_list);
1735 
1736   destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
1737   append_to_statement_list (destroy_label, &body_list);
1738   if (needs_dtor)
1739     {
1740       tree dtor = build_special_member_call (var, complete_dtor_identifier,
1741 					     NULL, await_type, LOOKUP_NORMAL,
1742 					     tf_warning_or_error);
1743       append_to_statement_list (dtor, &body_list);
1744     }
1745   r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
1746   append_to_statement_list (r, &body_list);
1747 
1748   r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
1749 		  empty_list);
1750 
1751   append_to_statement_list (r, &stmt_list);
1752 
1753   /* Resume point.  */
1754   resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
1755   append_to_statement_list (resume_label, &stmt_list);
1756 
1757   /* This will produce the value (if one is provided) from the co_await
1758      expression.  */
1759   tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume().  */
1760   if (REFERENCE_REF_P (resume_call))
1761     /* Sink to await_resume call_expr.  */
1762     resume_call = TREE_OPERAND (resume_call, 0);
1763 
1764   *await_expr = resume_call; /* Replace the co_await expr with its result.  */
1765   append_to_statement_list_force (saved_statement, &stmt_list);
1766   /* Get a pointer to the revised statement.  */
1767   tree *revised = tsi_stmt_ptr (tsi_last (stmt_list));
1768   if (needs_dtor)
1769     {
1770       tree dtor = build_special_member_call (var, complete_dtor_identifier,
1771 					     NULL, await_type, LOOKUP_NORMAL,
1772 					     tf_warning_or_error);
1773       append_to_statement_list (dtor, &stmt_list);
1774     }
1775   data->index += 2;
1776 
1777   /* Replace the original statement with the expansion.  */
1778   *stmt = stmt_list;
1779 
1780   /* Now, if the awaitable had an initializer, expand any awaits that might
1781      be embedded in it.  */
1782   tree *aw_expr_ptr;
1783   if (await_init &&
1784       cp_walk_tree (await_init, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1785     expand_one_await_expression (await_init, aw_expr_ptr, d);
1786 
1787   /* Expand any more await expressions in the the original statement.  */
1788   if (cp_walk_tree (revised, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1789     expand_one_await_expression (revised, aw_expr_ptr, d);
1790 
1791   return NULL;
1792 }
1793 
1794 /* Check to see if a statement contains at least one await expression, if
1795    so, then process that.  */
1796 
1797 static tree
process_one_statement(tree * stmt,void * d)1798 process_one_statement (tree *stmt, void *d)
1799 {
1800   tree *aw_expr_ptr;
1801   if (cp_walk_tree (stmt, co_await_find_in_subtree, &aw_expr_ptr, NULL))
1802     expand_one_await_expression (stmt, aw_expr_ptr, d);
1803   return NULL_TREE;
1804 }
1805 
1806 static tree
await_statement_expander(tree * stmt,int * do_subtree,void * d)1807 await_statement_expander (tree *stmt, int *do_subtree, void *d)
1808 {
1809   tree res = NULL_TREE;
1810 
1811   /* Process a statement at a time.  */
1812   if (STATEMENT_CLASS_P (*stmt) || TREE_CODE (*stmt) == BIND_EXPR)
1813     return NULL_TREE; /* Just process the sub-trees.  */
1814   else if (TREE_CODE (*stmt) == STATEMENT_LIST)
1815     {
1816       tree_stmt_iterator i;
1817       for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
1818 	{
1819 	  res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_expander,
1820 			      d, NULL);
1821 	  if (res)
1822 	    return res;
1823 	}
1824       *do_subtree = 0; /* Done subtrees.  */
1825     }
1826   else if (EXPR_P (*stmt))
1827     {
1828       process_one_statement (stmt, d);
1829       *do_subtree = 0; /* Done subtrees.  */
1830     }
1831 
1832   /* Continue statement walk, where required.  */
1833   return res;
1834 }
1835 
1836 /* Suspend point hash_map.  */
1837 
1838 struct suspend_point_info
1839 {
1840   /* coro frame field type.  */
1841   tree awaitable_type;
1842   /* coro frame field name.  */
1843   tree await_field_id;
1844 };
1845 
1846 static hash_map<tree, suspend_point_info> *suspend_points;
1847 
1848 struct await_xform_data
1849 {
1850   tree actor_fn;   /* Decl for context.  */
1851   tree actor_frame;
1852   tree promise_proxy;
1853   tree real_promise;
1854   tree self_h_proxy;
1855   tree real_self_h;
1856 };
1857 
1858 /* When we built the await expressions, we didn't know the coro frame
1859    layout, therefore no idea where to find the promise or where to put
1860    the awaitables.  Now we know these things, fill them in.  */
1861 
1862 static tree
transform_await_expr(tree await_expr,await_xform_data * xform)1863 transform_await_expr (tree await_expr, await_xform_data *xform)
1864 {
1865   suspend_point_info *si = suspend_points->get (await_expr);
1866   location_t loc = EXPR_LOCATION (await_expr);
1867   if (!si)
1868     {
1869       error_at (loc, "no suspend point info for %qD", await_expr);
1870       return error_mark_node;
1871     }
1872 
1873   /* So, on entry, we have:
1874      in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1875 	  We no longer need a [it had diagnostic value, maybe?]
1876 	  We need to replace the promise proxy in all elements
1877 	  We need to replace the e_proxy in the awr_call.  */
1878 
1879   tree coro_frame_type = TREE_TYPE (xform->actor_frame);
1880 
1881   /* If we have a frame var for the awaitable, get a reference to it.  */
1882   proxy_replace data;
1883   if (si->await_field_id)
1884     {
1885       tree as_m
1886 	 = lookup_member (coro_frame_type, si->await_field_id,
1887 			  /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
1888       tree as = build_class_member_access_expr (xform->actor_frame, as_m,
1889 						NULL_TREE, true,
1890 						tf_warning_or_error);
1891 
1892       /* Replace references to the instance proxy with the frame entry now
1893 	 computed.  */
1894       data.from = TREE_OPERAND (await_expr, 1);
1895       data.to = as;
1896       cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1897 
1898       /* .. and replace.  */
1899       TREE_OPERAND (await_expr, 1) = as;
1900     }
1901 
1902   /* Now do the self_handle.  */
1903   data.from = xform->self_h_proxy;
1904   data.to = xform->real_self_h;
1905   cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1906 
1907   /* Now do the promise.  */
1908   data.from = xform->promise_proxy;
1909   data.to = xform->real_promise;
1910   cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1911 
1912   return await_expr;
1913 }
1914 
1915 /* A wrapper for the transform_await_expr function so that it can be a
1916    callback from cp_walk_tree.  */
1917 
1918 static tree
transform_await_wrapper(tree * stmt,int * do_subtree,void * d)1919 transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
1920 {
1921   /* Set actor function as new DECL_CONTEXT of label_decl.  */
1922   struct await_xform_data *xform = (struct await_xform_data *) d;
1923   if (TREE_CODE (*stmt) == LABEL_DECL
1924       && DECL_CONTEXT (*stmt) != xform->actor_fn)
1925     DECL_CONTEXT (*stmt) = xform->actor_fn;
1926 
1927   /* We should have already lowered co_yields to their co_await.  */
1928   gcc_checking_assert (TREE_CODE (*stmt) != CO_YIELD_EXPR);
1929   if (TREE_CODE (*stmt) != CO_AWAIT_EXPR)
1930     return NULL_TREE;
1931 
1932   tree await_expr = *stmt;
1933   *stmt = transform_await_expr (await_expr, xform);
1934   if (*stmt == error_mark_node)
1935     *do_subtree = 0;
1936   return NULL_TREE;
1937 }
1938 
1939 /* This caches information that we determine about function params,
1940    their uses and copies in the coroutine frame.  */
1941 
1942 struct param_info
1943 {
1944   tree field_id;     /* The name of the copy in the coroutine frame.  */
1945   vec<tree *> *body_uses; /* Worklist of uses, void if there are none.  */
1946   tree frame_type;   /* The type used to represent this parm in the frame.  */
1947   tree orig_type;    /* The original type of the parm (not as passed).  */
1948   tree guard_var;    /* If we need a DTOR on exception, this bool guards it.  */
1949   tree fr_copy_dtor; /* If we need a DTOR on exception, this is it.  */
1950   bool by_ref;       /* Was passed by reference.  */
1951   bool pt_ref;       /* Was a pointer to object.  */
1952   bool rv_ref;       /* Was an rvalue ref.  */
1953   bool trivial_dtor; /* The frame type has a trivial DTOR.  */
1954   bool this_ptr;     /* Is 'this' */
1955   bool lambda_cobj;  /* Lambda capture object */
1956 };
1957 
1958 struct local_var_info
1959 {
1960   tree field_id;
1961   tree field_idx;
1962   tree frame_type;
1963   bool is_lambda_capture;
1964   bool is_static;
1965   bool has_value_expr_p;
1966   location_t def_loc;
1967 };
1968 
1969 /* For figuring out what local variable usage we have.  */
1970 struct local_vars_transform
1971 {
1972   tree context;
1973   tree actor_frame;
1974   tree coro_frame_type;
1975   location_t loc;
1976   hash_map<tree, local_var_info> *local_var_uses;
1977 };
1978 
1979 static tree
transform_local_var_uses(tree * stmt,int * do_subtree,void * d)1980 transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
1981 {
1982   local_vars_transform *lvd = (local_vars_transform *) d;
1983 
1984   /* For each var in this bind expr (that has a frame id, which means it was
1985      accessed), build a frame reference for each and then walk the bind expr
1986      statements, substituting the frame ref for the original var.  */
1987 
1988   if (TREE_CODE (*stmt) == BIND_EXPR)
1989     {
1990       tree lvar;
1991       for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
1992 	   lvar = DECL_CHAIN (lvar))
1993 	{
1994 	  bool existed;
1995 	  local_var_info &local_var
1996 	    = lvd->local_var_uses->get_or_insert (lvar, &existed);
1997 	  gcc_checking_assert (existed);
1998 
1999 	  /* Re-write the variable's context to be in the actor func.  */
2000 	  DECL_CONTEXT (lvar) = lvd->context;
2001 
2002 	/* For capture proxies, this could include the decl value expr.  */
2003 	if (local_var.is_lambda_capture || local_var.has_value_expr_p)
2004 	  {
2005 	    tree ve = DECL_VALUE_EXPR (lvar);
2006 	    cp_walk_tree (&ve, transform_local_var_uses, d, NULL);
2007 	    continue; /* No frame entry for this.  */
2008 	  }
2009 
2010 	  /* TODO: implement selective generation of fields when vars are
2011 	     known not-used.  */
2012 	  if (local_var.field_id == NULL_TREE)
2013 	    continue; /* Wasn't used.  */
2014 
2015 	  tree fld_ref
2016 	    = lookup_member (lvd->coro_frame_type, local_var.field_id,
2017 			     /*protect=*/1, /*want_type=*/0,
2018 			     tf_warning_or_error);
2019 	  tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
2020 				     lvd->actor_frame, fld_ref, NULL_TREE);
2021 	  local_var.field_idx = fld_idx;
2022 	}
2023       /* FIXME: we should be able to do this in the loop above, but (at least
2024 	 for range for) there are cases where the DECL_INITIAL contains
2025 	 forward references.
2026 	 So, now we've built the revised var in the frame, substitute uses of
2027 	 it in initializers and the bind expr body.  */
2028       for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
2029 	   lvar = DECL_CHAIN (lvar))
2030 	{
2031 	  /* we need to walk some of the decl trees, which might contain
2032 	     references to vars replaced at a higher level.  */
2033 	  cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
2034 			NULL);
2035 	  cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
2036 	  cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
2037 			NULL);
2038 	}
2039       cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
2040 
2041       /* Now we have processed and removed references to the original vars,
2042 	 we can drop those from the bind - leaving capture proxies alone.  */
2043       for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;)
2044 	{
2045 	  bool existed;
2046 	  local_var_info &local_var
2047 	    = lvd->local_var_uses->get_or_insert (*pvar, &existed);
2048 	  gcc_checking_assert (existed);
2049 
2050 	  /* Leave lambda closure captures alone, we replace the *this
2051 	     pointer with the frame version and let the normal process
2052 	     deal with the rest.
2053 	     Likewise, variables with their value found elsewhere.
2054 	     Skip past unused ones too.  */
2055 	  if (local_var.is_lambda_capture
2056 	     || local_var.has_value_expr_p
2057 	     || local_var.field_id == NULL_TREE)
2058 	    {
2059 	      pvar = &DECL_CHAIN (*pvar);
2060 	      continue;
2061 	    }
2062 
2063 	  /* Discard this one, we replaced it.  */
2064 	  *pvar = DECL_CHAIN (*pvar);
2065 	}
2066 
2067       *do_subtree = 0; /* We've done the body already.  */
2068       return NULL_TREE;
2069     }
2070 
2071   tree var_decl = *stmt;
2072   /* Look inside cleanups, we don't want to wrap a statement list in a
2073      cleanup.  */
2074   bool needs_cleanup = true;
2075   if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR)
2076     var_decl = TREE_OPERAND (var_decl, 0);
2077   else
2078     needs_cleanup = false;
2079 
2080   /* Look inside the decl_expr for the actual var.  */
2081   bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR;
2082   if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL)
2083     var_decl = DECL_EXPR_DECL (var_decl);
2084   else if (TREE_CODE (var_decl) != VAR_DECL)
2085     return NULL_TREE;
2086 
2087   /* VAR_DECLs that are not recorded can belong to the proxies we've placed
2088      for the promise and coroutine handle(s), to global vars or to compiler
2089      temporaries.  Skip past these, we will handle them later.  */
2090   local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
2091 
2092   if (local_var_i == NULL)
2093     return NULL_TREE;
2094 
2095   if (local_var_i->is_lambda_capture
2096       || local_var_i->is_static
2097       || local_var_i->has_value_expr_p)
2098     return NULL_TREE;
2099 
2100   /* This is our revised 'local' i.e. a frame slot.  */
2101   tree revised = local_var_i->field_idx;
2102   gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context);
2103 
2104   if (decl_expr_p && DECL_INITIAL (var_decl))
2105     {
2106       location_t loc = DECL_SOURCE_LOCATION (var_decl);
2107       tree r
2108 	= cp_build_modify_expr (loc, revised, INIT_EXPR,
2109 				DECL_INITIAL (var_decl), tf_warning_or_error);
2110       if (needs_cleanup)
2111 	r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt));
2112       *stmt = r;
2113     }
2114   else
2115     *stmt = revised;
2116 
2117   if (decl_expr_p)
2118     *do_subtree = 0; /* We've accounted for the nested use.  */
2119   return NULL_TREE;
2120 }
2121 
2122 /* A helper to build the frame DTOR.
2123    [dcl.fct.def.coroutine] / 12
2124    The deallocation function’s name is looked up in the scope of the promise
2125    type.  If this lookup fails, the deallocation function’s name is looked up
2126    in the global scope.  If deallocation function lookup finds both a usual
2127    deallocation function with only a pointer parameter and a usual
2128    deallocation function with both a pointer parameter and a size parameter,
2129    then the selected deallocation function shall be the one with two
2130    parameters.  Otherwise, the selected deallocation function shall be the
2131    function with one parameter.  If no usual deallocation function is found
2132    the program is ill-formed.  The selected deallocation function shall be
2133    called with the address of the block of storage to be reclaimed as its
2134    first argument.  If a deallocation function with a parameter of type
2135    std::size_t is used, the size of the block is passed as the corresponding
2136    argument.  */
2137 
2138 static tree
coro_get_frame_dtor(tree coro_fp,tree orig,tree frame_size,tree promise_type,location_t loc)2139 coro_get_frame_dtor (tree coro_fp, tree orig, tree frame_size,
2140 		     tree promise_type, location_t loc)
2141 {
2142   tree del_coro_fr = NULL_TREE;
2143   tree frame_arg = build1 (CONVERT_EXPR, ptr_type_node, coro_fp);
2144   tree delname = ovl_op_identifier (false, DELETE_EXPR);
2145   tree fns = lookup_promise_method (orig, delname, loc,
2146 					/*musthave=*/false);
2147   if (fns && BASELINK_P (fns))
2148     {
2149       /* Look for sized version first, since this takes precedence.  */
2150       vec<tree, va_gc> *args = make_tree_vector ();
2151       vec_safe_push (args, frame_arg);
2152       vec_safe_push (args, frame_size);
2153       tree dummy_promise = build_dummy_object (promise_type);
2154 
2155       /* It's OK to fail for this one... */
2156       del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2157 					   NULL_TREE, LOOKUP_NORMAL, NULL,
2158 					   tf_none);
2159 
2160       if (!del_coro_fr || del_coro_fr == error_mark_node)
2161 	{
2162 	  release_tree_vector (args);
2163 	  args = make_tree_vector_single (frame_arg);
2164 	  del_coro_fr = build_new_method_call (dummy_promise, fns, &args,
2165 					       NULL_TREE, LOOKUP_NORMAL, NULL,
2166 					       tf_none);
2167 	}
2168 
2169       /* But one of them must succeed, or the program is ill-formed.  */
2170       if (!del_coro_fr || del_coro_fr == error_mark_node)
2171 	{
2172 	  error_at (loc, "%qE is provided by %qT but is not usable with"
2173 		  " the function signature %qD", delname, promise_type, orig);
2174 	  del_coro_fr = error_mark_node;
2175 	}
2176     }
2177   else
2178     {
2179       del_coro_fr = build_op_delete_call (DELETE_EXPR, frame_arg, frame_size,
2180 					  /*global_p=*/true, /*placement=*/NULL,
2181 					  /*alloc_fn=*/NULL,
2182 					  tf_warning_or_error);
2183       if (!del_coro_fr || del_coro_fr == error_mark_node)
2184 	del_coro_fr = error_mark_node;
2185     }
2186   return del_coro_fr;
2187 }
2188 
2189 /* The actor transform.  */
2190 
2191 static void
build_actor_fn(location_t loc,tree coro_frame_type,tree actor,tree fnbody,tree orig,hash_map<tree,param_info> * param_uses,hash_map<tree,local_var_info> * local_var_uses,vec<tree,va_gc> * param_dtor_list,tree resume_fn_field,tree resume_idx_field,unsigned body_count,tree frame_size)2192 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
2193 		tree orig, hash_map<tree, param_info> *param_uses,
2194 		hash_map<tree, local_var_info> *local_var_uses,
2195 		vec<tree, va_gc> *param_dtor_list, tree resume_fn_field,
2196 		tree resume_idx_field, unsigned body_count, tree frame_size)
2197 {
2198   verify_stmt_tree (fnbody);
2199   /* Some things we inherit from the original function.  */
2200   tree handle_type = get_coroutine_handle_type (orig);
2201   tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
2202   tree promise_type = get_coroutine_promise_type (orig);
2203   tree promise_proxy = get_coroutine_promise_proxy (orig);
2204 
2205   /* One param, the coro frame pointer.  */
2206   tree actor_fp = DECL_ARGUMENTS (actor);
2207 
2208   /* We have a definition here.  */
2209   TREE_STATIC (actor) = 1;
2210 
2211   tree actor_outer = push_stmt_list ();
2212   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2213   tree stmt = begin_compound_stmt (BCS_FN_BODY);
2214 
2215   tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
2216   tree top_block = make_node (BLOCK);
2217   BIND_EXPR_BLOCK (actor_bind) = top_block;
2218 
2219   tree continuation = build_lang_decl (VAR_DECL,
2220 				       get_identifier ("actor.continue"),
2221 				       void_coro_handle_type);
2222   DECL_ARTIFICIAL (continuation) = 1;
2223   DECL_IGNORED_P (continuation) = 1;
2224   DECL_CONTEXT (continuation) = actor;
2225   BIND_EXPR_VARS (actor_bind) = continuation;
2226 
2227   /* Link in the block associated with the outer scope of the re-written
2228      function body.  */
2229   tree first = expr_first (fnbody);
2230   gcc_checking_assert (first && TREE_CODE (first) == BIND_EXPR);
2231   tree block = BIND_EXPR_BLOCK (first);
2232   gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
2233   gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
2234   BLOCK_SUPERCONTEXT (block) = top_block;
2235   BLOCK_SUBBLOCKS (top_block) = block;
2236 
2237   add_stmt (actor_bind);
2238   tree actor_body = push_stmt_list ();
2239 
2240   /* The entry point for the actor code from the ramp.  */
2241   tree actor_begin_label
2242     = create_named_label_with_ctx (loc, "actor.begin", actor);
2243   tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
2244 
2245   /* Declare the continuation handle.  */
2246   add_decl_expr (continuation);
2247 
2248   /* Re-write param references in the body, no code should be generated
2249      here.  */
2250   if (DECL_ARGUMENTS (orig))
2251     {
2252       tree arg;
2253       for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
2254 	{
2255 	  bool existed;
2256 	  param_info &parm = param_uses->get_or_insert (arg, &existed);
2257 	  if (!parm.body_uses)
2258 	    continue; /* Wasn't used in the original function body.  */
2259 
2260 	  tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
2261 					/*protect=*/1, /*want_type=*/0,
2262 					tf_warning_or_error);
2263 	  tree fld_idx = build3_loc (loc, COMPONENT_REF, parm.frame_type,
2264 				     actor_frame, fld_ref, NULL_TREE);
2265 
2266 	  /* We keep these in the frame as a regular pointer, so convert that
2267 	   back to the type expected.  */
2268 	  if (parm.pt_ref)
2269 	    fld_idx = build1_loc (loc, CONVERT_EXPR, TREE_TYPE (arg), fld_idx);
2270 
2271 	  int i;
2272 	  tree *puse;
2273 	  FOR_EACH_VEC_ELT (*parm.body_uses, i, puse)
2274 	    *puse = fld_idx;
2275 	}
2276     }
2277 
2278   /* Re-write local vars, similarly.  */
2279   local_vars_transform xform_vars_data
2280     = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
2281   cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
2282 
2283   tree resume_idx_name = get_identifier ("__resume_at");
2284   tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2285 				  tf_warning_or_error);
2286   tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
2287 		     rat_field, NULL_TREE);
2288 
2289   tree ret_label
2290     = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
2291 
2292   tree continue_label
2293     = create_named_label_with_ctx (loc, "actor.continue.ret", actor);
2294 
2295   tree lsb_if = begin_if_stmt ();
2296   tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
2297 		       build_int_cst (short_unsigned_type_node, 1));
2298   chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
2299 		  build_int_cst (short_unsigned_type_node, 0));
2300   finish_if_stmt_cond (chkb0, lsb_if);
2301 
2302   tree destroy_dispatcher = begin_switch_stmt ();
2303   finish_switch_cond (rat, destroy_dispatcher);
2304   tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
2305 				   create_anon_label_with_ctx (loc, actor));
2306   add_stmt (ddeflab);
2307   tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2308   b = coro_build_cvt_void_expr_stmt (b, loc);
2309   add_stmt (b);
2310 
2311   /* The destroy point numbered #1 is special, in that it is reached from a
2312      coroutine that is suspended after re-throwing from unhandled_exception().
2313      This label just invokes the cleanup of promise, param copies and the
2314      frame itself.  */
2315   tree del_promise_label
2316     = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
2317   b = build_case_label (build_int_cst (short_unsigned_type_node, 1), NULL_TREE,
2318 			create_anon_label_with_ctx (loc, actor));
2319   add_stmt (b);
2320   add_stmt (build_stmt (loc, GOTO_EXPR, del_promise_label));
2321 
2322   short unsigned lab_num = 3;
2323   for (unsigned destr_pt = 0; destr_pt < body_count; destr_pt++)
2324     {
2325       tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2326       b = build_case_label (l_num, NULL_TREE,
2327 			    create_anon_label_with_ctx (loc, actor));
2328       add_stmt (b);
2329       b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2330 					l_num);
2331       b = coro_build_cvt_void_expr_stmt (b, loc);
2332       add_stmt (b);
2333       b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
2334       add_stmt (b);
2335       lab_num += 2;
2336     }
2337 
2338   /* Insert the prototype dispatcher.  */
2339   finish_switch_stmt (destroy_dispatcher);
2340 
2341   finish_then_clause (lsb_if);
2342 
2343   tree dispatcher = begin_switch_stmt ();
2344   finish_switch_cond (rat, dispatcher);
2345   b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
2346 			create_anon_label_with_ctx (loc, actor));
2347   add_stmt (b);
2348   b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
2349   add_stmt (b);
2350 
2351   tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
2352 				   create_anon_label_with_ctx (loc, actor));
2353   add_stmt (rdeflab);
2354   b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
2355   b = coro_build_cvt_void_expr_stmt (b, loc);
2356   add_stmt (b);
2357 
2358   lab_num = 2;
2359   /* The final resume should be made to hit the default (trap, UB) entry
2360      although it will be unreachable via the normal entry point, since that
2361      is set to NULL on reaching final suspend.  */
2362   for (unsigned resu_pt = 0; resu_pt < body_count; resu_pt++)
2363     {
2364       tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
2365       b = build_case_label (l_num, NULL_TREE,
2366 			    create_anon_label_with_ctx (loc, actor));
2367       add_stmt (b);
2368       b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
2369 					l_num);
2370       b = coro_build_cvt_void_expr_stmt (b, loc);
2371       add_stmt (b);
2372       b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
2373       add_stmt (b);
2374       lab_num += 2;
2375     }
2376 
2377   /* Insert the prototype dispatcher.  */
2378   finish_switch_stmt (dispatcher);
2379 
2380   finish_if_stmt (lsb_if);
2381 
2382   tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
2383   add_stmt (r);
2384 
2385   /* actor's version of the promise.  */
2386   tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
2387 			     tf_warning_or_error);
2388   tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE, false,
2389 					    tf_warning_or_error);
2390 
2391   /* actor's coroutine 'self handle'.  */
2392   tree ash_m = lookup_member (coro_frame_type, get_identifier ("__self_h"), 1,
2393 			      0, tf_warning_or_error);
2394   tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
2395 					     false, tf_warning_or_error);
2396   /* So construct the self-handle from the frame address.  */
2397   tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
2398 			      0, tf_warning_or_error);
2399 
2400   r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
2401   vec<tree, va_gc> *args = make_tree_vector_single (r);
2402   tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
2403 				    NULL, tf_warning_or_error);
2404   r = build2 (INIT_EXPR, handle_type, ash, hfa);
2405   r = coro_build_cvt_void_expr_stmt (r, loc);
2406   add_stmt (r);
2407   release_tree_vector (args);
2408 
2409   /* Now we know the real promise, and enough about the frame layout to
2410      decide where to put things.  */
2411 
2412   await_xform_data xform
2413     = {actor, actor_frame, promise_proxy, ap, self_h_proxy, ash};
2414 
2415   /* Transform the await expressions in the function body.  Only do each
2416      await tree once!  */
2417   hash_set<tree> pset;
2418   cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
2419 
2420   /* Now replace the promise proxy with its real value.  */
2421   proxy_replace p_data;
2422   p_data.from = promise_proxy;
2423   p_data.to = ap;
2424   cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2425 
2426   /* The rewrite of the function adds code to set the __resume field to
2427      nullptr when the coroutine is done and also the index to zero when
2428      calling an unhandled exception.  These are represented by two proxies
2429      in the function, so rewrite them to the proper frame access.  */
2430   tree resume_m
2431     = lookup_member (coro_frame_type, get_identifier ("__resume"),
2432 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
2433   tree res_x = build_class_member_access_expr (actor_frame, resume_m, NULL_TREE,
2434 					       false, tf_warning_or_error);
2435   p_data.from = resume_fn_field;
2436   p_data.to = res_x;
2437   cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2438 
2439   p_data.from = resume_idx_field;
2440   p_data.to = rat;
2441   cp_walk_tree (&fnbody, replace_proxy, &p_data, NULL);
2442 
2443   /* Add in our function body with the co_returns rewritten to final form.  */
2444   add_stmt (fnbody);
2445 
2446   /* now do the tail of the function.  */
2447   r = build_stmt (loc, LABEL_EXPR, del_promise_label);
2448   add_stmt (r);
2449 
2450   /* Destructors for the things we built explicitly.  */
2451   r = build_special_member_call (ap, complete_dtor_identifier, NULL,
2452 				 promise_type, LOOKUP_NORMAL,
2453 				 tf_warning_or_error);
2454   add_stmt (r);
2455 
2456   tree del_frame_label
2457     = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
2458   r = build_stmt (loc, LABEL_EXPR, del_frame_label);
2459   add_stmt (r);
2460 
2461   /* Here deallocate the frame (if we allocated it), which we will have at
2462      present.  */
2463   tree fnf_m
2464     = lookup_member (coro_frame_type, get_identifier ("__frame_needs_free"), 1,
2465 		     0, tf_warning_or_error);
2466   tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
2467 						false, tf_warning_or_error);
2468 
2469   tree need_free_if = begin_if_stmt ();
2470   fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
2471   tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
2472   finish_if_stmt_cond (cmp, need_free_if);
2473   if (param_dtor_list != NULL)
2474     {
2475       int i;
2476       tree pid;
2477       FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
2478 	{
2479 	  tree m
2480 	    = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
2481 	  tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
2482 						   false, tf_warning_or_error);
2483 	  tree t = TREE_TYPE (a);
2484 	  tree dtor;
2485 	  dtor
2486 	    = build_special_member_call (a, complete_dtor_identifier, NULL, t,
2487 					 LOOKUP_NORMAL, tf_warning_or_error);
2488 	  add_stmt (dtor);
2489 	}
2490     }
2491 
2492   /* Build the frame DTOR.  */
2493   tree del_coro_fr = coro_get_frame_dtor (actor_fp, orig, frame_size,
2494 					  promise_type, loc);
2495   finish_expr_stmt (del_coro_fr);
2496   finish_then_clause (need_free_if);
2497   tree scope = IF_SCOPE (need_free_if);
2498   IF_SCOPE (need_free_if) = NULL;
2499   r = do_poplevel (scope);
2500   add_stmt (r);
2501 
2502   /* done.  */
2503   r = build_stmt (loc, RETURN_EXPR, NULL);
2504   TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
2505   r = maybe_cleanup_point_expr_void (r);
2506   add_stmt (r);
2507 
2508   /* This is the suspend return point.  */
2509   r = build_stmt (loc, LABEL_EXPR, ret_label);
2510   add_stmt (r);
2511 
2512   r = build_stmt (loc, RETURN_EXPR, NULL);
2513   TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this.  */
2514   r = maybe_cleanup_point_expr_void (r);
2515   add_stmt (r);
2516 
2517   /* This is the 'continuation' return point.  For such a case we have a coro
2518      handle (from the await_suspend() call) and we want handle.resume() to
2519      execute as a tailcall allowing arbitrary chaining of coroutines.  */
2520   r = build_stmt (loc, LABEL_EXPR, continue_label);
2521   add_stmt (r);
2522 
2523   /* We want to force a tail-call even for O0/1, so this expands the resume
2524      call into its underlying implementation.  */
2525   tree addr = lookup_member (void_coro_handle_type, coro_address_identifier,
2526 			       1, 0, tf_warning_or_error);
2527   addr = build_new_method_call (continuation, addr, NULL, NULL_TREE,
2528 				  LOOKUP_NORMAL, NULL, tf_warning_or_error);
2529   tree resume = build_call_expr_loc
2530     (loc, builtin_decl_explicit (BUILT_IN_CORO_RESUME), 1, addr);
2531 
2532   /* In order to support an arbitrary number of coroutine continuations,
2533      we must tail call them.  However, some targets do not support indirect
2534      tail calls to arbitrary callees.  See PR94359.  */
2535   CALL_EXPR_TAILCALL (resume) = true;
2536   resume = coro_build_cvt_void_expr_stmt (resume, loc);
2537   add_stmt (resume);
2538 
2539   r = build_stmt (loc, RETURN_EXPR, NULL);
2540   gcc_checking_assert (maybe_cleanup_point_expr_void (r) == r);
2541   add_stmt (r);
2542 
2543   /* We will need to know which resume point number should be encoded.  */
2544   tree res_idx_m
2545     = lookup_member (coro_frame_type, resume_idx_name,
2546 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
2547   tree resume_pt_number
2548     = build_class_member_access_expr (actor_frame, res_idx_m, NULL_TREE, false,
2549 				      tf_warning_or_error);
2550 
2551   /* We've now rewritten the tree and added the initial and final
2552      co_awaits.  Now pass over the tree and expand the co_awaits.  */
2553 
2554   coro_aw_data data = {actor, actor_fp, resume_pt_number, NULL_TREE,
2555 		       ash, del_promise_label, ret_label,
2556 		       continue_label, continuation, 2};
2557   cp_walk_tree (&actor_body, await_statement_expander, &data, NULL);
2558 
2559   BIND_EXPR_BODY (actor_bind) = pop_stmt_list (actor_body);
2560   TREE_SIDE_EFFECTS (actor_bind) = true;
2561 
2562   finish_compound_stmt (stmt);
2563   DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
2564   verify_stmt_tree (DECL_SAVED_TREE (actor));
2565 }
2566 
2567 /* The prototype 'destroy' function :
2568    frame->__resume_at |= 1;
2569    actor (frame);  */
2570 
2571 static void
build_destroy_fn(location_t loc,tree coro_frame_type,tree destroy,tree actor)2572 build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
2573 		  tree actor)
2574 {
2575   /* One param, the coro frame pointer.  */
2576   tree destr_fp = DECL_ARGUMENTS (destroy);
2577 
2578   /* We have a definition here.  */
2579   TREE_STATIC (destroy) = 1;
2580 
2581   tree destr_outer = push_stmt_list ();
2582   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2583   tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
2584 
2585   tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
2586 
2587   tree resume_idx_name = get_identifier ("__resume_at");
2588   tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2589 				  tf_warning_or_error);
2590   tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, destr_frame,
2591 		     rat_field, NULL_TREE);
2592 
2593   /* _resume_at |= 1 */
2594   tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
2595 			  build_int_cst (short_unsigned_type_node, 1));
2596   tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
2597   r = coro_build_cvt_void_expr_stmt (r, loc);
2598   add_stmt (r);
2599 
2600   /* So .. call the actor ..  */
2601   r = build_call_expr_loc (loc, actor, 1, destr_fp);
2602   r = coro_build_cvt_void_expr_stmt (r, loc);
2603   add_stmt (r);
2604 
2605   /* done. */
2606   r = build_stmt (loc, RETURN_EXPR, NULL);
2607   r = maybe_cleanup_point_expr_void (r);
2608   add_stmt (r);
2609 
2610   finish_compound_stmt (dstr_stmt);
2611   DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
2612 }
2613 
2614 /* Helper that returns an identifier for an appended extension to the
2615    current un-mangled function name.  */
2616 
2617 static tree
get_fn_local_identifier(tree orig,const char * append)2618 get_fn_local_identifier (tree orig, const char *append)
2619 {
2620   /* Figure out the bits we need to generate names for the outlined things
2621      For consistency, this needs to behave the same way as
2622      ASM_FORMAT_PRIVATE_NAME does. */
2623   tree nm = DECL_NAME (orig);
2624   const char *sep, *pfx = "";
2625 #ifndef NO_DOT_IN_LABEL
2626   sep = ".";
2627 #else
2628 #ifndef NO_DOLLAR_IN_LABEL
2629   sep = "$";
2630 #else
2631   sep = "_";
2632   pfx = "__";
2633 #endif
2634 #endif
2635 
2636   char *an;
2637   if (DECL_ASSEMBLER_NAME (orig))
2638     an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
2639 		   (char *) 0));
2640   else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
2641 	   && DECL_TI_ARGS (orig))
2642     {
2643       tree tpl_args = DECL_TI_ARGS (orig);
2644       an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
2645       for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
2646 	{
2647 	  tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
2648 	  an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
2649 	}
2650       an = ACONCAT ((an, sep, append, (char *) 0));
2651     }
2652   else
2653     an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
2654 
2655   return get_identifier (an);
2656 }
2657 
2658 /* Build an initial or final await initialized from the promise
2659    initial_suspend or final_suspend expression.  */
2660 
2661 static tree
build_init_or_final_await(location_t loc,bool is_final)2662 build_init_or_final_await (location_t loc, bool is_final)
2663 {
2664   tree suspend_alt = is_final ? coro_final_suspend_identifier
2665 			      : coro_initial_suspend_identifier;
2666 
2667   tree setup_call
2668     = coro_build_promise_expression (current_function_decl, NULL, suspend_alt,
2669 				     loc, NULL, /*musthave=*/true);
2670 
2671   /* Check for noexcept on the final_suspend call.  */
2672   if (flag_exceptions && is_final && setup_call != error_mark_node
2673       && coro_diagnose_throwing_final_aw_expr (setup_call))
2674     return error_mark_node;
2675 
2676   /* So build the co_await for this */
2677   /* For initial/final suspends the call is "a" per [expr.await] 3.2.  */
2678   return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
2679 						    : INITIAL_SUSPEND_POINT));
2680 }
2681 
2682 /* Callback to record the essential data for each await point found in the
2683    function.  */
2684 
2685 static bool
register_await_info(tree await_expr,tree aw_type,tree aw_nam)2686 register_await_info (tree await_expr, tree aw_type, tree aw_nam)
2687 {
2688   bool seen;
2689   suspend_point_info &s
2690     = suspend_points->get_or_insert (await_expr, &seen);
2691   if (seen)
2692     {
2693       warning_at (EXPR_LOCATION (await_expr), 0, "duplicate info for %qE",
2694 		await_expr);
2695       return false;
2696     }
2697   s.awaitable_type = aw_type;
2698   s.await_field_id = aw_nam;
2699   return true;
2700 }
2701 
2702 /* This data set is used when analyzing statements for await expressions.  */
2703 
2704 struct susp_frame_data
2705 {
2706   /* Function-wide.  */
2707   tree *field_list; /* The current coroutine frame field list.  */
2708   tree handle_type; /* The self-handle type for this coroutine.  */
2709   tree fs_label;    /* The destination for co_returns.  */
2710   vec<tree, va_gc> *block_stack; /* Track block scopes.  */
2711   vec<tree, va_gc> *bind_stack;  /* Track current bind expr.  */
2712   unsigned await_number;	 /* Which await in the function.  */
2713   unsigned cond_number;		 /* Which replaced condition in the fn.  */
2714   /* Temporary values for one statement or expression being analyzed.  */
2715   hash_set<tree> captured_temps; /* The suspend captured these temps.  */
2716   vec<tree, va_gc> *to_replace;  /* The VAR decls to replace.  */
2717   hash_set<tree> *truth_aoif_to_expand; /* The set of TRUTH exprs to expand.  */
2718   unsigned saw_awaits;		 /* Count of awaits in this statement  */
2719   bool captures_temporary;	 /* This expr captures temps by ref.  */
2720   bool needs_truth_if_exp;	 /* We must expand a truth_if expression.  */
2721   bool has_awaiter_init;	 /* We must handle initializing an awaiter.  */
2722 };
2723 
2724 /* If this is an await expression, then count it (both uniquely within the
2725    function and locally within a single statement).  */
2726 
2727 static tree
register_awaits(tree * stmt,int *,void * d)2728 register_awaits (tree *stmt, int *, void *d)
2729 {
2730   tree aw_expr = *stmt;
2731 
2732   /* We should have already lowered co_yields to their co_await.  */
2733   gcc_checking_assert (TREE_CODE (aw_expr) != CO_YIELD_EXPR);
2734 
2735   if (TREE_CODE (aw_expr) != CO_AWAIT_EXPR)
2736     return NULL_TREE;
2737 
2738   /* Count how many awaits the current expression contains.  */
2739   susp_frame_data *data = (susp_frame_data *) d;
2740   data->saw_awaits++;
2741   /* Each await suspend context is unique, this is a function-wide value.  */
2742   data->await_number++;
2743 
2744   /* Awaitables should either be user-locals or promoted to coroutine frame
2745      entries at this point, and their initializers should have been broken
2746      out.  */
2747   tree aw = TREE_OPERAND (aw_expr, 1);
2748   gcc_checking_assert (!TREE_OPERAND (aw_expr, 2));
2749 
2750   tree aw_field_type = TREE_TYPE (aw);
2751   tree aw_field_nam = NULL_TREE;
2752   register_await_info (aw_expr, aw_field_type, aw_field_nam);
2753 
2754   /* Rewrite target expressions on the await_suspend () to remove extraneous
2755      cleanups for the awaitables, which are now promoted to frame vars and
2756      managed via that.  */
2757   tree v = TREE_OPERAND (aw_expr, 3);
2758   tree o = TREE_VEC_ELT (v, 1);
2759   if (TREE_CODE (o) == TARGET_EXPR)
2760     TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1));
2761   return NULL_TREE;
2762 }
2763 
2764 /* There are cases where any await expression is relevant.  */
2765 static tree
find_any_await(tree * stmt,int * dosub,void * d)2766 find_any_await (tree *stmt, int *dosub, void *d)
2767 {
2768   if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
2769     {
2770       *dosub = 0; /* We don't need to consider this any further.  */
2771       tree **p = (tree **) d;
2772       *p = stmt;
2773       return *stmt;
2774     }
2775   return NULL_TREE;
2776 }
2777 
2778 static bool
tmp_target_expr_p(tree t)2779 tmp_target_expr_p (tree t)
2780 {
2781   if (TREE_CODE (t) != TARGET_EXPR)
2782     return false;
2783   tree v = TREE_OPERAND (t, 0);
2784   if (!DECL_ARTIFICIAL (v))
2785     return false;
2786   if (DECL_NAME (v))
2787     return false;
2788   return true;
2789 }
2790 
2791 /* Structure to record sub-expressions that need to be handled by the
2792    statement flattener.  */
2793 
2794 struct coro_interesting_subtree
2795 {
2796   tree* entry;
2797   hash_set<tree> *temps_used;
2798 };
2799 
2800 /* tree-walk callback that returns the first encountered sub-expression of
2801    a kind that needs to be handled specifically by the statement flattener.  */
2802 
2803 static tree
find_interesting_subtree(tree * expr_p,int * dosub,void * d)2804 find_interesting_subtree (tree *expr_p, int *dosub, void *d)
2805 {
2806   tree expr = *expr_p;
2807   coro_interesting_subtree *p = (coro_interesting_subtree *)d;
2808   if (TREE_CODE (expr) == CO_AWAIT_EXPR)
2809     {
2810       *dosub = 0; /* We don't need to consider this any further.  */
2811       if (TREE_OPERAND (expr, 2))
2812 	{
2813 	  p->entry = expr_p;
2814 	  return expr;
2815 	}
2816     }
2817   else if (tmp_target_expr_p (expr)
2818 	   && !p->temps_used->contains (expr))
2819     {
2820       p->entry = expr_p;
2821       return expr;
2822     }
2823 
2824   return NULL_TREE;
2825 }
2826 
2827 /* Node for a doubly-linked list of promoted variables and their
2828    initializers.  When the initializer is a conditional expression
2829    the 'then' and 'else' clauses are represented by a linked list
2830    attached to then_cl and else_cl respectively.  */
2831 
2832 struct var_nest_node
2833 {
2834   var_nest_node () = default;
var_nest_nodevar_nest_node2835   var_nest_node (tree v, tree i, var_nest_node *p, var_nest_node *n)
2836     : var(v), init(i), prev(p), next(n), then_cl (NULL), else_cl (NULL)
2837     {
2838       if (p)
2839 	p->next = this;
2840       if (n)
2841 	n->prev = this;
2842     }
2843   tree var;
2844   tree init;
2845   var_nest_node *prev;
2846   var_nest_node *next;
2847   var_nest_node *then_cl;
2848   var_nest_node *else_cl;
2849 };
2850 
2851 /* This is called for single statements from the co-await statement walker.
2852    It checks to see if the statement contains any initializers for awaitables
2853    and if any of these capture items by reference.  */
2854 
2855 static void
flatten_await_stmt(var_nest_node * n,hash_set<tree> * promoted,hash_set<tree> * temps_used,tree * replace_in)2856 flatten_await_stmt (var_nest_node *n, hash_set<tree> *promoted,
2857 		    hash_set<tree> *temps_used, tree *replace_in)
2858 {
2859   bool init_expr = false;
2860   switch (TREE_CODE (n->init))
2861     {
2862       default: break;
2863       /* Compound expressions must be flattened specifically.  */
2864       case COMPOUND_EXPR:
2865 	{
2866 	  tree first = TREE_OPERAND (n->init, 0);
2867 	  n->init = TREE_OPERAND (n->init, 1);
2868 	  var_nest_node *ins
2869 	    = new var_nest_node(NULL_TREE, first, n->prev, n);
2870 	  /* The compiler (but not the user) can generate temporaries with
2871 	     uses in the second arm of a compound expr.  */
2872 	  flatten_await_stmt (ins, promoted, temps_used, &n->init);
2873 	  flatten_await_stmt (n, promoted, temps_used, NULL);
2874 	  /* The two arms have been processed separately.  */
2875 	  return;
2876 	}
2877 	break;
2878       /* Handle conditional expressions.  */
2879       case INIT_EXPR:
2880 	init_expr = true;
2881 	/* FALLTHROUGH */
2882       case MODIFY_EXPR:
2883 	{
2884 	  tree old_expr = TREE_OPERAND (n->init, 1);
2885 	  if (TREE_CODE (old_expr) == COMPOUND_EXPR)
2886 	    {
2887 	      tree first = TREE_OPERAND (old_expr, 0);
2888 	      TREE_OPERAND (n->init, 1) = TREE_OPERAND (old_expr, 1);
2889 	      var_nest_node *ins
2890 		= new var_nest_node(NULL_TREE, first, n->prev, n);
2891 	      flatten_await_stmt (ins, promoted, temps_used,
2892 				  &TREE_OPERAND (n->init, 1));
2893 	      flatten_await_stmt (n, promoted, temps_used, NULL);
2894 	      return;
2895 	    }
2896 	  if (TREE_CODE (old_expr) != COND_EXPR)
2897 	    break;
2898 	  /* Reconstruct x = t ? y : z;
2899 	     as (void) t ? x = y : x = z;  */
2900 	  tree var = TREE_OPERAND (n->init, 0);
2901 	  tree var_type = TREE_TYPE (var);
2902 	  tree cond = COND_EXPR_COND (old_expr);
2903 	  /* We are allowed a void type throw in one or both of the cond
2904 	     expr arms.  */
2905 	  tree then_cl = COND_EXPR_THEN (old_expr);
2906 	  if (!VOID_TYPE_P (TREE_TYPE (then_cl)))
2907 	    {
2908 	      gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2909 	      then_cl
2910 		= build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2911 			  var, then_cl);
2912 	    }
2913 	  tree else_cl = COND_EXPR_ELSE (old_expr);
2914 	  if (!VOID_TYPE_P (TREE_TYPE (else_cl)))
2915 	    {
2916 	      gcc_checking_assert (TREE_CODE (then_cl) != STATEMENT_LIST);
2917 	      else_cl
2918 		= build2 (init_expr ? INIT_EXPR : MODIFY_EXPR, var_type,
2919 			  var, else_cl);
2920 	    }
2921 	  n->init = build3 (COND_EXPR, var_type, cond, then_cl, else_cl);
2922 	}
2923 	/* FALLTHROUGH */
2924       case COND_EXPR:
2925 	{
2926 	  tree *found;
2927 	  tree cond = COND_EXPR_COND (n->init);
2928 	  /* If the condition contains an await expression, then we need to
2929 	     set that first and use a separate var.  */
2930 	  if (cp_walk_tree (&cond, find_any_await, &found, NULL))
2931 	    {
2932 	      tree cond_type = TREE_TYPE (cond);
2933 	      tree cond_var  = build_lang_decl (VAR_DECL, NULL_TREE, cond_type);
2934 	      DECL_ARTIFICIAL (cond_var) = true;
2935 	      layout_decl (cond_var, 0);
2936 	      gcc_checking_assert (!TYPE_NEEDS_CONSTRUCTING (cond_type));
2937 	      cond = build2 (INIT_EXPR, cond_type, cond_var, cond);
2938 	      var_nest_node *ins
2939 		= new var_nest_node (cond_var, cond, n->prev, n);
2940 	      COND_EXPR_COND (n->init) = cond_var;
2941 	      flatten_await_stmt (ins, promoted, temps_used, NULL);
2942 	    }
2943 
2944 	  n->then_cl
2945 	    = new var_nest_node (n->var, COND_EXPR_THEN (n->init), NULL, NULL);
2946 	  n->else_cl
2947 	    = new var_nest_node (n->var, COND_EXPR_ELSE (n->init), NULL, NULL);
2948 	  flatten_await_stmt (n->then_cl, promoted, temps_used, NULL);
2949 	  /* Point to the start of the flattened code.  */
2950 	  while (n->then_cl->prev)
2951 	    n->then_cl = n->then_cl->prev;
2952 	  flatten_await_stmt (n->else_cl, promoted, temps_used, NULL);
2953 	  while (n->else_cl->prev)
2954 	    n->else_cl = n->else_cl->prev;
2955 	  return;
2956 	}
2957 	break;
2958     }
2959   coro_interesting_subtree v = { NULL, temps_used };
2960   tree t = cp_walk_tree (&n->init, find_interesting_subtree, (void *)&v, NULL);
2961   if (!t)
2962     return;
2963   switch (TREE_CODE (t))
2964     {
2965       default: break;
2966       case CO_AWAIT_EXPR:
2967 	{
2968 	  /* Await expressions with initializers have a compiler-temporary
2969 	     as the awaitable.  'promote' this.  */
2970 	  tree var = TREE_OPERAND (t, 1);
2971 	  bool already_present = promoted->add (var);
2972 	  gcc_checking_assert (!already_present);
2973 	  tree init = TREE_OPERAND (t, 2);
2974 	  switch (TREE_CODE (init))
2975 	    {
2976 	      default: break;
2977 	      case INIT_EXPR:
2978 	      case MODIFY_EXPR:
2979 		{
2980 		  tree inner = TREE_OPERAND (init, 1);
2981 		  /* We can have non-lvalue-expressions here, but when we see
2982 		     a target expression, mark it as already used.  */
2983 		  if (TREE_CODE (inner) == TARGET_EXPR)
2984 		    {
2985 		      temps_used->add (inner);
2986 		      gcc_checking_assert
2987 			(TREE_CODE (TREE_OPERAND (inner, 1)) != COND_EXPR);
2988 		    }
2989 		}
2990 		break;
2991 	      case CALL_EXPR:
2992 		/* If this is a call and not a CTOR, then we didn't expect it.  */
2993 		gcc_checking_assert
2994 		  (DECL_CONSTRUCTOR_P (TREE_OPERAND (CALL_EXPR_FN (init), 0)));
2995 		break;
2996 	    }
2997 	  var_nest_node *ins = new var_nest_node (var, init, n->prev, n);
2998 	  TREE_OPERAND (t, 2) = NULL_TREE;
2999 	  flatten_await_stmt (ins, promoted, temps_used, NULL);
3000 	  flatten_await_stmt (n, promoted, temps_used, NULL);
3001 	  return;
3002 	}
3003 	break;
3004       case TARGET_EXPR:
3005 	{
3006 	  /* We have a temporary; promote it, but allow for the idiom in code
3007 	     generated by the compiler like
3008 	     a = (target_expr produces temp, op uses temp).  */
3009 	  tree init = t;
3010 	  temps_used->add (init);
3011 	  tree var_type = TREE_TYPE (init);
3012 	  char *buf = xasprintf ("D.%d", DECL_UID (TREE_OPERAND (init, 0)));
3013 	  tree var = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
3014 	  DECL_ARTIFICIAL (var) = true;
3015 	  free (buf);
3016 	  bool already_present = promoted->add (var);
3017 	  gcc_checking_assert (!already_present);
3018 	  tree inner = TREE_OPERAND (init, 1);
3019 	  gcc_checking_assert (TREE_CODE (inner) != COND_EXPR);
3020 	  if (type_build_ctor_call (var_type))
3021 	    {
3022 	      releasing_vec p_in (make_tree_vector_single (init));
3023 	      init = build_special_member_call (var, complete_ctor_identifier,
3024 						&p_in, var_type, LOOKUP_NORMAL,
3025 						tf_warning_or_error);
3026 	    }
3027 	  else
3028 	    init = build2 (INIT_EXPR, var_type, var, init);
3029 	  /* Simplify for the case that we have an init containing the temp
3030 	     alone.  */
3031 	  if (t == n->init && n->var == NULL_TREE)
3032 	    {
3033 	      n->var = var;
3034 	      proxy_replace pr = {TREE_OPERAND (t, 0), var};
3035 	      cp_walk_tree (&init, replace_proxy, &pr, NULL);
3036 	      n->init = init;
3037 	      if (replace_in)
3038 		cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
3039 	      flatten_await_stmt (n, promoted, temps_used, NULL);
3040 	    }
3041 	  else
3042 	    {
3043 	      var_nest_node *ins
3044 		= new var_nest_node (var, init, n->prev, n);
3045 	      /* We have to replace the target expr... */
3046 	      *v.entry = var;
3047 	      /* ... and any uses of its var.  */
3048 	      proxy_replace pr = {TREE_OPERAND (t, 0), var};
3049 	      cp_walk_tree (&n->init, replace_proxy, &pr, NULL);
3050 	      /* Compiler-generated temporaries can also have uses in
3051 		 following arms of compound expressions, which will be listed
3052 		 in 'replace_in' if present.  */
3053 	      if (replace_in)
3054 		cp_walk_tree (replace_in, replace_proxy, &pr, NULL);
3055 	      flatten_await_stmt (ins, promoted, temps_used, NULL);
3056 	      flatten_await_stmt (n, promoted, temps_used, NULL);
3057 	    }
3058 	  return;
3059 	}
3060 	break;
3061     }
3062 }
3063 
3064 /* Helper for 'process_conditional' that handles recursion into nested
3065    conditionals.  */
3066 
3067 static void
handle_nested_conditionals(var_nest_node * n,vec<tree> & list,hash_map<tree,tree> & map)3068 handle_nested_conditionals (var_nest_node *n, vec<tree>& list,
3069 			    hash_map<tree, tree>& map)
3070 {
3071   do
3072     {
3073       if (n->var && DECL_NAME (n->var))
3074 	{
3075 	  list.safe_push (n->var);
3076 	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (n->var)))
3077 	    {
3078 	      bool existed;
3079 	      tree& flag = map.get_or_insert (n->var, &existed);
3080 	      if (!existed)
3081 		{
3082 		  /* We didn't see this var before and it needs a DTOR, so
3083 		     build a guard variable for it.  */
3084 		  char *nam
3085 		    = xasprintf ("%s_guard",
3086 				 IDENTIFIER_POINTER (DECL_NAME (n->var)));
3087 		  flag = build_lang_decl (VAR_DECL, get_identifier (nam),
3088 					  boolean_type_node);
3089 		  free (nam);
3090 		  DECL_ARTIFICIAL (flag) = true;
3091 		}
3092 
3093 	      /* The initializer for this variable is replaced by a compound
3094 		 expression that performs the init and then records that the
3095 		 variable is live (and the DTOR should be run at the scope
3096 		 exit.  */
3097 	      tree set_flag = build2 (INIT_EXPR, boolean_type_node,
3098 				      flag, boolean_true_node);
3099 	      n->init
3100 		= build2 (COMPOUND_EXPR, boolean_type_node, n->init, set_flag);
3101 	}
3102 	}
3103       if (TREE_CODE (n->init) == COND_EXPR)
3104 	{
3105 	  tree new_then = push_stmt_list ();
3106 	  handle_nested_conditionals (n->then_cl, list, map);
3107 	  new_then = pop_stmt_list (new_then);
3108 	  tree new_else = push_stmt_list ();
3109 	  handle_nested_conditionals (n->else_cl, list, map);
3110 	  new_else = pop_stmt_list (new_else);
3111 	  tree new_if
3112 	    = build4 (IF_STMT, void_type_node, COND_EXPR_COND (n->init),
3113 		      new_then, new_else, NULL_TREE);
3114 	  add_stmt (new_if);
3115 	}
3116       else
3117 	finish_expr_stmt (n->init);
3118       n = n->next;
3119     } while (n);
3120 }
3121 
3122 /* helper for 'maybe_promote_temps'.
3123 
3124    When we have a conditional expression which might embed await expressions
3125    and/or promoted variables, we need to handle it appropriately.
3126 
3127    The linked lists for the 'then' and 'else' clauses in a conditional node
3128    identify the promoted variables (but these cannot be wrapped in a regular
3129    cleanup).
3130 
3131    So recurse through the lists and build up a composite list of captured vars.
3132    Declare these and any guard variables needed to decide if a DTOR should be
3133    run.  Then embed the conditional into a try-finally expression that handles
3134    running each DTOR conditionally on its guard variable.  */
3135 
3136 static void
process_conditional(var_nest_node * n,tree & vlist)3137 process_conditional (var_nest_node *n, tree& vlist)
3138 {
3139   tree init = n->init;
3140   hash_map<tree, tree> var_flags;
3141   vec<tree> var_list = vNULL;
3142   tree new_then = push_stmt_list ();
3143   handle_nested_conditionals (n->then_cl, var_list, var_flags);
3144   new_then = pop_stmt_list (new_then);
3145   tree new_else = push_stmt_list ();
3146   handle_nested_conditionals (n->else_cl, var_list, var_flags);
3147   new_else = pop_stmt_list (new_else);
3148   /* Declare the vars.  There are two loops so that the boolean flags are
3149      grouped in the frame.  */
3150   for (unsigned i = 0; i < var_list.length(); i++)
3151     {
3152       tree var = var_list[i];
3153       DECL_CHAIN (var) = vlist;
3154       vlist = var;
3155       add_decl_expr (var);
3156     }
3157   /* Define the guard flags for variables that need a DTOR.  */
3158   for (unsigned i = 0; i < var_list.length(); i++)
3159     {
3160       tree *flag = var_flags.get (var_list[i]);
3161       if (flag)
3162 	{
3163 	  DECL_INITIAL (*flag) = boolean_false_node;
3164 	  DECL_CHAIN (*flag) = vlist;
3165 	  vlist = *flag;
3166 	  add_decl_expr (*flag);
3167 	}
3168     }
3169   tree new_if
3170     = build4 (IF_STMT, void_type_node, COND_EXPR_COND (init),
3171 	      new_then, new_else, NULL_TREE);
3172   /* Build a set of conditional DTORs.  */
3173   tree final_actions = push_stmt_list ();
3174   while (!var_list.is_empty())
3175     {
3176       tree var = var_list.pop ();
3177       tree *flag = var_flags.get (var);
3178       if (!flag)
3179 	continue;
3180       tree var_type = TREE_TYPE (var);
3181       tree cleanup
3182 	= build_special_member_call (var, complete_dtor_identifier,
3183 				     NULL, var_type, LOOKUP_NORMAL,
3184 				     tf_warning_or_error);
3185       tree cond_cleanup = begin_if_stmt ();
3186       finish_if_stmt_cond (*flag, cond_cleanup);
3187       finish_expr_stmt (cleanup);
3188       finish_then_clause (cond_cleanup);
3189       finish_if_stmt (cond_cleanup);
3190     }
3191   final_actions = pop_stmt_list (final_actions);
3192   tree try_finally
3193     = build2 (TRY_FINALLY_EXPR, void_type_node, new_if, final_actions);
3194   add_stmt (try_finally);
3195 }
3196 
3197 /* Given *STMT, that contains at least one await expression.
3198 
3199    The full expression represented in the original source code will contain
3200    suspension points, but it is still required that the lifetime of temporary
3201    values extends to the end of the expression.
3202 
3203    We already have a mechanism to 'promote' user-authored local variables
3204    to a coroutine frame counterpart (which allows explicit management of the
3205    lifetime across suspensions).  The transform here re-writes STMT into
3206    a bind expression, promotes temporary values into local variables in that
3207    and flattens the statement into a series of cleanups.
3208 
3209    Conditional expressions are re-written to regular 'if' statements.
3210    The cleanups for variables initialized inside a conditional (including
3211    nested cases) are wrapped in a try-finally clause, with guard variables
3212    to determine which DTORs need to be run.  */
3213 
3214 static tree
maybe_promote_temps(tree * stmt,void * d)3215 maybe_promote_temps (tree *stmt, void *d)
3216 {
3217   susp_frame_data *awpts = (susp_frame_data *) d;
3218 
3219   location_t sloc = EXPR_LOCATION (*stmt);
3220   tree expr = *stmt;
3221   /* Strip off uninteresting wrappers.  */
3222   if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3223     expr = TREE_OPERAND (expr, 0);
3224   if (TREE_CODE (expr) == EXPR_STMT)
3225     expr = EXPR_STMT_EXPR (expr);
3226   if (TREE_CODE (expr) == CONVERT_EXPR
3227       && VOID_TYPE_P (TREE_TYPE (expr)))
3228     expr = TREE_OPERAND (expr, 0);
3229   STRIP_NOPS (expr);
3230 
3231   /* We walk the statement trees, flattening it into an ordered list of
3232      variables with initializers and fragments corresponding to compound
3233      expressions, truth or/and if and ternary conditionals.  Conditional
3234      expressions carry a nested list of fragments for the then and else
3235      clauses.  We anchor to the 'bottom' of the fragment list; we will write
3236      a cleanup nest with one shell for each variable initialized.  */
3237   var_nest_node *root = new var_nest_node (NULL_TREE, expr, NULL, NULL);
3238   /* Check to see we didn't promote one twice.  */
3239   hash_set<tree> promoted_vars;
3240   hash_set<tree> used_temps;
3241   flatten_await_stmt (root, &promoted_vars, &used_temps, NULL);
3242 
3243   gcc_checking_assert (root->next == NULL);
3244   tree vlist = NULL_TREE;
3245   var_nest_node *t = root;
3246   /* We build the bind scope expression from the bottom-up.
3247      EXPR_LIST holds the inner expression nest at the current cleanup
3248      level (becoming the final expression list when we've exhausted the
3249      number of sub-expression fragments).  */
3250   tree expr_list = NULL_TREE;
3251   do
3252     {
3253       tree new_list = push_stmt_list ();
3254       /* When we have a promoted variable, then add that to the bind scope
3255 	 and initialize it.  When there's no promoted variable, we just need
3256 	 to run the initializer.
3257 	 If the initializer is a conditional expression, we need to collect
3258 	 and declare any promoted variables nested within it.  DTORs for such
3259 	 variables must be run conditionally too.  */
3260       if (t->var && DECL_NAME (t->var))
3261 	{
3262 	  tree var = t->var;
3263 	  DECL_CHAIN (var) = vlist;
3264 	  vlist = var;
3265 	  add_decl_expr (var);
3266 	  if (TREE_CODE (t->init) == COND_EXPR)
3267 	    process_conditional (t, vlist);
3268 	  else
3269 	    finish_expr_stmt (t->init);
3270 	  tree var_type = TREE_TYPE (var);
3271 	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (var_type))
3272 	    {
3273 	      tree cleanup
3274 		= build_special_member_call (var, complete_dtor_identifier,
3275 					     NULL, var_type, LOOKUP_NORMAL,
3276 					     tf_warning_or_error);
3277 	      tree cl = build_stmt (sloc, CLEANUP_STMT, expr_list, cleanup, var);
3278 	      add_stmt (cl); /* push this onto the level above.  */
3279 	    }
3280 	  else if (expr_list)
3281 	    {
3282 	      if (TREE_CODE (expr_list) != STATEMENT_LIST)
3283 		add_stmt (expr_list);
3284 	      else if (!tsi_end_p (tsi_start (expr_list)))
3285 		add_stmt (expr_list);
3286 	    }
3287 	}
3288       else
3289 	{
3290 	  if (TREE_CODE (t->init) == COND_EXPR)
3291 	    process_conditional (t, vlist);
3292 	  else
3293 	    finish_expr_stmt (t->init);
3294 	  if (expr_list)
3295 	    {
3296 	      if (TREE_CODE (expr_list) != STATEMENT_LIST)
3297 		add_stmt (expr_list);
3298 	      else if (!tsi_end_p (tsi_start (expr_list)))
3299 		add_stmt (expr_list);
3300 	    }
3301 	}
3302       expr_list = pop_stmt_list (new_list);
3303       var_nest_node *old = t;
3304       t = t->prev;
3305       delete old;
3306     } while (t);
3307 
3308   /* Now produce the bind expression containing the 'promoted' temporaries
3309      as its variable list, and the cleanup nest as the statement.  */
3310   tree await_bind = build3_loc (sloc, BIND_EXPR, void_type_node,
3311 				NULL, NULL, NULL);
3312   BIND_EXPR_BODY (await_bind) = expr_list;
3313   BIND_EXPR_VARS (await_bind) = nreverse (vlist);
3314   tree b_block = make_node (BLOCK);
3315   if (!awpts->block_stack->is_empty ())
3316     {
3317       tree s_block = awpts->block_stack->last ();
3318       if (s_block)
3319 	{
3320 	BLOCK_SUPERCONTEXT (b_block) = s_block;
3321 	BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
3322 	BLOCK_SUBBLOCKS (s_block) = b_block;
3323 	}
3324     }
3325   BLOCK_VARS (b_block) = BIND_EXPR_VARS (await_bind) ;
3326   BIND_EXPR_BLOCK (await_bind) = b_block;
3327   TREE_SIDE_EFFECTS (await_bind) = TREE_SIDE_EFFECTS (BIND_EXPR_BODY (await_bind));
3328   *stmt = await_bind;
3329   hash_set<tree> visited;
3330   return cp_walk_tree (stmt, register_awaits, d, &visited);
3331 }
3332 
3333 /* Lightweight callback to determine two key factors:
3334    1) If the statement/expression contains any await expressions.
3335    2) If the statement/expression potentially requires a re-write to handle
3336       TRUTH_{AND,OR}IF_EXPRs since, in most cases, they will need expansion
3337       so that the await expressions are not processed in the case of the
3338       short-circuit arm.
3339 
3340    CO_YIELD expressions are re-written to their underlying co_await.  */
3341 
3342 static tree
analyze_expression_awaits(tree * stmt,int * do_subtree,void * d)3343 analyze_expression_awaits (tree *stmt, int *do_subtree, void *d)
3344 {
3345   susp_frame_data *awpts = (susp_frame_data *) d;
3346 
3347   switch (TREE_CODE (*stmt))
3348     {
3349       default: return NULL_TREE;
3350       case CO_YIELD_EXPR:
3351 	/* co_yield is syntactic sugar, re-write it to co_await.  */
3352 	*stmt = TREE_OPERAND (*stmt, 1);
3353 	/* FALLTHROUGH */
3354       case CO_AWAIT_EXPR:
3355 	awpts->saw_awaits++;
3356 	/* A non-null initializer for the awaiter means we need to expand.  */
3357 	if (TREE_OPERAND (*stmt, 2))
3358 	  awpts->has_awaiter_init = true;
3359 	break;
3360       case TRUTH_ANDIF_EXPR:
3361       case TRUTH_ORIF_EXPR:
3362 	{
3363 	  /* We don't need special action for awaits in the always-executed
3364 	     arm of a TRUTH_IF.  */
3365 	  if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 0),
3366 				       analyze_expression_awaits, d, NULL))
3367 	    return res;
3368 	  /* However, if there are await expressions on the conditionally
3369 	     executed branch, we must expand the TRUTH_IF to ensure that the
3370 	     expanded await expression control-flow is fully contained in the
3371 	     conditionally executed code.  */
3372 	  unsigned aw_count = awpts->saw_awaits;
3373 	  if (tree res = cp_walk_tree (&TREE_OPERAND (*stmt, 1),
3374 				       analyze_expression_awaits, d, NULL))
3375 	    return res;
3376 	  if (awpts->saw_awaits > aw_count)
3377 	    {
3378 	      awpts->truth_aoif_to_expand->add (*stmt);
3379 	      awpts->needs_truth_if_exp = true;
3380 	    }
3381 	  /* We've done the sub-trees here.  */
3382 	  *do_subtree = 0;
3383 	}
3384 	break;
3385     }
3386 
3387   return NULL_TREE; /* Recurse until done.  */
3388 }
3389 
3390 /* Given *EXPR
3391    If EXPR contains a TRUTH_{AND,OR}IF_EXPR, TAOIE with an await expr on
3392    the conditionally executed branch, change this in a ternary operator.
3393 
3394    bool not_expr = TAOIE == TRUTH_ORIF_EXPR ? NOT : NOP;
3395    not_expr (always-exec expr) ? conditionally-exec expr : not_expr;
3396 
3397    Apply this recursively to the condition and the conditionally-exec
3398    branch.  */
3399 
3400 struct truth_if_transform {
3401   tree *orig_stmt;
3402   tree scratch_var;
3403   hash_set<tree> *truth_aoif_to_expand;
3404 };
3405 
3406 static tree
expand_one_truth_if(tree * expr,int * do_subtree,void * d)3407 expand_one_truth_if (tree *expr, int *do_subtree, void *d)
3408 {
3409   truth_if_transform *xform = (truth_if_transform *) d;
3410 
3411   bool needs_not = false;
3412   switch (TREE_CODE (*expr))
3413     {
3414       default: break;
3415       case TRUTH_ORIF_EXPR:
3416 	needs_not = true;
3417 	/* FALLTHROUGH */
3418       case TRUTH_ANDIF_EXPR:
3419 	{
3420 	  if (!xform->truth_aoif_to_expand->contains (*expr))
3421 	    break;
3422 
3423 	  location_t sloc = EXPR_LOCATION (*expr);
3424 	  /* Transform truth expression into a cond expression with
3425 	     * the always-executed arm as the condition.
3426 	     * the conditionally-executed arm as the then clause.
3427 	     * the 'else' clause is fixed: 'true' for ||,'false' for &&.  */
3428 	  tree cond = TREE_OPERAND (*expr, 0);
3429 	  tree test1 = TREE_OPERAND (*expr, 1);
3430 	  tree fixed = needs_not ? boolean_true_node : boolean_false_node;
3431 	  if (needs_not)
3432 	    cond = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3433 	  tree cond_expr
3434 	    = build3_loc (sloc, COND_EXPR, boolean_type_node,
3435 			  cond, test1, fixed);
3436 	  *expr = cond_expr;
3437 	  if (tree res = cp_walk_tree (&COND_EXPR_COND (*expr),
3438 				       expand_one_truth_if, d, NULL))
3439 	    return res;
3440 	  if (tree res = cp_walk_tree (&COND_EXPR_THEN (*expr),
3441 				       expand_one_truth_if, d, NULL))
3442 	    return res;
3443 	  /* We've manually processed necessary sub-trees here.  */
3444 	  *do_subtree = 0;
3445 	}
3446 	break;
3447     }
3448   return NULL_TREE;
3449 }
3450 
3451 /* Helper that adds a new variable of VAR_TYPE to a bind scope BIND, the
3452    name is made up from NAM_ROOT, NAM_VERS.  */
3453 
3454 static tree
add_var_to_bind(tree & bind,tree var_type,const char * nam_root,unsigned nam_vers)3455 add_var_to_bind (tree& bind, tree var_type,
3456 		 const char *nam_root, unsigned nam_vers)
3457 {
3458   tree b_vars = BIND_EXPR_VARS (bind);
3459   /* Build a variable to hold the condition, this will be included in the
3460      frame as a local var.  */
3461   char *nam = xasprintf ("%s.%d", nam_root, nam_vers);
3462   tree newvar = build_lang_decl (VAR_DECL, get_identifier (nam), var_type);
3463   free (nam);
3464   DECL_CHAIN (newvar) = b_vars;
3465   BIND_EXPR_VARS (bind) = newvar;
3466   return newvar;
3467 }
3468 
3469 /* Helper to build and add if (!cond) break;  */
3470 
3471 static void
coro_build_add_if_not_cond_break(tree cond)3472 coro_build_add_if_not_cond_break (tree cond)
3473 {
3474   tree if_stmt = begin_if_stmt ();
3475   tree invert = build1 (TRUTH_NOT_EXPR, boolean_type_node, cond);
3476   finish_if_stmt_cond (invert, if_stmt);
3477   finish_break_stmt ();
3478   finish_then_clause (if_stmt);
3479   finish_if_stmt (if_stmt);
3480 }
3481 
3482 /* Tree walk callback to replace continue statements with goto label.  */
3483 static tree
replace_continue(tree * stmt,int * do_subtree,void * d)3484 replace_continue (tree *stmt, int *do_subtree, void *d)
3485 {
3486   tree expr = *stmt;
3487   if (TREE_CODE (expr) == CLEANUP_POINT_EXPR)
3488     expr = TREE_OPERAND (expr, 0);
3489   if (CONVERT_EXPR_P (expr) && VOID_TYPE_P (expr))
3490     expr = TREE_OPERAND (expr, 0);
3491   STRIP_NOPS (expr);
3492   if (!STATEMENT_CLASS_P (expr))
3493     return NULL_TREE;
3494 
3495   switch (TREE_CODE (expr))
3496     {
3497       /* Unless it's a special case, just walk the subtrees as usual.  */
3498       default: return NULL_TREE;
3499 
3500       case CONTINUE_STMT:
3501 	{
3502 	  tree *label = (tree *)d;
3503 	  location_t loc = EXPR_LOCATION (expr);
3504 	  /* re-write a continue to goto label.  */
3505 	  *stmt = build_stmt (loc, GOTO_EXPR, *label);
3506 	  *do_subtree = 0;
3507 	  return NULL_TREE;
3508 	}
3509 
3510       /* Statements that do not require recursion.  */
3511       case DECL_EXPR:
3512       case BREAK_STMT:
3513       case GOTO_EXPR:
3514       case LABEL_EXPR:
3515       case CASE_LABEL_EXPR:
3516       case ASM_EXPR:
3517       /* These must break recursion.  */
3518       case FOR_STMT:
3519       case WHILE_STMT:
3520       case DO_STMT:
3521 	*do_subtree = 0;
3522 	return NULL_TREE;
3523     }
3524 }
3525 
3526 /* Tree walk callback to analyze, register and pre-process statements that
3527    contain await expressions.  */
3528 
3529 static tree
await_statement_walker(tree * stmt,int * do_subtree,void * d)3530 await_statement_walker (tree *stmt, int *do_subtree, void *d)
3531 {
3532   tree res = NULL_TREE;
3533   susp_frame_data *awpts = (susp_frame_data *) d;
3534 
3535   /* Process a statement at a time.  */
3536   if (TREE_CODE (*stmt) == BIND_EXPR)
3537     {
3538       /* For conditional expressions, we might wish to add an artificial var
3539 	 to their containing bind expr.  */
3540       vec_safe_push (awpts->bind_stack, *stmt);
3541       /* We might need to insert a new bind expression, and want to link it
3542 	 into the correct scope, so keep a note of the current block scope.  */
3543       tree blk = BIND_EXPR_BLOCK (*stmt);
3544       vec_safe_push (awpts->block_stack, blk);
3545       res = cp_walk_tree (&BIND_EXPR_BODY (*stmt), await_statement_walker,
3546 			  d, NULL);
3547       awpts->block_stack->pop ();
3548       awpts->bind_stack->pop ();
3549       *do_subtree = 0; /* Done subtrees.  */
3550       return res;
3551     }
3552   else if (TREE_CODE (*stmt) == STATEMENT_LIST)
3553     {
3554       tree_stmt_iterator i;
3555       for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
3556 	{
3557 	  res = cp_walk_tree (tsi_stmt_ptr (i), await_statement_walker,
3558 			      d, NULL);
3559 	  if (res)
3560 	    return res;
3561 	}
3562       *do_subtree = 0; /* Done subtrees.  */
3563       return NULL_TREE;
3564     }
3565 
3566   /* We have something to be handled as a single statement.  */
3567   bool has_cleanup_wrapper = TREE_CODE (*stmt) == CLEANUP_POINT_EXPR;
3568   hash_set<tree> visited;
3569   awpts->saw_awaits = 0;
3570   hash_set<tree> truth_aoif_to_expand;
3571   awpts->truth_aoif_to_expand = &truth_aoif_to_expand;
3572   awpts->needs_truth_if_exp = false;
3573   awpts->has_awaiter_init = false;
3574   tree expr = *stmt;
3575   if (has_cleanup_wrapper)
3576     expr = TREE_OPERAND (expr, 0);
3577   STRIP_NOPS (expr);
3578 
3579   if (STATEMENT_CLASS_P (expr))
3580     switch (TREE_CODE (expr))
3581       {
3582 	/* Unless it's a special case, just walk the subtrees as usual.  */
3583 	default: return NULL_TREE;
3584 
3585 	/* When we have a conditional expression, which contains one or more
3586 	   await expressions, we have to break the condition out into a
3587 	   regular statement so that the control flow introduced by the await
3588 	   transforms can be implemented.  */
3589 	case IF_STMT:
3590 	  {
3591 	    /* Transform 'if (cond with awaits) then stmt1 else stmt2' into
3592 	       bool cond = cond with awaits.
3593 	       if (cond) then stmt1 else stmt2.  */
3594 	    tree if_stmt = *stmt;
3595 	    /* We treat the condition as if it was a stand-alone statement,
3596 	       to see if there are any await expressions which will be analyzed
3597 	       and registered.  */
3598 	    if ((res = cp_walk_tree (&IF_COND (if_stmt),
3599 		analyze_expression_awaits, d, &visited)))
3600 	      return res;
3601 	    if (!awpts->saw_awaits)
3602 	      return NULL_TREE; /* Nothing special to do here.  */
3603 
3604 	    gcc_checking_assert (!awpts->bind_stack->is_empty());
3605 	    tree& bind_expr = awpts->bind_stack->last ();
3606 	    tree newvar = add_var_to_bind (bind_expr, boolean_type_node,
3607 					   "ifcd", awpts->cond_number++);
3608 	    tree insert_list = push_stmt_list ();
3609 	    tree cond_inner = IF_COND (if_stmt);
3610 	    if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3611 	      cond_inner = TREE_OPERAND (cond_inner, 0);
3612 	    add_decl_expr (newvar);
3613 	    location_t sloc = EXPR_LOCATION (IF_COND (if_stmt));
3614 	    /* We want to initialize the new variable with the expression
3615 	       that contains the await(s) and potentially also needs to
3616 	       have truth_if expressions expanded.  */
3617 	    tree new_s = build2_loc (sloc, MODIFY_EXPR, boolean_type_node,
3618 				     newvar, cond_inner);
3619 	    finish_expr_stmt (new_s);
3620 	    IF_COND (if_stmt) = newvar;
3621 	    add_stmt (if_stmt);
3622 	    *stmt = pop_stmt_list (insert_list);
3623 	    /* So now walk the new statement list.  */
3624 	    res = cp_walk_tree (stmt, await_statement_walker, d, NULL);
3625 	    *do_subtree = 0; /* Done subtrees.  */
3626 	    return res;
3627 	  }
3628 	  break;
3629 	case FOR_STMT:
3630 	  {
3631 	    /* for loops only need special treatment if the condition or the
3632 	       iteration expression contain a co_await.  */
3633 	    tree for_stmt = *stmt;
3634 	    /* Sanity check.  */
3635 	    if ((res = cp_walk_tree (&FOR_INIT_STMT (for_stmt),
3636 		analyze_expression_awaits, d, &visited)))
3637 	      return res;
3638 	    gcc_checking_assert (!awpts->saw_awaits);
3639 
3640 	    if ((res = cp_walk_tree (&FOR_COND (for_stmt),
3641 		analyze_expression_awaits, d, &visited)))
3642 	      return res;
3643 	    bool for_cond_await = awpts->saw_awaits != 0;
3644 	    unsigned save_awaits = awpts->saw_awaits;
3645 
3646 	    if ((res = cp_walk_tree (&FOR_EXPR (for_stmt),
3647 		analyze_expression_awaits, d, &visited)))
3648 	      return res;
3649 	    bool for_expr_await = awpts->saw_awaits > save_awaits;
3650 
3651 	    /* If the condition has an await, then we will need to rewrite the
3652 	       loop as
3653 	       for (init expression;true;iteration expression) {
3654 		  condition = await expression;
3655 		  if (condition)
3656 		    break;
3657 		  ...
3658 		}
3659 	    */
3660 	    if (for_cond_await)
3661 	      {
3662 		tree insert_list = push_stmt_list ();
3663 		/* This will be expanded when the revised body is handled.  */
3664 		coro_build_add_if_not_cond_break (FOR_COND (for_stmt));
3665 		/* .. add the original for body.  */
3666 		add_stmt (FOR_BODY (for_stmt));
3667 		/* To make the new for body.  */
3668 		FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3669 		FOR_COND (for_stmt) = boolean_true_node;
3670 	      }
3671 	    /* If the iteration expression has an await, it's a bit more
3672 	       tricky.
3673 	       for (init expression;condition;) {
3674 		 ...
3675 		 iteration_expr_label:
3676 		   iteration expression with await;
3677 	       }
3678 	       but, then we will need to re-write any continue statements into
3679 	       'goto iteration_expr_label:'.
3680 	    */
3681 	    if (for_expr_await)
3682 	      {
3683 		location_t sloc = EXPR_LOCATION (FOR_EXPR (for_stmt));
3684 		tree insert_list = push_stmt_list ();
3685 		/* The original for body.  */
3686 		add_stmt (FOR_BODY (for_stmt));
3687 		char *buf = xasprintf ("for.iter.expr.%u", awpts->cond_number++);
3688 		tree it_expr_label
3689 		  = create_named_label_with_ctx (sloc, buf, NULL_TREE);
3690 		free (buf);
3691 		add_stmt (build_stmt (sloc, LABEL_EXPR, it_expr_label));
3692 		add_stmt (FOR_EXPR (for_stmt));
3693 		FOR_EXPR (for_stmt) = NULL_TREE;
3694 		FOR_BODY (for_stmt) = pop_stmt_list (insert_list);
3695 		/* rewrite continue statements to goto label.  */
3696 		hash_set<tree> visited_continue;
3697 		if ((res = cp_walk_tree (&FOR_BODY (for_stmt),
3698 		     replace_continue, &it_expr_label, &visited_continue)))
3699 		  return res;
3700 	      }
3701 
3702 	    /* So now walk the body statement (list), if there were no await
3703 	       expressions, then this handles the original body - and either
3704 	       way we will have finished with this statement.  */
3705 	    res = cp_walk_tree (&FOR_BODY (for_stmt),
3706 				await_statement_walker, d, NULL);
3707 	    *do_subtree = 0; /* Done subtrees.  */
3708 	    return res;
3709 	  }
3710 	  break;
3711 	case WHILE_STMT:
3712 	  {
3713 	    /* We turn 'while (cond with awaits) stmt' into
3714 	       while (true) {
3715 		  if (!(cond with awaits))
3716 		    break;
3717 		  stmt..
3718 		} */
3719 	    tree while_stmt = *stmt;
3720 	    if ((res = cp_walk_tree (&WHILE_COND (while_stmt),
3721 		analyze_expression_awaits, d, &visited)))
3722 	      return res;
3723 	    if (!awpts->saw_awaits)
3724 	      return NULL_TREE; /* Nothing special to do here.  */
3725 
3726 	    tree insert_list = push_stmt_list ();
3727 	    coro_build_add_if_not_cond_break (WHILE_COND (while_stmt));
3728 	    /* The original while body.  */
3729 	    add_stmt (WHILE_BODY (while_stmt));
3730 	    /* The new while body.  */
3731 	    WHILE_BODY (while_stmt) = pop_stmt_list (insert_list);
3732 	    WHILE_COND (while_stmt) = boolean_true_node;
3733 	    /* So now walk the new statement list.  */
3734 	    res = cp_walk_tree (&WHILE_BODY (while_stmt),
3735 				await_statement_walker, d, NULL);
3736 	    *do_subtree = 0; /* Done subtrees.  */
3737 	    return res;
3738 	  }
3739 	  break;
3740 	case DO_STMT:
3741 	  {
3742 	    /* We turn do stmt while (cond with awaits) into:
3743 	       do {
3744 		  stmt..
3745 		  if (!(cond with awaits))
3746 		    break;
3747 	       } while (true); */
3748 	    tree do_stmt = *stmt;
3749 	    if ((res = cp_walk_tree (&DO_COND (do_stmt),
3750 		analyze_expression_awaits, d, &visited)))
3751 	      return res;
3752 	    if (!awpts->saw_awaits)
3753 	      return NULL_TREE; /* Nothing special to do here.  */
3754 
3755 	    tree insert_list = push_stmt_list ();
3756 	    /* The original do stmt body.  */
3757 	    add_stmt (DO_BODY (do_stmt));
3758 	    coro_build_add_if_not_cond_break (DO_COND (do_stmt));
3759 	    /* The new while body.  */
3760 	    DO_BODY (do_stmt) = pop_stmt_list (insert_list);
3761 	    DO_COND (do_stmt) = boolean_true_node;
3762 	    /* So now walk the new statement list.  */
3763 	    res = cp_walk_tree (&DO_BODY (do_stmt), await_statement_walker,
3764 				d, NULL);
3765 	    *do_subtree = 0; /* Done subtrees.  */
3766 	    return res;
3767 	  }
3768 	  break;
3769 	case SWITCH_STMT:
3770 	  {
3771 	    /* We turn 'switch (cond with awaits) stmt' into
3772 	       switch_type cond = cond with awaits
3773 	       switch (cond) stmt.  */
3774 	    tree sw_stmt = *stmt;
3775 	    if ((res = cp_walk_tree (&SWITCH_STMT_COND (sw_stmt),
3776 		analyze_expression_awaits, d, &visited)))
3777 	      return res;
3778 	    if (!awpts->saw_awaits)
3779 	      return NULL_TREE; /* Nothing special to do here.  */
3780 
3781 	    gcc_checking_assert (!awpts->bind_stack->is_empty());
3782 	    /* Build a variable to hold the condition, this will be
3783 		   included in the frame as a local var.  */
3784 	    tree& bind_expr = awpts->bind_stack->last ();
3785 	    tree sw_type = SWITCH_STMT_TYPE (sw_stmt);
3786 	    tree newvar = add_var_to_bind (bind_expr, sw_type, "swch",
3787 					   awpts->cond_number++);
3788 	    tree insert_list = push_stmt_list ();
3789 	    add_decl_expr (newvar);
3790 
3791 	    tree cond_inner = SWITCH_STMT_COND (sw_stmt);
3792 	    if (TREE_CODE (cond_inner) == CLEANUP_POINT_EXPR)
3793 	      cond_inner = TREE_OPERAND (cond_inner, 0);
3794 	    location_t sloc = EXPR_LOCATION (SWITCH_STMT_COND (sw_stmt));
3795 	    tree new_s = build2_loc (sloc, INIT_EXPR, sw_type, newvar,
3796 				     cond_inner);
3797 	    finish_expr_stmt (new_s);
3798 	    SWITCH_STMT_COND (sw_stmt) = newvar;
3799 	    /* Now add the switch statement with the condition re-
3800 		   written to use the local var.  */
3801 	    add_stmt (sw_stmt);
3802 	    *stmt = pop_stmt_list (insert_list);
3803 	    /* Process the expanded list.  */
3804 	    res = cp_walk_tree (stmt, await_statement_walker,
3805 				d, NULL);
3806 	    *do_subtree = 0; /* Done subtrees.  */
3807 	    return res;
3808 	  }
3809 	  break;
3810 	case CO_RETURN_EXPR:
3811 	  {
3812 	    /* Expand the co_return as per [stmt.return.coroutine]
3813 	       - for co_return;
3814 		{ p.return_void (); goto final_suspend; }
3815 	       - for co_return [void expr];
3816 		{ expr; p.return_void(); goto final_suspend;}
3817 	       - for co_return [non void expr];
3818 		{ p.return_value(expr); goto final_suspend; }  */
3819 	    if ((res = cp_walk_tree (stmt, analyze_expression_awaits,
3820 		 d, &visited)))
3821 	      return res;
3822 	    location_t loc = EXPR_LOCATION (expr);
3823 	    tree call = TREE_OPERAND (expr, 1);
3824 	    expr = TREE_OPERAND (expr, 0);
3825 	    tree ret_list = push_stmt_list ();
3826 	    /* [stmt.return.coroutine], 2.2
3827 	       If expr is present and void, it is placed immediately before
3828 	       the call for return_void;  */
3829 	    tree *maybe_await_stmt = NULL;
3830 	    if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
3831 	      {
3832 		finish_expr_stmt (expr);
3833 		/* If the return argument was a void expression, then any
3834 		   awaits must be contained in that.  */
3835 		maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
3836 	      }
3837 	    /* Insert p.return_{void,value(expr)}.  */
3838 	    finish_expr_stmt (call);
3839 	    /* Absent a return of a void expression, any awaits must be in
3840 	       the parameter to return_value().  */
3841 	    if (!maybe_await_stmt)
3842 	      maybe_await_stmt = tsi_stmt_ptr (tsi_last (ret_list));
3843 	    expr = build1_loc (loc, GOTO_EXPR, void_type_node, awpts->fs_label);
3844 	    finish_expr_stmt (expr);
3845 	    *stmt = pop_stmt_list (ret_list);
3846 	    /* Once this is complete, we will have processed subtrees.  */
3847 	    *do_subtree = 0;
3848 	    if (awpts->saw_awaits)
3849 	      {
3850 		gcc_checking_assert (maybe_await_stmt);
3851 		res = cp_walk_tree (maybe_await_stmt, await_statement_walker,
3852 				    d, NULL);
3853 		if (res)
3854 		  return res;
3855 	      }
3856 	    return NULL_TREE; /* Done.  */
3857 	  }
3858 	break;
3859       }
3860   else if (EXPR_P (expr))
3861     {
3862       if ((res = cp_walk_tree (stmt, analyze_expression_awaits, d, &visited)))
3863 	return res;
3864       *do_subtree = 0; /* Done subtrees.  */
3865       if (!awpts->saw_awaits)
3866 	return NULL_TREE; /* Nothing special to do here.  */
3867 
3868       if (awpts->needs_truth_if_exp)
3869 	{
3870 	  /* If a truth-and/or-if expression has an await expression in the
3871 	     conditionally-taken branch, then it must be rewritten into a
3872 	     regular conditional.  */
3873 	  truth_if_transform xf = {stmt, NULL_TREE, &truth_aoif_to_expand};
3874 	  if ((res = cp_walk_tree (stmt, expand_one_truth_if, &xf, NULL)))
3875 	    return res;
3876 	}
3877       /* Process this statement, which contains at least one await expression
3878 	 to 'promote' temporary values to a coroutine frame slot.  */
3879       return maybe_promote_temps (stmt, d);
3880     }
3881   /* Continue recursion, if needed.  */
3882   return res;
3883 }
3884 
3885 /* For figuring out what param usage we have.  */
3886 
3887 struct param_frame_data
3888 {
3889   tree *field_list;
3890   hash_map<tree, param_info> *param_uses;
3891   hash_set<tree *> *visited;
3892   location_t loc;
3893   bool param_seen;
3894 };
3895 
3896 /* A tree-walk callback that records the use of parameters (to allow for
3897    optimizations where handling unused parameters may be omitted).  */
3898 
3899 static tree
register_param_uses(tree * stmt,int * do_subtree ATTRIBUTE_UNUSED,void * d)3900 register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
3901 {
3902   param_frame_data *data = (param_frame_data *) d;
3903 
3904   /* For lambda closure content, we have to look specifically.  */
3905   if (TREE_CODE (*stmt) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (*stmt))
3906     {
3907       tree t = DECL_VALUE_EXPR (*stmt);
3908       return cp_walk_tree (&t, register_param_uses, d, NULL);
3909     }
3910 
3911   if (TREE_CODE (*stmt) != PARM_DECL)
3912     return NULL_TREE;
3913 
3914   /* If we already saw the containing expression, then we're done.  */
3915   if (data->visited->add (stmt))
3916     return NULL_TREE;
3917 
3918   bool existed;
3919   param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
3920   gcc_checking_assert (existed);
3921 
3922   if (!parm.body_uses)
3923     {
3924       vec_alloc (parm.body_uses, 4);
3925       parm.body_uses->quick_push (stmt);
3926       data->param_seen = true;
3927     }
3928   else
3929     parm.body_uses->safe_push (stmt);
3930 
3931   return NULL_TREE;
3932 }
3933 
3934 /* Small helper for the repetitive task of adding a new field to the coro
3935    frame type.  */
3936 
3937 static tree
coro_make_frame_entry(tree * field_list,const char * name,tree fld_type,location_t loc)3938 coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
3939 		       location_t loc)
3940 {
3941   tree id = get_identifier (name);
3942   tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
3943   DECL_CHAIN (decl) = *field_list;
3944   *field_list = decl;
3945   return id;
3946 }
3947 
3948 /* For recording local variable usage.  */
3949 
3950 struct local_vars_frame_data
3951 {
3952   tree *field_list;
3953   hash_map<tree, local_var_info> *local_var_uses;
3954   unsigned int nest_depth, bind_indx;
3955   location_t loc;
3956   bool saw_capture;
3957   bool local_var_seen;
3958 };
3959 
3960 /* A tree-walk callback that processes one bind expression noting local
3961    variables, and making a coroutine frame slot available for those that
3962    need it, so that they can be 'promoted' across suspension points.  */
3963 
3964 static tree
register_local_var_uses(tree * stmt,int * do_subtree,void * d)3965 register_local_var_uses (tree *stmt, int *do_subtree, void *d)
3966 {
3967   local_vars_frame_data *lvd = (local_vars_frame_data *) d;
3968 
3969   /* As we enter a bind expression - record the vars there and then recurse.
3970      As we exit drop the nest depth.
3971      The bind index is a growing count of how many bind indices we've seen.
3972      We build a space in the frame for each local var.  */
3973 
3974   if (TREE_CODE (*stmt) == BIND_EXPR)
3975     {
3976       lvd->bind_indx++;
3977       lvd->nest_depth++;
3978       tree lvar;
3979       for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
3980 	   lvar = DECL_CHAIN (lvar))
3981 	{
3982 	  bool existed;
3983 	  local_var_info &local_var
3984 	    = lvd->local_var_uses->get_or_insert (lvar, &existed);
3985 	  gcc_checking_assert (!existed);
3986 	  local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
3987 	  tree lvtype = TREE_TYPE (lvar);
3988 	  local_var.frame_type = lvtype;
3989 	  local_var.field_idx = local_var.field_id = NULL_TREE;
3990 
3991 	  /* Make sure that we only present vars to the tests below.  */
3992 	  if (TREE_CODE (lvar) == TYPE_DECL
3993 	      || TREE_CODE (lvar) == NAMESPACE_DECL)
3994 	    continue;
3995 
3996 	  /* We don't move static vars into the frame. */
3997 	  local_var.is_static = TREE_STATIC (lvar);
3998 	  if (local_var.is_static)
3999 	    continue;
4000 
4001 	  lvd->local_var_seen = true;
4002 	  /* If this var is a lambda capture proxy, we want to leave it alone,
4003 	     and later rewrite the DECL_VALUE_EXPR to indirect through the
4004 	     frame copy of the pointer to the lambda closure object.  */
4005 	  local_var.is_lambda_capture = is_capture_proxy (lvar);
4006 	  if (local_var.is_lambda_capture)
4007 	    continue;
4008 
4009 	  /* If a variable has a value expression, then that's what needs
4010 	     to be processed.  */
4011 	  local_var.has_value_expr_p = DECL_HAS_VALUE_EXPR_P (lvar);
4012 	  if (local_var.has_value_expr_p)
4013 	    continue;
4014 
4015 	  /* Make names depth+index unique, so that we can support nested
4016 	     scopes with identically named locals.  */
4017 	  tree lvname = DECL_NAME (lvar);
4018 	  char *buf;
4019 	  if (lvname != NULL_TREE)
4020 	    buf = xasprintf ("__%s.%u.%u", IDENTIFIER_POINTER (lvname),
4021 			     lvd->nest_depth, lvd->bind_indx);
4022 	  else
4023 	    buf = xasprintf ("_D%u.%u.%u", DECL_UID (lvar), lvd->nest_depth,
4024 			     lvd->bind_indx);
4025 	  /* TODO: Figure out if we should build a local type that has any
4026 	     excess alignment or size from the original decl.  */
4027 	  local_var.field_id
4028 	    = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
4029 	  free (buf);
4030 	  /* We don't walk any of the local var sub-trees, they won't contain
4031 	     any bind exprs.  */
4032 	}
4033       cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
4034       *do_subtree = 0; /* We've done this.  */
4035       lvd->nest_depth--;
4036     }
4037   return NULL_TREE;
4038 }
4039 
4040 /* Build, return FUNCTION_DECL node based on ORIG with a type FN_TYPE which has
4041    a single argument of type CORO_FRAME_PTR.  Build the actor function if
4042    ACTOR_P is true, otherwise the destroy. */
4043 
4044 static tree
coro_build_actor_or_destroy_function(tree orig,tree fn_type,tree coro_frame_ptr,bool actor_p)4045 coro_build_actor_or_destroy_function (tree orig, tree fn_type,
4046 				      tree coro_frame_ptr, bool actor_p)
4047 {
4048   location_t loc = DECL_SOURCE_LOCATION (orig);
4049   tree fn
4050     = build_lang_decl (FUNCTION_DECL, copy_node (DECL_NAME (orig)), fn_type);
4051 
4052   /* Allow for locating the ramp (original) function from this one.  */
4053   if (!to_ramp)
4054     to_ramp = hash_map<tree, tree>::create_ggc (10);
4055   to_ramp->put (fn, orig);
4056 
4057   DECL_CONTEXT (fn) = DECL_CONTEXT (orig);
4058   DECL_SOURCE_LOCATION (fn) = loc;
4059   DECL_ARTIFICIAL (fn) = true;
4060   DECL_INITIAL (fn) = error_mark_node;
4061 
4062   tree id = get_identifier ("frame_ptr");
4063   tree fp = build_lang_decl (PARM_DECL, id, coro_frame_ptr);
4064   DECL_CONTEXT (fp) = fn;
4065   DECL_ARG_TYPE (fp) = type_passed_as (coro_frame_ptr);
4066   DECL_ARGUMENTS (fn) = fp;
4067 
4068   /* Copy selected attributes from the original function.  */
4069   TREE_USED (fn) = TREE_USED (orig);
4070   if (DECL_SECTION_NAME (orig))
4071     set_decl_section_name (fn, orig);
4072   /* Copy any alignment that the FE added.  */
4073   if (DECL_ALIGN (orig))
4074     SET_DECL_ALIGN (fn, DECL_ALIGN (orig));
4075   /* Copy any alignment the user added.  */
4076   DECL_USER_ALIGN (fn) = DECL_USER_ALIGN (orig);
4077   /* Apply attributes from the original fn.  */
4078   DECL_ATTRIBUTES (fn) = copy_list (DECL_ATTRIBUTES (orig));
4079 
4080   /* A void return.  */
4081   tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
4082   DECL_CONTEXT (resdecl) = fn;
4083   DECL_ARTIFICIAL (resdecl) = 1;
4084   DECL_IGNORED_P (resdecl) = 1;
4085   DECL_RESULT (fn) = resdecl;
4086 
4087   /* This is a coroutine component.  */
4088   DECL_COROUTINE_P (fn) = 1;
4089 
4090   /* Set up a means to find out if a decl is one of the helpers and, if so,
4091      which one.  */
4092   if (coroutine_info *info = get_coroutine_info (orig))
4093     {
4094       gcc_checking_assert ((actor_p && info->actor_decl == NULL_TREE)
4095 			   || info->destroy_decl == NULL_TREE);
4096       if (actor_p)
4097 	info->actor_decl = fn;
4098       else
4099 	info->destroy_decl = fn;
4100     }
4101   return fn;
4102 }
4103 
4104 /* Re-write the body as per [dcl.fct.def.coroutine] / 5.  */
4105 
4106 static tree
coro_rewrite_function_body(location_t fn_start,tree fnbody,tree orig,tree resume_fn_ptr_type,tree & resume_fn_field,tree & resume_idx_field,tree & fs_label)4107 coro_rewrite_function_body (location_t fn_start, tree fnbody, tree orig,
4108 			    tree resume_fn_ptr_type, tree& resume_fn_field,
4109 			    tree& resume_idx_field, tree& fs_label)
4110 {
4111   /* This will be our new outer scope.  */
4112   tree update_body = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4113   tree top_block = make_node (BLOCK);
4114   BIND_EXPR_BLOCK (update_body) = top_block;
4115   BIND_EXPR_BODY (update_body) = push_stmt_list ();
4116 
4117   /* If the function has a top level bind expression, then connect that
4118      after first making sure we give it a new block.  */
4119   tree first = expr_first (fnbody);
4120   if (first && TREE_CODE (first) == BIND_EXPR)
4121     {
4122       tree block = BIND_EXPR_BLOCK (first);
4123       gcc_checking_assert (block);
4124       gcc_checking_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
4125       gcc_checking_assert (BLOCK_CHAIN (block) == NULL_TREE);
4126       /* Replace the top block to avoid issues with locations for args
4127 	 appearing to be in a non-existent place.  */
4128       tree replace_blk = make_node (BLOCK);
4129       BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
4130       BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
4131       for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
4132 	BLOCK_SUPERCONTEXT (b) = replace_blk;
4133       BIND_EXPR_BLOCK (first) = replace_blk;
4134       /* The top block has one child, so far, and we have now got a
4135 	 superblock.  */
4136       BLOCK_SUPERCONTEXT (replace_blk) = top_block;
4137       BLOCK_SUBBLOCKS (top_block) = replace_blk;
4138     }
4139 
4140   /* Wrap the function body in a try {} catch (...) {} block, if exceptions
4141      are enabled.  */
4142   tree promise = get_coroutine_promise_proxy (orig);
4143   tree var_list = NULL_TREE;
4144   tree initial_await = build_init_or_final_await (fn_start, false);
4145 
4146   /* [stmt.return.coroutine] / 3
4147      If p.return_void() is a valid expression, flowing off the end of a
4148      coroutine is equivalent to a co_return with no operand; otherwise
4149      flowing off the end of a coroutine results in undefined behavior.  */
4150   tree return_void
4151     = get_coroutine_return_void_expr (current_function_decl, fn_start, false);
4152 
4153   /* We will need to be able to set the resume function pointer to nullptr
4154      to signal that the coroutine is 'done'.  */
4155   resume_fn_field
4156     = build_lang_decl (VAR_DECL, get_identifier ("resume.fn.ptr.proxy"),
4157 		       resume_fn_ptr_type);
4158   DECL_ARTIFICIAL (resume_fn_field) = true;
4159   tree zero_resume
4160     = build1 (CONVERT_EXPR, resume_fn_ptr_type, integer_zero_node);
4161   zero_resume
4162     = build2 (INIT_EXPR, resume_fn_ptr_type, resume_fn_field, zero_resume);
4163   /* Likewise, the resume index needs to be reset.  */
4164   resume_idx_field
4165     = build_lang_decl (VAR_DECL, get_identifier ("resume.index.proxy"),
4166 		       short_unsigned_type_node);
4167   DECL_ARTIFICIAL (resume_idx_field) = true;
4168   tree zero_resume_idx = build_int_cst (short_unsigned_type_node, 0);
4169   zero_resume_idx = build2 (INIT_EXPR, short_unsigned_type_node,
4170 			    resume_idx_field, zero_resume_idx);
4171 
4172   if (flag_exceptions)
4173     {
4174       /* Build promise.unhandled_exception();  */
4175       tree ueh
4176 	= coro_build_promise_expression (current_function_decl, promise,
4177 					 coro_unhandled_exception_identifier,
4178 					 fn_start, NULL, /*musthave=*/true);
4179       /* Create and initialize the initial-await-resume-called variable per
4180 	 [dcl.fct.def.coroutine] / 5.3.  */
4181       tree i_a_r_c = build_lang_decl (VAR_DECL, get_identifier ("i_a_r_c"),
4182 				      boolean_type_node);
4183       DECL_ARTIFICIAL (i_a_r_c) = true;
4184       DECL_CHAIN (i_a_r_c) = var_list;
4185       var_list = i_a_r_c;
4186       DECL_INITIAL (i_a_r_c) = boolean_false_node;
4187       add_decl_expr (i_a_r_c);
4188       /* Start the try-catch.  */
4189       tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
4190       add_stmt (tcb);
4191       TRY_STMTS (tcb) = push_stmt_list ();
4192       if (initial_await != error_mark_node)
4193 	{
4194 	  /* Build a compound expression that sets the
4195 	     initial-await-resume-called variable true and then calls the
4196 	     initial suspend expression await resume.  */
4197 	  tree vec = TREE_OPERAND (initial_await, 3);
4198 	  tree aw_r = TREE_VEC_ELT (vec, 2);
4199 	  tree update = build2 (MODIFY_EXPR, boolean_type_node, i_a_r_c,
4200 				boolean_true_node);
4201 	  aw_r = cp_build_compound_expr (update, aw_r, tf_warning_or_error);
4202 	  TREE_VEC_ELT (vec, 2) = aw_r;
4203 	}
4204       /* Add the initial await to the start of the user-authored function.  */
4205       finish_expr_stmt (initial_await);
4206       /* Append the original function body.  */
4207       add_stmt (fnbody);
4208       if (return_void)
4209 	add_stmt (return_void);
4210       TRY_STMTS (tcb) = pop_stmt_list (TRY_STMTS (tcb));
4211       TRY_HANDLERS (tcb) = push_stmt_list ();
4212       /* Mimic what the parser does for the catch.  */
4213       tree handler = begin_handler ();
4214       finish_handler_parms (NULL_TREE, handler); /* catch (...) */
4215 
4216       /* Get the initial await resume called value.  */
4217       tree not_iarc_if = begin_if_stmt ();
4218       tree not_iarc = build1_loc (fn_start, TRUTH_NOT_EXPR,
4219 				  boolean_type_node, i_a_r_c);
4220       finish_if_stmt_cond (not_iarc, not_iarc_if);
4221       /* If the initial await resume called value is false, rethrow...  */
4222       tree rethrow = build_throw (fn_start, NULL_TREE);
4223       TREE_NO_WARNING (rethrow) = true;
4224       finish_expr_stmt (rethrow);
4225       finish_then_clause (not_iarc_if);
4226       tree iarc_scope = IF_SCOPE (not_iarc_if);
4227       IF_SCOPE (not_iarc_if) = NULL;
4228       not_iarc_if = do_poplevel (iarc_scope);
4229       add_stmt (not_iarc_if);
4230       /* ... else call the promise unhandled exception method
4231 	 but first we set done = true and the resume index to 0.
4232 	 If the unhandled exception method returns, then we continue
4233 	 to the final await expression (which duplicates the clearing of
4234 	 the field). */
4235       finish_expr_stmt (zero_resume);
4236       finish_expr_stmt (zero_resume_idx);
4237       ueh = maybe_cleanup_point_expr_void (ueh);
4238       add_stmt (ueh);
4239       finish_handler (handler);
4240       TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
4241     }
4242   else
4243     {
4244       if (pedantic)
4245 	{
4246 	  /* We still try to look for the promise method and warn if it's not
4247 	     present.  */
4248 	  tree ueh_meth
4249 	    = lookup_promise_method (orig, coro_unhandled_exception_identifier,
4250 				     fn_start, /*musthave=*/false);
4251 	  if (!ueh_meth || ueh_meth == error_mark_node)
4252 	    warning_at (fn_start, 0, "no member named %qE in %qT",
4253 			coro_unhandled_exception_identifier,
4254 			get_coroutine_promise_type (orig));
4255 	}
4256       /* Else we don't check and don't care if the method is missing..
4257 	 just add the initial suspend, function and return.  */
4258       finish_expr_stmt (initial_await);
4259       /* Append the original function body.  */
4260       add_stmt (fnbody);
4261       if (return_void)
4262 	add_stmt (return_void);
4263     }
4264 
4265   /* co_return branches to the final_suspend label, so declare that now.  */
4266   fs_label
4267     = create_named_label_with_ctx (fn_start, "final.suspend", NULL_TREE);
4268   add_stmt (build_stmt (fn_start, LABEL_EXPR, fs_label));
4269 
4270   /* Before entering the final suspend point, we signal that this point has
4271      been reached by setting the resume function pointer to zero (this is
4272      what the 'done()' builtin tests) as per the current ABI.  */
4273   finish_expr_stmt (zero_resume);
4274   finish_expr_stmt (build_init_or_final_await (fn_start, true));
4275   BIND_EXPR_BODY (update_body) = pop_stmt_list (BIND_EXPR_BODY (update_body));
4276   BIND_EXPR_VARS (update_body) = nreverse (var_list);
4277   BLOCK_VARS (top_block) = BIND_EXPR_VARS (update_body);
4278 
4279   return update_body;
4280 }
4281 
4282 /* Here we:
4283    a) Check that the function and promise type are valid for a
4284       coroutine.
4285    b) Carry out the initial morph to create the skeleton of the
4286       coroutine ramp function and the rewritten body.
4287 
4288   Assumptions.
4289 
4290   1. We only hit this code once all dependencies are resolved.
4291   2. The function body will be either a bind expr or a statement list
4292   3. That cfun and current_function_decl are valid for the case we're
4293      expanding.
4294   4. 'input_location' will be of the final brace for the function.
4295 
4296  We do something like this:
4297  declare a dummy coro frame.
4298  struct _R_frame {
4299   using handle_type = coro::coroutine_handle<coro1::promise_type>;
4300   void (*__resume)(_R_frame *);
4301   void (*__destroy)(_R_frame *);
4302   coro1::promise_type __p;
4303   bool frame_needs_free; free the coro frame mem if set.
4304   bool i_a_r_c; [dcl.fct.def.coroutine] / 5.3
4305   short __resume_at;
4306   handle_type self_handle;
4307   (maybe) parameter copies.
4308   (maybe) local variables saved (including awaitables)
4309   (maybe) trailing space.
4310  };  */
4311 
4312 bool
morph_fn_to_coro(tree orig,tree * resumer,tree * destroyer)4313 morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
4314 {
4315   gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
4316 
4317   *resumer = error_mark_node;
4318   *destroyer = error_mark_node;
4319   if (!coro_function_valid_p (orig))
4320     {
4321       /* For early errors, we do not want a diagnostic about the missing
4322 	 ramp return value, since the user cannot fix this - a 'return' is
4323 	 not allowed in a coroutine.  */
4324       TREE_NO_WARNING (orig) = true;
4325       /* Discard the body, we can't process it further.  */
4326       pop_stmt_list (DECL_SAVED_TREE (orig));
4327       DECL_SAVED_TREE (orig) = push_stmt_list ();
4328       return false;
4329     }
4330 
4331   /* We can't validly get here with an empty statement list, since there's no
4332      way for the FE to decide it's a coroutine in the absence of any code.  */
4333   tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
4334   gcc_checking_assert (fnbody != NULL_TREE);
4335 
4336   /* We don't have the locus of the opening brace - it's filled in later (and
4337      there doesn't really seem to be any easy way to get at it).
4338      The closing brace is assumed to be input_location.  */
4339   location_t fn_start = DECL_SOURCE_LOCATION (orig);
4340   gcc_rich_location fn_start_loc (fn_start);
4341 
4342   /* Initial processing of the function-body.
4343      If we have no expressions or just an error then punt.  */
4344   tree body_start = expr_first (fnbody);
4345   if (body_start == NULL_TREE || body_start == error_mark_node)
4346     {
4347       DECL_SAVED_TREE (orig) = push_stmt_list ();
4348       append_to_statement_list (fnbody, &DECL_SAVED_TREE (orig));
4349       /* Suppress warnings about the missing return value.  */
4350       TREE_NO_WARNING (orig) = true;
4351       return false;
4352     }
4353 
4354   /* So, we've tied off the original user-authored body in fn_body.
4355 
4356      Start the replacement synthesized ramp body as newbody.
4357      If we encounter a fatal error we might return a now-empty body.
4358 
4359      Note, the returned ramp body is not 'popped', to be compatible with
4360      the way that decl.c handles regular functions, the scope pop is done
4361      in the caller.  */
4362 
4363   tree newbody = push_stmt_list ();
4364   DECL_SAVED_TREE (orig) = newbody;
4365 
4366   /* If our original body is noexcept, then that's what we apply to our
4367      generated ramp, transfer any MUST_NOT_THOW_EXPR to that.  */
4368   bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
4369   if (is_noexcept)
4370     {
4371       /* The function body we will continue with is the single operand to
4372 	 the must-not-throw.  */
4373       fnbody = TREE_OPERAND (body_start, 0);
4374       /* Transfer the must-not-throw to the ramp body.  */
4375       add_stmt (body_start);
4376       /* Re-start the ramp as must-not-throw.  */
4377       TREE_OPERAND (body_start, 0) = push_stmt_list ();
4378     }
4379 
4380   /* If the original function has a return value with a non-trivial DTOR
4381      and the body contains a var with a DTOR that might throw, the decl is
4382      marked "throwing_cleanup".
4383      We do not [in the ramp, which is synthesised here], use any body var
4384      types with DTORs that might throw.
4385      The original body is transformed into the actor function which only
4386      contains void returns, and is also wrapped in a try-catch block.
4387      So (a) the 'throwing_cleanup' is not correct for the ramp and (b) we do
4388      not need to transfer it to the actor which only contains void returns.  */
4389   cp_function_chain->throwing_cleanup = false;
4390 
4391   /* Create the coro frame type, as far as it can be known at this stage.
4392      1. Types we already know.  */
4393 
4394   tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
4395   tree handle_type = get_coroutine_handle_type (orig);
4396   tree promise_type = get_coroutine_promise_type (orig);
4397 
4398   /* 2. Types we need to define or look up.  */
4399 
4400   tree fr_name = get_fn_local_identifier (orig, "frame");
4401   tree coro_frame_type = xref_tag (record_type, fr_name);
4402   DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
4403   tree coro_frame_ptr = build_pointer_type (coro_frame_type);
4404   tree act_des_fn_type
4405     = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
4406   tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
4407 
4408   /* Declare the actor and destroyer function.  */
4409   tree actor = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4410 						     coro_frame_ptr, true);
4411   tree destroy = coro_build_actor_or_destroy_function (orig, act_des_fn_type,
4412 						       coro_frame_ptr, false);
4413 
4414   /* Construct the wrapped function body; we will analyze this to determine
4415      the requirements for the coroutine frame.  */
4416 
4417   tree resume_fn_field = NULL_TREE;
4418   tree resume_idx_field = NULL_TREE;
4419   tree fs_label = NULL_TREE;
4420   fnbody = coro_rewrite_function_body (fn_start, fnbody, orig,
4421 				       act_des_fn_ptr, resume_fn_field,
4422 				       resume_idx_field, fs_label);
4423   /* Build our dummy coro frame layout.  */
4424   coro_frame_type = begin_class_definition (coro_frame_type);
4425 
4426   tree field_list = NULL_TREE;
4427   tree resume_name
4428     = coro_make_frame_entry (&field_list, "__resume",
4429 			     act_des_fn_ptr, fn_start);
4430   tree destroy_name
4431     = coro_make_frame_entry (&field_list, "__destroy",
4432 			     act_des_fn_ptr, fn_start);
4433   tree promise_name
4434     = coro_make_frame_entry (&field_list, "__p", promise_type, fn_start);
4435   tree fnf_name = coro_make_frame_entry (&field_list, "__frame_needs_free",
4436 					 boolean_type_node, fn_start);
4437   tree resume_idx_name
4438     = coro_make_frame_entry (&field_list, "__resume_at",
4439 			     short_unsigned_type_node, fn_start);
4440 
4441   /* We need a handle to this coroutine, which is passed to every
4442      await_suspend().  There's no point in creating it over and over.  */
4443   (void) coro_make_frame_entry (&field_list, "__self_h", handle_type, fn_start);
4444 
4445   /* Now add in fields for function params (if there are any).
4446      We do not attempt elision of copies at this stage, we do analyze the
4447      uses and build worklists to replace those when the state machine is
4448      lowered.  */
4449 
4450   hash_map<tree, param_info> *param_uses = NULL;
4451   if (DECL_ARGUMENTS (orig))
4452     {
4453       /* Build a hash map with an entry for each param.
4454 	  The key is the param tree.
4455 	  Then we have an entry for the frame field name.
4456 	  Then a cache for the field ref when we come to use it.
4457 	  Then a tree list of the uses.
4458 	  The second two entries start out empty - and only get populated
4459 	  when we see uses.  */
4460       param_uses = new hash_map<tree, param_info>;
4461       bool lambda_p = LAMBDA_FUNCTION_P (orig);
4462 
4463       unsigned no_name_parm = 0;
4464       for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4465 	   arg = DECL_CHAIN (arg))
4466 	{
4467 	  bool existed;
4468 	  param_info &parm = param_uses->get_or_insert (arg, &existed);
4469 	  gcc_checking_assert (!existed);
4470 	  parm.body_uses = NULL;
4471 	  tree actual_type = TREE_TYPE (arg);
4472 	  actual_type = complete_type_or_else (actual_type, orig);
4473 	  if (actual_type == NULL_TREE)
4474 	    actual_type = error_mark_node;
4475 	  parm.orig_type = actual_type;
4476 	  parm.by_ref = parm.pt_ref = parm.rv_ref =  false;
4477 	  if (TREE_CODE (actual_type) == REFERENCE_TYPE)
4478 	    {
4479 	      /* If the user passes by reference, then we will save the
4480 		 pointer to the original.  As noted in
4481 		 [dcl.fct.def.coroutine] / 13, if the lifetime of the
4482 		 referenced item ends and then the coroutine is resumed,
4483 		 we have UB; well, the user asked for it.  */
4484 	      if (TYPE_REF_IS_RVALUE (actual_type))
4485 		parm.rv_ref = true;
4486 	      else
4487 		parm.pt_ref = true;
4488 	    }
4489 	  else if (TYPE_REF_P (DECL_ARG_TYPE (arg)))
4490 	    parm.by_ref = true;
4491 
4492 	  parm.frame_type = actual_type;
4493 
4494 	  parm.this_ptr = is_this_parameter (arg);
4495 	  parm.lambda_cobj = lambda_p && DECL_NAME (arg) == closure_identifier;
4496 
4497 	  char *buf;
4498 	  if (DECL_NAME (arg))
4499 	    {
4500 	      tree pname = DECL_NAME (arg);
4501 	      buf = xasprintf ("__parm.%s", IDENTIFIER_POINTER (pname));
4502 	    }
4503 	  else
4504 	    buf = xasprintf ("__unnamed_parm.%d", no_name_parm++);
4505 
4506 	  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (parm.frame_type))
4507 	    {
4508 	      char *gbuf = xasprintf ("%s.live", buf);
4509 	      parm.guard_var
4510 		= build_lang_decl (VAR_DECL, get_identifier (gbuf),
4511 				   boolean_type_node);
4512 	      free (gbuf);
4513 	      DECL_ARTIFICIAL (parm.guard_var) = true;
4514 	      DECL_INITIAL (parm.guard_var) = boolean_false_node;
4515 	      parm.trivial_dtor = false;
4516 	    }
4517 	  else
4518 	    parm.trivial_dtor = true;
4519 	  parm.field_id = coro_make_frame_entry
4520 	    (&field_list, buf, actual_type, DECL_SOURCE_LOCATION (arg));
4521 	  free (buf);
4522 	}
4523 
4524       /* We want to record every instance of param's use, so don't include
4525 	 a 'visited' hash_set on the tree walk, but only record a containing
4526 	 expression once.  */
4527       hash_set<tree *> visited;
4528       param_frame_data param_data
4529 	= {&field_list, param_uses, &visited, fn_start, false};
4530       cp_walk_tree (&fnbody, register_param_uses, &param_data, NULL);
4531     }
4532 
4533   /* We need to know, and inspect, each suspend point in the function
4534      in several places.  It's convenient to place this map out of line
4535      since it's used from tree walk callbacks.  */
4536   suspend_points = new hash_map<tree, suspend_point_info>;
4537 
4538   /* Now insert the data for any body await points, at this time we also need
4539      to promote any temporaries that are captured by reference (to regular
4540      vars) they will get added to the coro frame along with other locals.  */
4541   susp_frame_data body_aw_points
4542     = {&field_list, handle_type, fs_label, NULL, NULL, 0, 0,
4543        hash_set<tree> (), NULL, NULL, 0, false, false, false};
4544   body_aw_points.block_stack = make_tree_vector ();
4545   body_aw_points.bind_stack = make_tree_vector ();
4546   body_aw_points.to_replace = make_tree_vector ();
4547   cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
4548 
4549   /* 4. Now make space for local vars, this is conservative again, and we
4550      would expect to delete unused entries later.  */
4551   hash_map<tree, local_var_info> local_var_uses;
4552   local_vars_frame_data local_vars_data
4553     = {&field_list, &local_var_uses, 0, 0, fn_start, false, false};
4554   cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
4555 
4556   /* Tie off the struct for now, so that we can build offsets to the
4557      known entries.  */
4558   TYPE_FIELDS (coro_frame_type) = field_list;
4559   TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
4560   BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
4561   BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
4562 
4563   coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
4564 
4565   /* Ramp: */
4566   /* Now build the ramp function pieces.  */
4567   tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
4568   add_stmt (ramp_bind);
4569   tree ramp_body = push_stmt_list ();
4570 
4571   tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"),
4572 				  coro_frame_ptr);
4573   tree varlist = coro_fp;
4574 
4575   /* To signal that we need to cleanup copied function args.  */
4576   if (flag_exceptions && DECL_ARGUMENTS (orig))
4577     for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4578 	arg = DECL_CHAIN (arg))
4579       {
4580 	param_info *parm_i = param_uses->get (arg);
4581 	gcc_checking_assert (parm_i);
4582 	if (parm_i->trivial_dtor)
4583 	  continue;
4584 	DECL_CHAIN (parm_i->guard_var) = varlist;
4585 	varlist = parm_i->guard_var;
4586       }
4587 
4588   /* Signal that we need to clean up the promise object on exception.  */
4589   tree coro_promise_live
4590    = build_lang_decl (VAR_DECL, get_identifier ("coro.promise.live"),
4591 		      boolean_type_node);
4592   DECL_ARTIFICIAL (coro_promise_live) = true;
4593   DECL_CHAIN (coro_promise_live) = varlist;
4594   varlist = coro_promise_live;
4595   DECL_INITIAL (coro_promise_live) = boolean_false_node;
4596   /* When the get-return-object is in the RETURN slot, we need to arrange for
4597      cleanup on exception.  */
4598   tree coro_gro_live
4599    = build_lang_decl (VAR_DECL, get_identifier ("coro.gro.live"),
4600 		      boolean_type_node);
4601   DECL_ARTIFICIAL (coro_gro_live) = true;
4602   DECL_CHAIN (coro_gro_live) = varlist;
4603   varlist = coro_gro_live;
4604   DECL_INITIAL (coro_gro_live) = boolean_false_node;
4605 
4606   /* Collected the scope vars we need ... only one for now. */
4607   BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
4608 
4609   /* We're now going to create a new top level scope block for the ramp
4610      function.  */
4611   tree top_block = make_node (BLOCK);
4612 
4613   BIND_EXPR_BLOCK (ramp_bind) = top_block;
4614   BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
4615   BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
4616 
4617   /* The decl_expr for the coro frame pointer, initialize to zero so that we
4618      can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
4619      directly apparently).  This avoids a "used uninitialized" warning.  */
4620   tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4621   DECL_INITIAL (coro_fp) = zeroinit;
4622   add_decl_expr (coro_fp);
4623   if (flag_exceptions && DECL_ARGUMENTS (orig))
4624     for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4625 	arg = DECL_CHAIN (arg))
4626       {
4627 	param_info *parm_i = param_uses->get (arg);
4628 	if (parm_i->trivial_dtor)
4629 	  continue;
4630 	add_decl_expr (parm_i->guard_var);;
4631       }
4632   add_decl_expr (coro_promise_live);
4633   add_decl_expr (coro_gro_live);
4634 
4635   /* The CO_FRAME internal function is a mechanism to allow the middle end
4636      to adjust the allocation in response to optimizations.  We provide the
4637      current conservative estimate of the frame size (as per the current)
4638      computed layout.  */
4639   tree frame_size = TYPE_SIZE_UNIT (coro_frame_type);
4640   tree resizeable
4641     = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
4642 				    frame_size, coro_fp);
4643 
4644   /* [dcl.fct.def.coroutine] / 10 (part1)
4645     The unqualified-id get_return_object_on_allocation_failure is looked up
4646     in the scope of the promise type by class member access lookup.  */
4647 
4648   /* We don't require this, so coro_build_promise_expression can return NULL,
4649      but, if the lookup succeeds, then the function must be usable.  */
4650   tree dummy_promise = build_dummy_object (get_coroutine_promise_type (orig));
4651   tree grooaf
4652     = coro_build_promise_expression (orig, dummy_promise,
4653 				     coro_gro_on_allocation_fail_identifier,
4654 				     fn_start, NULL, /*musthave=*/false);
4655 
4656   /* however, should that fail, returning an error, the later stages can't
4657      handle the erroneous expression, so we reset the call as if it was
4658      absent.  */
4659   if (grooaf == error_mark_node)
4660     grooaf = NULL_TREE;
4661 
4662   /* Allocate the frame, this has several possibilities:
4663      [dcl.fct.def.coroutine] / 9 (part 1)
4664      The allocation function’s name is looked up in the scope of the promise
4665      type.  It's not a failure for it to be absent see part 4, below.  */
4666 
4667   tree nwname = ovl_op_identifier (false, NEW_EXPR);
4668   tree new_fn = NULL_TREE;
4669 
4670   if (TYPE_HAS_NEW_OPERATOR (promise_type))
4671     {
4672       tree fns = lookup_promise_method (orig, nwname, fn_start,
4673 					/*musthave=*/true);
4674       /* [dcl.fct.def.coroutine] / 9 (part 2)
4675 	If the lookup finds an allocation function in the scope of the promise
4676 	type, overload resolution is performed on a function call created by
4677 	assembling an argument list.  The first argument is the amount of space
4678 	requested, and has type std::size_t.  The succeeding arguments are
4679 	those of the original function.  */
4680       vec<tree, va_gc> *args = make_tree_vector ();
4681       vec_safe_push (args, resizeable); /* Space needed.  */
4682 
4683       for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4684 	   arg = DECL_CHAIN (arg))
4685 	{
4686 	  param_info *parm_i = param_uses->get (arg);
4687 	  gcc_checking_assert (parm_i);
4688 	  if (parm_i->this_ptr || parm_i->lambda_cobj)
4689 	    {
4690 	      /* We pass a reference to *this to the allocator lookup.  */
4691 	      tree tt = TREE_TYPE (TREE_TYPE (arg));
4692 	      tree this_ref = build1 (INDIRECT_REF, tt, arg);
4693 	      tt = cp_build_reference_type (tt, false);
4694 	      this_ref = convert_to_reference (tt, this_ref, CONV_STATIC,
4695 					       LOOKUP_NORMAL , NULL_TREE,
4696 					       tf_warning_or_error);
4697 	      vec_safe_push (args, this_ref);
4698 	    }
4699 	  else
4700 	    vec_safe_push (args, arg);
4701 	}
4702 
4703       /* Note the function selected; we test to see if it's NOTHROW.  */
4704       tree func;
4705       /* Failure is not an error for this attempt.  */
4706       new_fn = build_new_method_call (dummy_promise, fns, &args, NULL,
4707 				      LOOKUP_NORMAL, &func, tf_none);
4708       release_tree_vector (args);
4709 
4710       if (new_fn == error_mark_node)
4711 	{
4712 	  /* [dcl.fct.def.coroutine] / 9 (part 3)
4713 	    If no viable function is found, overload resolution is performed
4714 	    again on a function call created by passing just the amount of
4715 	    space required as an argument of type std::size_t.  */
4716 	  args = make_tree_vector_single (resizeable); /* Space needed.  */
4717 	  new_fn = build_new_method_call (dummy_promise, fns, &args,
4718 					  NULL_TREE, LOOKUP_NORMAL, &func,
4719 					  tf_none);
4720 	  release_tree_vector (args);
4721 	}
4722 
4723      /* However, if the promise provides an operator new, then one of these
4724 	two options must be available.  */
4725     if (new_fn == error_mark_node)
4726       {
4727 	error_at (fn_start, "%qE is provided by %qT but is not usable with"
4728 		  " the function signature %qD", nwname, promise_type, orig);
4729 	new_fn = error_mark_node;
4730       }
4731     else if (grooaf && !TYPE_NOTHROW_P (TREE_TYPE (func)))
4732       error_at (fn_start, "%qE is provided by %qT but %qE is not marked"
4733 		" %<throw()%> or %<noexcept%>", grooaf, promise_type, nwname);
4734     else if (!grooaf && TYPE_NOTHROW_P (TREE_TYPE (func)))
4735       warning_at (fn_start, 0, "%qE is marked %<throw()%> or %<noexcept%> but"
4736 		  " no usable %<get_return_object_on_allocation_failure%>"
4737 		  " is provided by %qT", nwname, promise_type);
4738     }
4739   else /* No operator new in the promise.  */
4740     {
4741       /* [dcl.fct.def.coroutine] / 9 (part 4)
4742 	 If this lookup fails, the allocation function’s name is looked up in
4743 	 the global scope.  */
4744 
4745       vec<tree, va_gc> *args;
4746       /* build_operator_new_call () will insert size needed as element 0 of
4747 	 this, and we might need to append the std::nothrow constant.  */
4748       vec_alloc (args, 2);
4749       if (grooaf)
4750 	{
4751 	  /* [dcl.fct.def.coroutine] / 10 (part 2)
4752 	   If any declarations (of the get return on allocation fail) are
4753 	   found, then the result of a call to an allocation function used
4754 	   to obtain storage for the coroutine state is assumed to return
4755 	   nullptr if it fails to obtain storage and, if a global allocation
4756 	   function is selected, the ::operator new(size_t, nothrow_t) form
4757 	   is used.  The allocation function used in this case shall have a
4758 	   non-throwing noexcept-specification.  So we need std::nothrow.  */
4759 	  tree std_nt = lookup_qualified_name (std_node,
4760 					       get_identifier ("nothrow"),
4761 					       LOOK_want::NORMAL,
4762 					       /*complain=*/true);
4763 	  if (!std_nt || std_nt == error_mark_node)
4764 	    error_at (fn_start, "%qE is provided by %qT but %<std::nothrow%> "
4765 		      "cannot be found", grooaf, promise_type);
4766 	  vec_safe_push (args, std_nt);
4767 	}
4768 
4769       /* If we get to this point, we must succeed in looking up the global
4770 	 operator new for the params provided.  Extract a simplified version
4771 	 of the machinery from build_operator_new_call.  This can update the
4772 	 frame size.  */
4773       tree cookie = NULL;
4774       new_fn = build_operator_new_call (nwname, &args, &frame_size, &cookie,
4775 					/*align_arg=*/NULL,
4776 					/*size_check=*/NULL, /*fn=*/NULL,
4777 					tf_warning_or_error);
4778       resizeable = build_call_expr_internal_loc
4779 	(fn_start, IFN_CO_FRAME, size_type_node, 2, frame_size, coro_fp);
4780       /* If the operator call fails for some reason, then don't try to
4781 	 amend it.  */
4782       if (new_fn != error_mark_node)
4783 	CALL_EXPR_ARG (new_fn, 0) = resizeable;
4784 
4785       release_tree_vector (args);
4786     }
4787 
4788   tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
4789   tree r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
4790   r = coro_build_cvt_void_expr_stmt (r, fn_start);
4791   add_stmt (r);
4792 
4793   /* If the user provided a method to return an object on alloc fail, then
4794      check the returned pointer and call the func if it's null.
4795      Otherwise, no check, and we fail for noexcept/fno-exceptions cases.  */
4796 
4797   if (grooaf)
4798     {
4799       /* [dcl.fct.def.coroutine] / 10 (part 3)
4800 	 If the allocation function returns nullptr,the coroutine returns
4801 	 control to the caller of the coroutine and the return value is
4802 	 obtained by a call to T::get_return_object_on_allocation_failure(),
4803 	 where T is the promise type.  */
4804 
4805       gcc_checking_assert (same_type_p (fn_return_type, TREE_TYPE (grooaf)));
4806       tree if_stmt = begin_if_stmt ();
4807       tree cond = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
4808       cond = build2 (EQ_EXPR, boolean_type_node, coro_fp, cond);
4809       finish_if_stmt_cond (cond, if_stmt);
4810       if (VOID_TYPE_P (fn_return_type))
4811 	{
4812 	  /* Execute the get-return-object-on-alloc-fail call...  */
4813 	  finish_expr_stmt (grooaf);
4814 	  /* ... but discard the result, since we return void.  */
4815 	  finish_return_stmt (NULL_TREE);
4816 	}
4817       else
4818 	{
4819 	  /* Get the fallback return object.  */
4820 	  r = build_cplus_new (fn_return_type, grooaf, tf_warning_or_error);
4821 	  finish_return_stmt (r);
4822 	}
4823       finish_then_clause (if_stmt);
4824       finish_if_stmt (if_stmt);
4825     }
4826 
4827   /* Up to now any exception thrown will propagate directly to the caller.
4828      This is OK since the only source of such exceptions would be in allocation
4829      of the coroutine frame, and therefore the ramp will not have initialized
4830      any further state.  From here, we will track state that needs explicit
4831      destruction in the case that promise or g.r.o setup fails or an exception
4832      is thrown from the initial suspend expression.  */
4833   tree ramp_cleanup = NULL_TREE;
4834   if (flag_exceptions)
4835     {
4836       ramp_cleanup = build_stmt (fn_start, TRY_BLOCK, NULL, NULL);
4837       add_stmt (ramp_cleanup);
4838       TRY_STMTS (ramp_cleanup) = push_stmt_list ();
4839     }
4840 
4841   /* deref the frame pointer, to use in member access code.  */
4842   tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
4843 
4844   /* For now, once allocation has succeeded we always assume that this needs
4845      destruction, there's no impl. for frame allocation elision.  */
4846   tree fnf_m
4847     = lookup_member (coro_frame_type, fnf_name, 1, 0, tf_warning_or_error);
4848   tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
4849 					       false, tf_warning_or_error);
4850   r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
4851   r = coro_build_cvt_void_expr_stmt (r, fn_start);
4852   add_stmt (r);
4853 
4854   /* Put the resumer and destroyer functions in.  */
4855 
4856   tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
4857   tree resume_m
4858     = lookup_member (coro_frame_type, resume_name,
4859 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4860   tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
4861 						  false, tf_warning_or_error);
4862   r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
4863   r = coro_build_cvt_void_expr_stmt (r, fn_start);
4864   add_stmt (r);
4865 
4866   tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
4867   tree destroy_m
4868     = lookup_member (coro_frame_type, destroy_name,
4869 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4870   tree destroy_x
4871     = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
4872 				      tf_warning_or_error);
4873   r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
4874   r = coro_build_cvt_void_expr_stmt (r, fn_start);
4875   add_stmt (r);
4876 
4877   /* [dcl.fct.def.coroutine] /13
4878      When a coroutine is invoked, a copy is created for each coroutine
4879      parameter.  Each such copy is an object with automatic storage duration
4880      that is direct-initialized from an lvalue referring to the corresponding
4881      parameter if the parameter is an lvalue reference, and from an xvalue
4882      referring to it otherwise.  A reference to a parameter in the function-
4883      body of the coroutine and in the call to the coroutine promise
4884      constructor is replaced by a reference to its copy.  */
4885 
4886   vec<tree, va_gc> *promise_args = NULL; /* So that we can adjust refs.  */
4887 
4888   /* The initialization and destruction of each parameter copy occurs in the
4889      context of the called coroutine.  Initializations of parameter copies are
4890      sequenced before the call to the coroutine promise constructor and
4891      indeterminately sequenced with respect to each other.  The lifetime of
4892      parameter copies ends immediately after the lifetime of the coroutine
4893      promise object ends.  */
4894 
4895   vec<tree, va_gc> *param_dtor_list = NULL;
4896 
4897   if (DECL_ARGUMENTS (orig))
4898     {
4899       promise_args = make_tree_vector ();
4900       for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
4901 	   arg = DECL_CHAIN (arg))
4902 	{
4903 	  bool existed;
4904 	  param_info &parm = param_uses->get_or_insert (arg, &existed);
4905 
4906 	  tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
4907 					/*protect=*/1, /*want_type=*/0,
4908 					tf_warning_or_error);
4909 	  tree fld_idx
4910 	    = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
4911 					      false, tf_warning_or_error);
4912 
4913 	  /* Add this to the promise CTOR arguments list, accounting for
4914 	     refs and special handling for method this ptr.  */
4915 	  if (parm.this_ptr || parm.lambda_cobj)
4916 	    {
4917 	      /* We pass a reference to *this to the param preview.  */
4918 	      tree tt = TREE_TYPE (arg);
4919 	      gcc_checking_assert (POINTER_TYPE_P (tt));
4920 	      tree ct = TREE_TYPE (tt);
4921 	      tree this_ref = build1 (INDIRECT_REF, ct, arg);
4922 	      tree rt = cp_build_reference_type (ct, false);
4923 	      this_ref = convert_to_reference (rt, this_ref, CONV_STATIC,
4924 					       LOOKUP_NORMAL, NULL_TREE,
4925 					       tf_warning_or_error);
4926 	      vec_safe_push (promise_args, this_ref);
4927 	    }
4928 	  else if (parm.rv_ref)
4929 	    vec_safe_push (promise_args, rvalue(fld_idx));
4930 	  else
4931 	    vec_safe_push (promise_args, fld_idx);
4932 
4933 	  if (parm.rv_ref || parm.pt_ref)
4934 	    /* Initialise the frame reference field directly.  */
4935 	    r = build_modify_expr (fn_start, TREE_OPERAND (fld_idx, 0),
4936 				   parm.frame_type, INIT_EXPR,
4937 				   DECL_SOURCE_LOCATION (arg), arg,
4938 				   DECL_ARG_TYPE (arg));
4939 	  else if (type_build_ctor_call (parm.frame_type))
4940 	    {
4941 	      vec<tree, va_gc> *p_in;
4942 	      if (CLASS_TYPE_P (parm.frame_type)
4943 		  && classtype_has_non_deleted_move_ctor (parm.frame_type))
4944 		p_in = make_tree_vector_single (move (arg));
4945 	      else if (lvalue_p (arg))
4946 		p_in = make_tree_vector_single (rvalue (arg));
4947 	      else
4948 		p_in = make_tree_vector_single (arg);
4949 	      /* Construct in place or move as relevant.  */
4950 	      r = build_special_member_call (fld_idx, complete_ctor_identifier,
4951 					     &p_in, parm.frame_type,
4952 					     LOOKUP_NORMAL,
4953 					     tf_warning_or_error);
4954 	      release_tree_vector (p_in);
4955 	    }
4956 	  else
4957 	    {
4958 	      if (!same_type_p (parm.frame_type, DECL_ARG_TYPE (arg)))
4959 		r = build1_loc (DECL_SOURCE_LOCATION (arg), CONVERT_EXPR,
4960 				parm.frame_type, arg);
4961 	      else
4962 		r = arg;
4963 	      r = build_modify_expr (fn_start, fld_idx, parm.frame_type,
4964 				     INIT_EXPR, DECL_SOURCE_LOCATION (arg), r,
4965 				     TREE_TYPE (r));
4966 	    }
4967 	  finish_expr_stmt (r);
4968 	  if (!parm.trivial_dtor)
4969 	    {
4970 	      if (param_dtor_list == NULL)
4971 		param_dtor_list = make_tree_vector ();
4972 	      vec_safe_push (param_dtor_list, parm.field_id);
4973 	      /* Cleanup this frame copy on exception.  */
4974 	      parm.fr_copy_dtor
4975 		= build_special_member_call (fld_idx, complete_dtor_identifier,
4976 					     NULL, parm.frame_type,
4977 					     LOOKUP_NORMAL,
4978 					     tf_warning_or_error);
4979 	      /* This var is now live.  */
4980 	      r = build_modify_expr (fn_start, parm.guard_var,
4981 				     boolean_type_node, INIT_EXPR, fn_start,
4982 				     boolean_true_node, boolean_type_node);
4983 	      finish_expr_stmt (r);
4984 	    }
4985 	}
4986     }
4987 
4988   /* Set up the promise.  */
4989   tree promise_m
4990     = lookup_member (coro_frame_type, promise_name,
4991 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
4992 
4993   tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
4994 					   false, tf_warning_or_error);
4995 
4996   tree promise_dtor = NULL_TREE;
4997   if (type_build_ctor_call (promise_type))
4998     {
4999       /* Do a placement new constructor for the promise type (we never call
5000 	 the new operator, just the constructor on the object in place in the
5001 	 frame).
5002 
5003 	 First try to find a constructor with the same parameter list as the
5004 	 original function (if it has params), failing that find a constructor
5005 	 with no parameter list.  */
5006 
5007       if (DECL_ARGUMENTS (orig))
5008 	{
5009 	  r = build_special_member_call (p, complete_ctor_identifier,
5010 					 &promise_args, promise_type,
5011 					 LOOKUP_NORMAL, tf_none);
5012 	  release_tree_vector (promise_args);
5013 	}
5014       else
5015 	r = NULL_TREE;
5016 
5017       if (r == NULL_TREE || r == error_mark_node)
5018 	r = build_special_member_call (p, complete_ctor_identifier, NULL,
5019 				       promise_type, LOOKUP_NORMAL,
5020 				       tf_warning_or_error);
5021 
5022       r = coro_build_cvt_void_expr_stmt (r, fn_start);
5023       finish_expr_stmt (r);
5024 
5025       r = build_modify_expr (fn_start, coro_promise_live, boolean_type_node,
5026 			     INIT_EXPR, fn_start, boolean_true_node,
5027 			     boolean_type_node);
5028       finish_expr_stmt (r);
5029 
5030       promise_dtor
5031 	= build_special_member_call (p, complete_dtor_identifier,
5032 				     NULL, promise_type, LOOKUP_NORMAL,
5033 				     tf_warning_or_error);
5034     }
5035 
5036   /* Set up a new bind context for the GRO.  */
5037   tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
5038   /* Make and connect the scope blocks.  */
5039   tree gro_block = make_node (BLOCK);
5040   BLOCK_SUPERCONTEXT (gro_block) = top_block;
5041   BLOCK_SUBBLOCKS (top_block) = gro_block;
5042   BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
5043   add_stmt (gro_context_bind);
5044 
5045   tree get_ro
5046     = coro_build_promise_expression (orig, p,
5047 				     coro_get_return_object_identifier,
5048 				     fn_start, NULL, /*musthave=*/true);
5049   /* Without a return object we haven't got much clue what's going on.  */
5050   if (get_ro == error_mark_node)
5051     {
5052       BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
5053       DECL_SAVED_TREE (orig) = newbody;
5054       /* Suppress warnings about the missing return value.  */
5055       TREE_NO_WARNING (orig) = true;
5056       return false;
5057     }
5058 
5059   tree gro_context_body = push_stmt_list ();
5060   tree gro_type = TREE_TYPE (get_ro);
5061   bool gro_is_void_p = VOID_TYPE_P (gro_type);
5062 
5063   tree gro = NULL_TREE;
5064   tree gro_bind_vars = NULL_TREE;
5065   /* Used for return objects in the RESULT slot.  */
5066   tree gro_ret_dtor = NULL_TREE;
5067   tree gro_cleanup_stmt = NULL_TREE;
5068   /* We have to sequence the call to get_return_object before initial
5069      suspend.  */
5070   if (gro_is_void_p)
5071     r = get_ro;
5072   else if (same_type_p (gro_type, fn_return_type))
5073     {
5074      /* [dcl.fct.def.coroutine] / 7
5075 	The expression promise.get_return_object() is used to initialize the
5076 	glvalue result or... (see below)
5077 	Construct the return result directly.  */
5078       if (type_build_ctor_call (gro_type))
5079 	{
5080 	  vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
5081 	  r = build_special_member_call (DECL_RESULT (orig),
5082 					 complete_ctor_identifier,
5083 					 &arg, gro_type, LOOKUP_NORMAL,
5084 					 tf_warning_or_error);
5085 	  release_tree_vector (arg);
5086 	}
5087       else
5088 	r = build2_loc (fn_start, INIT_EXPR, gro_type,
5089 			DECL_RESULT (orig), get_ro);
5090 
5091       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5092 	/* If some part of the initalization code (prior to the await_resume
5093 	     of the initial suspend expression), then we need to clean up the
5094 	     return value.  */
5095 	gro_ret_dtor
5096 	  = build_special_member_call (DECL_RESULT (orig),
5097 				       complete_dtor_identifier, NULL,
5098 				       gro_type, LOOKUP_NORMAL,
5099 				       tf_warning_or_error);
5100     }
5101   else
5102     {
5103       /* ... or ... Construct an object that will be used as the single
5104 	param to the CTOR for the return object.  */
5105       gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"), gro_type);
5106       DECL_CONTEXT (gro) = current_scope ();
5107       DECL_ARTIFICIAL (gro) = true;
5108       DECL_IGNORED_P (gro) = true;
5109       add_decl_expr (gro);
5110       gro_bind_vars = gro;
5111       if (type_build_ctor_call (gro_type))
5112 	{
5113 	  vec<tree, va_gc> *arg = make_tree_vector_single (get_ro);
5114 	  r = build_special_member_call (gro, complete_ctor_identifier,
5115 					 &arg, gro_type, LOOKUP_NORMAL,
5116 					 tf_warning_or_error);
5117 	  release_tree_vector (arg);
5118 	}
5119       else
5120 	r = build2_loc (fn_start, INIT_EXPR, gro_type, gro, get_ro);
5121       /* The constructed object might require a cleanup.  */
5122       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (gro_type))
5123 	{
5124 	  gro_cleanup_stmt
5125 	    = build_special_member_call (gro, complete_dtor_identifier,
5126 					 NULL, gro_type, LOOKUP_NORMAL,
5127 					 tf_warning_or_error);
5128 	  gro_cleanup_stmt = build_stmt (input_location, CLEANUP_STMT, NULL,
5129 					 gro_cleanup_stmt, gro);
5130 	}
5131     }
5132   finish_expr_stmt (r);
5133 
5134   if (gro_cleanup_stmt && gro_cleanup_stmt != error_mark_node)
5135     CLEANUP_BODY (gro_cleanup_stmt) = push_stmt_list ();
5136 
5137   /* If we have a live g.r.o in the return slot, then signal this for exception
5138      cleanup.  */
5139   if (gro_ret_dtor)
5140     {
5141        r = build_modify_expr (fn_start, coro_gro_live, boolean_type_node,
5142 			      INIT_EXPR, fn_start, boolean_true_node,
5143 			      boolean_type_node);
5144       finish_expr_stmt (r);
5145     }
5146   /* Initialize the resume_idx_name to 0, meaning "not started".  */
5147   tree resume_idx_m
5148     = lookup_member (coro_frame_type, resume_idx_name,
5149 		     /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
5150   tree resume_idx
5151     = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
5152 				      tf_warning_or_error);
5153   r = build_int_cst (short_unsigned_type_node, 0);
5154   r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
5155   r = coro_build_cvt_void_expr_stmt (r, fn_start);
5156   add_stmt (r);
5157 
5158   /* So .. call the actor ..  */
5159   r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
5160   r = maybe_cleanup_point_expr_void (r);
5161   add_stmt (r);
5162 
5163   /* Switch to using 'input_location' as the loc, since we're now more
5164      logically doing things related to the end of the function.  */
5165 
5166   /* The ramp is done, we just need the return value.
5167      [dcl.fct.def.coroutine] / 7
5168      The expression promise.get_return_object() is used to initialize the
5169      glvalue result or prvalue result object of a call to a coroutine.
5170 
5171      If the 'get return object' is non-void, then we built it before the
5172      promise was constructed.  We now supply a reference to that var,
5173      either as the return value (if it's the same type) or to the CTOR
5174      for an object of the return type.  */
5175 
5176   if (same_type_p (gro_type, fn_return_type))
5177     r = gro_is_void_p ? NULL_TREE : DECL_RESULT (orig);
5178   else
5179     {
5180       if (CLASS_TYPE_P (fn_return_type))
5181 	{
5182 	  /* For class type return objects, we can attempt to construct,
5183 	     even if the gro is void.  */
5184 	  vec<tree, va_gc> *args = NULL;
5185 	  vec<tree, va_gc> **arglist = NULL;
5186 	  if (!gro_is_void_p)
5187 	    {
5188 	      args = make_tree_vector_single (rvalue (gro));
5189 	      arglist = &args;
5190 	    }
5191 	  r = build_special_member_call (NULL_TREE,
5192 					 complete_ctor_identifier, arglist,
5193 					 fn_return_type, LOOKUP_NORMAL,
5194 					 tf_warning_or_error);
5195 	  r = build_cplus_new (fn_return_type, r, tf_warning_or_error);
5196 	  if (args)
5197 	    release_tree_vector (args);
5198 	}
5199       else if (gro_is_void_p)
5200 	{
5201 	  /* We can't initialize a non-class return value from void.  */
5202 	  error_at (input_location, "cannot initialize a return object of type"
5203 		    " %qT with an rvalue of type %<void%>", fn_return_type);
5204 	  r = error_mark_node;
5205 	}
5206       else
5207 	r = build1_loc (input_location, CONVERT_EXPR,
5208 			fn_return_type, rvalue (gro));
5209     }
5210 
5211   finish_return_stmt (r);
5212 
5213   if (gro_cleanup_stmt)
5214     {
5215       CLEANUP_BODY (gro_cleanup_stmt)
5216 	= pop_stmt_list (CLEANUP_BODY (gro_cleanup_stmt));
5217       add_stmt (gro_cleanup_stmt);
5218     }
5219 
5220   /* Finish up the ramp function.  */
5221   BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
5222   BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
5223   TREE_SIDE_EFFECTS (gro_context_bind) = true;
5224 
5225   if (flag_exceptions)
5226     {
5227       TRY_HANDLERS (ramp_cleanup) = push_stmt_list ();
5228       tree handler = begin_handler ();
5229       finish_handler_parms (NULL_TREE, handler); /* catch (...) */
5230 
5231       /* If we have a live G.R.O in the return slot, then run its DTOR.
5232      When the return object is constructed from a separate g.r.o, this is
5233      already handled by its regular cleanup.  */
5234       if (gro_ret_dtor && gro_ret_dtor != error_mark_node)
5235 	{
5236 	  tree gro_d_if = begin_if_stmt ();
5237 	  finish_if_stmt_cond (coro_gro_live, gro_d_if);
5238 	  finish_expr_stmt (gro_ret_dtor);
5239 	  finish_then_clause (gro_d_if);
5240 	  tree gro_d_if_scope = IF_SCOPE (gro_d_if);
5241 	  IF_SCOPE (gro_d_if) = NULL;
5242 	  gro_d_if = do_poplevel (gro_d_if_scope);
5243 	  add_stmt (gro_d_if);
5244 	}
5245 
5246       /* If the promise is live, then run its dtor if that's available.  */
5247       if (promise_dtor && promise_dtor != error_mark_node)
5248 	{
5249 	  tree promise_d_if = begin_if_stmt ();
5250 	  finish_if_stmt_cond (coro_promise_live, promise_d_if);
5251 	  finish_expr_stmt (promise_dtor);
5252 	  finish_then_clause (promise_d_if);
5253 	  tree promise_d_if_scope = IF_SCOPE (promise_d_if);
5254 	  IF_SCOPE (promise_d_if) = NULL;
5255 	  promise_d_if = do_poplevel (promise_d_if_scope);
5256 	  add_stmt (promise_d_if);
5257 	}
5258 
5259       /* Clean up any frame copies of parms with non-trivial dtors.  */
5260       if (DECL_ARGUMENTS (orig))
5261 	for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
5262 	     arg = DECL_CHAIN (arg))
5263 	  {
5264 	    param_info *parm_i = param_uses->get (arg);
5265 	    if (parm_i->trivial_dtor)
5266 	      continue;
5267 	    if (parm_i->fr_copy_dtor && parm_i->fr_copy_dtor != error_mark_node)
5268 	      {
5269 		tree dtor_if = begin_if_stmt ();
5270 		finish_if_stmt_cond (parm_i->guard_var, dtor_if);
5271 		finish_expr_stmt (parm_i->fr_copy_dtor);
5272 		finish_then_clause (dtor_if);
5273 		tree parm_d_if_scope = IF_SCOPE (dtor_if);
5274 		IF_SCOPE (dtor_if) = NULL;
5275 		dtor_if = do_poplevel (parm_d_if_scope);
5276 		add_stmt (dtor_if);
5277 	      }
5278 	  }
5279 
5280       /* We always expect to delete the frame.  */
5281       tree del_coro_fr = coro_get_frame_dtor (coro_fp, orig, frame_size,
5282 					      promise_type, fn_start);
5283       finish_expr_stmt (del_coro_fr);
5284       tree rethrow = build_throw (fn_start, NULL_TREE);
5285       TREE_NO_WARNING (rethrow) = true;
5286       finish_expr_stmt (rethrow);
5287       finish_handler (handler);
5288       TRY_HANDLERS (ramp_cleanup) = pop_stmt_list (TRY_HANDLERS (ramp_cleanup));
5289     }
5290 
5291   BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
5292   TREE_SIDE_EFFECTS (ramp_bind) = true;
5293 
5294   /* Start to build the final functions.
5295 
5296      We push_deferring_access_checks to avoid these routines being seen as
5297      nested by the middle end; we are doing the outlining here.  */
5298 
5299   push_deferring_access_checks (dk_no_check);
5300 
5301   /* Build the actor...  */
5302   build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
5303 		  &local_var_uses, param_dtor_list, resume_fn_field,
5304 		  resume_idx_field, body_aw_points.await_number, frame_size);
5305 
5306   /* Destroyer ... */
5307   build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
5308 
5309   pop_deferring_access_checks ();
5310 
5311   DECL_SAVED_TREE (orig) = newbody;
5312   /* Link our new functions into the list.  */
5313   TREE_CHAIN (destroy) = TREE_CHAIN (orig);
5314   TREE_CHAIN (actor) = destroy;
5315   TREE_CHAIN (orig) = actor;
5316 
5317   *resumer = actor;
5318   *destroyer = destroy;
5319 
5320   delete suspend_points;
5321   suspend_points = NULL;
5322   return true;
5323 }
5324 
5325 #include "gt-cp-coroutines.h"
5326 
5327