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