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