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