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