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