Add error messages for missing methods of awaitable class
[gcc.git] / gcc / cp / coroutines.cc
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 tree find_promise_type (tree);
37 static bool coro_promise_type_found_p (tree, location_t);
38
39 /* GCC C++ coroutines implementation.
40
41 The user authors a function that becomes a coroutine (lazily) by
42 making use of any of the co_await, co_yield or co_return keywords.
43
44 Unlike a regular function, where the activation record is placed on the
45 stack, and is destroyed on function exit, a coroutine has some state that
46 persists between calls - the coroutine frame (analogous to a stack frame).
47
48 We transform the user's function into three pieces:
49 1. A so-called ramp function, that establishes the coroutine frame and
50 begins execution of the coroutine.
51 2. An actor function that contains the state machine corresponding to the
52 user's suspend/resume structure.
53 3. A stub function that calls the actor function in 'destroy' mode.
54
55 The actor function is executed:
56 * from "resume point 0" by the ramp.
57 * from resume point N ( > 0 ) for handle.resume() calls.
58 * from the destroy stub for destroy point N for handle.destroy() calls.
59
60 The functions in this file carry out the necessary analysis of, and
61 transforms to, the AST to perform this.
62
63 The C++ coroutine design makes use of some helper functions that are
64 authored in a so-called "promise" class provided by the user.
65
66 At parse time (or post substitution) the type of the coroutine promise
67 will be determined. At that point, we can look up the required promise
68 class methods and issue diagnostics if they are missing or incorrect. To
69 avoid repeating these actions at code-gen time, we make use of temporary
70 'proxy' variables for the coroutine handle and the promise - which will
71 eventually be instantiated in the coroutine frame.
72
73 Each of the keywords will expand to a code sequence (although co_yield is
74 just syntactic sugar for a co_await).
75
76 We defer the analysis and transformation until template expansion is
77 complete so that we have complete types at that time. */
78
79
80 /* The state that we collect during parsing (and template expansion) for
81 a coroutine. */
82
83 struct GTY((for_user)) coroutine_info
84 {
85 tree function_decl; /* The original function decl. */
86 tree promise_type; /* The cached promise type for this function. */
87 tree handle_type; /* The cached coroutine handle for this function. */
88 tree self_h_proxy; /* A handle instance that is used as the proxy for the
89 one that will eventually be allocated in the coroutine
90 frame. */
91 tree promise_proxy; /* Likewise, a proxy promise instance. */
92 location_t first_coro_keyword; /* The location of the keyword that made this
93 function into a coroutine. */
94 };
95
96 struct coroutine_info_hasher : ggc_ptr_hash<coroutine_info>
97 {
98 typedef tree compare_type; /* We only compare the function decl. */
99 static inline hashval_t hash (coroutine_info *);
100 static inline hashval_t hash (const compare_type &);
101 static inline bool equal (coroutine_info *, coroutine_info *);
102 static inline bool equal (coroutine_info *, const compare_type &);
103 };
104
105 /* This table holds all the collected coroutine state for coroutines in
106 the current translation unit. */
107
108 static GTY (()) hash_table<coroutine_info_hasher> *coroutine_info_table;
109
110 /* We will initialise state lazily. */
111 static bool coro_initialized = false;
112
113 /* Return a hash value for the entry pointed to by INFO.
114 The compare type is a tree, but the only trees we are going use are
115 function decls. We use the DECL_UID as the hash value since that is
116 stable across PCH. */
117
118 hashval_t
119 coroutine_info_hasher::hash (coroutine_info *info)
120 {
121 return DECL_UID (info->function_decl);
122 }
123
124 /* Return a hash value for the compare value COMP. */
125
126 hashval_t
127 coroutine_info_hasher::hash (const compare_type& comp)
128 {
129 return DECL_UID (comp);
130 }
131
132 /* Return true if the entries pointed to by LHS and RHS are for the
133 same coroutine. */
134
135 bool
136 coroutine_info_hasher::equal (coroutine_info *lhs, coroutine_info *rhs)
137 {
138 return lhs->function_decl == rhs->function_decl;
139 }
140
141 bool
142 coroutine_info_hasher::equal (coroutine_info *lhs, const compare_type& rhs)
143 {
144 return lhs->function_decl == rhs;
145 }
146
147 /* Get the existing coroutine_info for FN_DECL, or insert a new one if the
148 entry does not yet exist. */
149
150 coroutine_info *
151 get_or_insert_coroutine_info (tree fn_decl)
152 {
153 gcc_checking_assert (coroutine_info_table != NULL);
154
155 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
156 (fn_decl, coroutine_info_hasher::hash (fn_decl), INSERT);
157
158 if (*slot == NULL)
159 {
160 *slot = new (ggc_cleared_alloc<coroutine_info> ()) coroutine_info ();
161 (*slot)->function_decl = fn_decl;
162 }
163
164 return *slot;
165 }
166
167 /* Get the existing coroutine_info for FN_DECL, fail if it doesn't exist. */
168
169 coroutine_info *
170 get_coroutine_info (tree fn_decl)
171 {
172 gcc_checking_assert (coroutine_info_table != NULL);
173
174 coroutine_info **slot = coroutine_info_table->find_slot_with_hash
175 (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
176 if (slot)
177 return *slot;
178 return NULL;
179 }
180
181 /* We will lazily create all the identifiers that are used by coroutines
182 on the first attempt to lookup the traits. */
183
184 /* Identifiers that are used by all coroutines. */
185
186 static GTY(()) tree coro_traits_identifier;
187 static GTY(()) tree coro_handle_identifier;
188 static GTY(()) tree coro_promise_type_identifier;
189
190 /* Required promise method name identifiers. */
191
192 static GTY(()) tree coro_await_transform_identifier;
193 static GTY(()) tree coro_initial_suspend_identifier;
194 static GTY(()) tree coro_final_suspend_identifier;
195 static GTY(()) tree coro_return_void_identifier;
196 static GTY(()) tree coro_return_value_identifier;
197 static GTY(()) tree coro_yield_value_identifier;
198 static GTY(()) tree coro_resume_identifier;
199 static GTY(()) tree coro_from_address_identifier;
200 static GTY(()) tree coro_get_return_object_identifier;
201 static GTY(()) tree coro_gro_on_allocation_fail_identifier;
202 static GTY(()) tree coro_unhandled_exception_identifier;
203
204 /* Awaitable methods. */
205
206 static GTY(()) tree coro_await_ready_identifier;
207 static GTY(()) tree coro_await_suspend_identifier;
208 static GTY(()) tree coro_await_resume_identifier;
209
210 /* Create the identifiers used by the coroutines library interfaces. */
211
212 static void
213 coro_init_identifiers ()
214 {
215 coro_traits_identifier = get_identifier ("coroutine_traits");
216 coro_handle_identifier = get_identifier ("coroutine_handle");
217 coro_promise_type_identifier = get_identifier ("promise_type");
218
219 coro_await_transform_identifier = get_identifier ("await_transform");
220 coro_initial_suspend_identifier = get_identifier ("initial_suspend");
221 coro_final_suspend_identifier = get_identifier ("final_suspend");
222 coro_return_void_identifier = get_identifier ("return_void");
223 coro_return_value_identifier = get_identifier ("return_value");
224 coro_yield_value_identifier = get_identifier ("yield_value");
225 coro_resume_identifier = get_identifier ("resume");
226 coro_from_address_identifier = get_identifier ("from_address");
227 coro_get_return_object_identifier = get_identifier ("get_return_object");
228 coro_gro_on_allocation_fail_identifier =
229 get_identifier ("get_return_object_on_allocation_failure");
230 coro_unhandled_exception_identifier = get_identifier ("unhandled_exception");
231
232 coro_await_ready_identifier = get_identifier ("await_ready");
233 coro_await_suspend_identifier = get_identifier ("await_suspend");
234 coro_await_resume_identifier = get_identifier ("await_resume");
235 }
236
237 /* Trees we only need to set up once. */
238
239 static GTY(()) tree coro_traits_templ;
240 static GTY(()) tree coro_handle_templ;
241 static GTY(()) tree void_coro_handle_type;
242
243 /* ================= Parse, Semantics and Type checking ================= */
244
245 /* This initial set of routines are helper for the parsing and template
246 expansion phases.
247
248 At the completion of this, we will have completed trees for each of the
249 keywords, but making use of proxy variables for the self-handle and the
250 promise class instance. */
251
252 /* [coroutine.traits]
253 Lookup the coroutine_traits template decl. */
254
255 static tree
256 find_coro_traits_template_decl (location_t kw)
257 {
258 tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
259 0, true);
260 if (traits_decl == NULL_TREE || traits_decl == error_mark_node)
261 {
262 error_at (kw, "cannot find %<coroutine traits%> template");
263 return NULL_TREE;
264 }
265 else
266 return traits_decl;
267 }
268
269 /* Instantiate Coroutine traits for the function signature. */
270
271 static tree
272 instantiate_coro_traits (tree fndecl, location_t kw)
273 {
274 /* [coroutine.traits.primary]
275 So now build up a type list for the template <typename _R, typename...>.
276 The types are the function's arg types and _R is the function return
277 type. */
278
279 tree functyp = TREE_TYPE (fndecl);
280 tree arg_node = TYPE_ARG_TYPES (functyp);
281 tree argtypes = make_tree_vec (list_length (arg_node)-1);
282 unsigned p = 0;
283
284 while (arg_node != NULL_TREE && !VOID_TYPE_P (TREE_VALUE (arg_node)))
285 {
286 TREE_VEC_ELT (argtypes, p++) = TREE_VALUE (arg_node);
287 arg_node = TREE_CHAIN (arg_node);
288 }
289
290 tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
291 SET_ARGUMENT_PACK_ARGS (argtypepack, argtypes);
292
293 tree targ = make_tree_vec (2);
294 TREE_VEC_ELT (targ, 0) = TREE_TYPE (functyp);
295 TREE_VEC_ELT (targ, 1) = argtypepack;
296
297 tree traits_class
298 = lookup_template_class (coro_traits_templ, targ,
299 /*in_decl=*/ NULL_TREE,
300 /*context=*/ NULL_TREE /*std_node*/,
301 /*entering scope=*/ false, tf_warning_or_error);
302
303 if (traits_class == error_mark_node || traits_class == NULL_TREE)
304 {
305 error_at (kw, "cannot instantiate %<coroutine traits%>");
306 return NULL_TREE;
307 }
308
309 return traits_class;
310 }
311
312 /* [coroutine.handle] */
313
314 static tree
315 find_coro_handle_template_decl (location_t kw)
316 {
317 tree handle_decl = lookup_qualified_name (std_node, coro_handle_identifier,
318 0, true);
319 if (handle_decl == NULL_TREE || handle_decl == error_mark_node)
320 {
321 error_at (kw, "cannot find %<coroutine handle%> template");
322 return NULL_TREE;
323 }
324 else
325 return handle_decl;
326 }
327
328 /* Instantiate the handle template for a given promise type. */
329
330 static tree
331 instantiate_coro_handle_for_promise_type (location_t kw, tree promise_type)
332 {
333 /* So now build up a type list for the template, one entry, the promise. */
334 tree targ = make_tree_vec (1);
335 TREE_VEC_ELT (targ, 0) = promise_type;
336 tree handle_type
337 = lookup_template_class (coro_handle_identifier, targ,
338 /* in_decl */ NULL_TREE,
339 /* context */ std_node,
340 /* entering scope */ false, tf_warning_or_error);
341
342 if (handle_type == error_mark_node)
343 {
344 error_at (kw, "cannot instantiate a %<coroutine handle%> for"
345 " promise type %qT", promise_type);
346 return NULL_TREE;
347 }
348
349 return handle_type;
350 }
351
352 /* Look for the promise_type in the instantiated traits. */
353
354 static tree
355 find_promise_type (tree traits_class)
356 {
357 tree promise_type
358 = lookup_member (traits_class, coro_promise_type_identifier,
359 /* protect */ 1, /*want_type=*/true, tf_warning_or_error);
360
361 if (promise_type)
362 promise_type
363 = complete_type_or_else (TREE_TYPE (promise_type), promise_type);
364
365 /* NULL_TREE on fail. */
366 return promise_type;
367 }
368
369 static bool
370 coro_promise_type_found_p (tree fndecl, location_t loc)
371 {
372 gcc_assert (fndecl != NULL_TREE);
373
374 /* Save the coroutine data on the side to avoid the overhead on every
375 function decl. */
376
377 /* We only need one entry per coroutine in a TU, the assumption here is that
378 there are typically not 1000s. */
379 if (!coro_initialized)
380 {
381 gcc_checking_assert (coroutine_info_table == NULL);
382 /* A table to hold the state, per coroutine decl. */
383 coroutine_info_table =
384 hash_table<coroutine_info_hasher>::create_ggc (11);
385 /* Set up the identifiers we will use. */
386 gcc_checking_assert (coro_traits_identifier == NULL);
387 coro_init_identifiers ();
388 /* Trees we only need to create once. */
389 /* Coroutine traits template. */
390 coro_traits_templ = find_coro_traits_template_decl (loc);
391 gcc_checking_assert (coro_traits_templ != NULL);
392 /* coroutine_handle<> template. */
393 coro_handle_templ = find_coro_handle_template_decl (loc);
394 gcc_checking_assert (coro_handle_templ != NULL);
395 /* We can also instantiate the void coroutine_handle<> */
396 void_coro_handle_type =
397 instantiate_coro_handle_for_promise_type (loc, NULL_TREE);
398 gcc_checking_assert (void_coro_handle_type != NULL);
399 coro_initialized = true;
400 }
401
402 coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
403 /* Without this, we cannot really proceed. */
404 gcc_checking_assert (coro_info);
405
406 /* If we don't already have a current promise type, try to look it up. */
407 if (coro_info->promise_type == NULL_TREE)
408 {
409 /* Get the coroutine traits template class instance for the function
410 signature we have - coroutine_traits <R, ...> */
411 tree templ_class = instantiate_coro_traits (fndecl, loc);
412
413 /* Find the promise type for that. */
414 coro_info->promise_type = find_promise_type (templ_class);
415
416 /* If we don't find it, punt on the rest. */
417 if (coro_info->promise_type == NULL_TREE)
418 {
419 error_at (loc, "unable to find the promise type for this coroutine");
420 return false;
421 }
422
423 /* Try to find the handle type for the promise. */
424 tree handle_type =
425 instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
426 if (handle_type == NULL_TREE)
427 return false;
428
429 /* Complete this, we're going to use it. */
430 coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
431
432 /* Diagnostic would be emitted by complete_type_or_else. */
433 if (!coro_info->handle_type)
434 return false;
435
436 /* Build a proxy for a handle to "self" as the param to
437 await_suspend() calls. */
438 coro_info->self_h_proxy
439 = build_lang_decl (VAR_DECL, get_identifier ("self_h.proxy"),
440 coro_info->handle_type);
441
442 /* Build a proxy for the promise so that we can perform lookups. */
443 coro_info->promise_proxy
444 = build_lang_decl (VAR_DECL, get_identifier ("promise.proxy"),
445 coro_info->promise_type);
446
447 /* Note where we first saw a coroutine keyword. */
448 coro_info->first_coro_keyword = loc;
449 }
450
451 return true;
452 }
453
454 /* These functions assumes that the caller has verified that the state for
455 the decl has been initialized, we try to minimize work here. */
456
457 static tree
458 get_coroutine_promise_type (tree decl)
459 {
460 if (coroutine_info *info = get_coroutine_info (decl))
461 return info->promise_type;
462
463 return NULL_TREE;
464 }
465
466 static tree
467 get_coroutine_handle_type (tree decl)
468 {
469 if (coroutine_info *info = get_coroutine_info (decl))
470 return info->handle_type;
471
472 return NULL_TREE;
473 }
474
475 static tree
476 get_coroutine_self_handle_proxy (tree decl)
477 {
478 if (coroutine_info *info = get_coroutine_info (decl))
479 return info->self_h_proxy;
480
481 return NULL_TREE;
482 }
483
484 static tree
485 get_coroutine_promise_proxy (tree decl)
486 {
487 if (coroutine_info *info = get_coroutine_info (decl))
488 return info->promise_proxy;
489
490 return NULL_TREE;
491 }
492
493 static tree
494 lookup_promise_method (tree fndecl, tree member_id, location_t loc,
495 bool musthave)
496 {
497 tree promise = get_coroutine_promise_type (fndecl);
498 tree pm_memb
499 = lookup_member (promise, member_id,
500 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
501 if (musthave && pm_memb == NULL_TREE)
502 {
503 error_at (loc, "no member named %qE in %qT", member_id, promise);
504 return error_mark_node;
505 }
506 return pm_memb;
507 }
508
509 /* Lookup an Awaitable member, which should be await_ready, await_suspend
510 or await_resume. */
511
512 static tree
513 lookup_awaitable_member (tree await_type, tree member_id, location_t loc)
514 {
515 tree aw_memb
516 = lookup_member (await_type, member_id,
517 /*protect=*/1, /*want_type=*/0, tf_warning_or_error);
518 if (aw_memb == NULL_TREE)
519 {
520 error_at (loc, "no member named %qE in %qT", member_id, await_type);
521 return error_mark_node;
522 }
523 return aw_memb;
524 }
525
526 /* Here we check the constraints that are common to all keywords (since the
527 presence of a coroutine keyword makes the function into a coroutine). */
528
529 static bool
530 coro_common_keyword_context_valid_p (tree fndecl, location_t kw_loc,
531 const char *kw_name)
532 {
533 if (fndecl == NULL_TREE)
534 {
535 error_at (kw_loc, "%qs cannot be used outside a function", kw_name);
536 return false;
537 }
538
539 /* This is arranged in order of prohibitions in the std. */
540 if (DECL_MAIN_P (fndecl))
541 {
542 // [basic.start.main] 3. The function main shall not be a coroutine.
543 error_at (kw_loc, "%qs cannot be used in the %<main%> function",
544 kw_name);
545 return false;
546 }
547
548 if (DECL_DECLARED_CONSTEXPR_P (fndecl))
549 {
550 // [dcl.constexpr] 3.3 it shall not be a coroutine.
551 error_at (kw_loc, "%qs cannot be used in a %<constexpr%> function",
552 kw_name);
553 cp_function_chain->invalid_constexpr = true;
554 return false;
555 }
556
557 if (FNDECL_USED_AUTO (fndecl))
558 {
559 // [dcl.spec.auto] 15. A function declared with a return type that uses
560 // a placeholder type shall not be a coroutine .
561 error_at (kw_loc,
562 "%qs cannot be used in a function with a deduced return type",
563 kw_name);
564 return false;
565 }
566
567 if (varargs_function_p (fndecl))
568 {
569 // [dcl.fct.def.coroutine] The parameter-declaration-clause of the
570 // coroutine shall not terminate with an ellipsis that is not part
571 // of a parameter-declaration.
572 error_at (kw_loc,
573 "%qs cannot be used in a varargs function", kw_name);
574 return false;
575 }
576
577 if (DECL_CONSTRUCTOR_P (fndecl))
578 {
579 // [class.ctor] 7. a constructor shall not be a coroutine.
580 error_at (kw_loc, "%qs cannot be used in a constructor", kw_name);
581 return false;
582 }
583
584 if (DECL_DESTRUCTOR_P (fndecl))
585 {
586 // [class.dtor] 21. a destructor shall not be a coroutine.
587 error_at (kw_loc, "%qs cannot be used in a destructor", kw_name);
588 return false;
589 }
590
591 return true;
592 }
593
594 /* Here we check the constraints that are not per keyword. */
595
596 static bool
597 coro_function_valid_p (tree fndecl)
598 {
599 location_t f_loc = DECL_SOURCE_LOCATION (fndecl);
600
601 /* Since we think the function is a coroutine, that implies we parsed
602 a keyword that triggered this. Keywords check promise validity for
603 their context and thus the promise type should be known at this point. */
604 gcc_checking_assert (get_coroutine_handle_type (fndecl) != NULL_TREE
605 && get_coroutine_promise_type (fndecl) != NULL_TREE);
606
607 if (current_function_returns_value || current_function_returns_null)
608 {
609 /* TODO: record or extract positions of returns (and the first coro
610 keyword) so that we can add notes to the diagnostic about where
611 the bad keyword is and what made the function into a coro. */
612 error_at (f_loc, "a %<return%> statement is not allowed in coroutine;"
613 " did you mean %<co_return%>?");
614 return false;
615 }
616
617 return true;
618 }
619
620 enum suspend_point_kind {
621 CO_AWAIT_SUSPEND_POINT = 0,
622 CO_YIELD_SUSPEND_POINT,
623 INITIAL_SUSPEND_POINT,
624 FINAL_SUSPEND_POINT
625 };
626
627 /* This performs [expr.await] bullet 3.3 and validates the interface obtained.
628 It is also used to build the initial and final suspend points.
629
630 'a', 'o' and 'e' are used as per the description in the section noted.
631
632 A, the original yield/await expr, is found at source location LOC.
633
634 We will be constructing a CO_AWAIT_EXPR for a suspend point of one of
635 the four suspend_point_kind kinds. This is indicated by SUSPEND_KIND. */
636
637 static tree
638 build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
639 {
640 /* Try and overload of operator co_await, .... */
641 tree o;
642 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (a)))
643 {
644 tree overload = NULL_TREE;
645 o = build_new_op (loc, CO_AWAIT_EXPR, LOOKUP_NORMAL, a, NULL_TREE,
646 NULL_TREE, &overload, tf_warning_or_error);
647 /* If no viable functions are found, o is a. */
648 if (!o || o == error_mark_node)
649 o = a;
650 }
651 else
652 o = a; /* This is most likely about to fail anyway. */
653
654 tree o_type = TREE_TYPE (o);
655 if (o_type && !VOID_TYPE_P (o_type))
656 o_type = complete_type_or_else (o_type, o);
657
658 if (!o_type)
659 return error_mark_node;
660
661 if (TREE_CODE (o_type) != RECORD_TYPE)
662 {
663 error_at (loc, "awaitable type %qT is not a structure",
664 o_type);
665 return error_mark_node;
666 }
667
668 /* Check for required awaitable members and their types. */
669 tree awrd_meth
670 = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc);
671 if (!awrd_meth || awrd_meth == error_mark_node)
672 return error_mark_node;
673 tree awsp_meth
674 = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc);
675 if (!awsp_meth || awsp_meth == error_mark_node)
676 return error_mark_node;
677
678 /* The type of the co_await is the return type of the awaitable's
679 await_resume, so we need to look that up. */
680 tree awrs_meth
681 = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc);
682 if (!awrs_meth || awrs_meth == error_mark_node)
683 return error_mark_node;
684
685 /* To complete the lookups, we need an instance of 'e' which is built from
686 'o' according to [expr.await] 3.4. However, we don't want to materialize
687 'e' here (it might need to be placed in the coroutine frame) so we will
688 make a temp placeholder instead. */
689 tree e_proxy = build_lang_decl (VAR_DECL, NULL_TREE, o_type);
690
691 /* I suppose we could check that this is contextually convertible to bool. */
692 tree awrd_func = NULL_TREE;
693 tree awrd_call
694 = build_new_method_call (e_proxy, awrd_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
695 &awrd_func, tf_warning_or_error);
696
697 if (!awrd_func || !awrd_call || awrd_call == error_mark_node)
698 return error_mark_node;
699
700 /* The suspend method may return one of three types:
701 1. void (no special action needed).
702 2. bool (if true, we don't need to suspend).
703 3. a coroutine handle, we execute the handle.resume() call. */
704 tree awsp_func = NULL_TREE;
705 tree h_proxy = get_coroutine_self_handle_proxy (current_function_decl);
706 vec<tree, va_gc> *args = make_tree_vector_single (h_proxy);
707 tree awsp_call
708 = build_new_method_call (e_proxy, awsp_meth, &args, NULL_TREE,
709 LOOKUP_NORMAL, &awsp_func, tf_warning_or_error);
710
711 release_tree_vector (args);
712 if (!awsp_func || !awsp_call || awsp_call == error_mark_node)
713 return error_mark_node;
714
715 bool ok = false;
716 tree susp_return_type = TREE_TYPE (TREE_TYPE (awsp_func));
717 if (same_type_p (susp_return_type, void_type_node))
718 ok = true;
719 else if (same_type_p (susp_return_type, boolean_type_node))
720 ok = true;
721 else if (TREE_CODE (susp_return_type) == RECORD_TYPE
722 && CLASS_TYPE_P (susp_return_type))
723 {
724 tree tt = CLASSTYPE_TI_TEMPLATE (susp_return_type);
725 if (tt == coro_handle_templ)
726 ok = true;
727 }
728
729 if (!ok)
730 {
731 error_at (loc, "%<await_suspend%> must return %<void%>, %<bool%> or"
732 " a coroutine handle");
733 return error_mark_node;
734 }
735
736 /* Finally, the type of e.await_resume() is the co_await's type. */
737 tree awrs_func = NULL_TREE;
738 tree awrs_call
739 = build_new_method_call (e_proxy, awrs_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
740 &awrs_func, tf_warning_or_error);
741
742 if (!awrs_func || !awrs_call || awrs_call == error_mark_node)
743 return error_mark_node;
744
745 /* We now have three call expressions, in terms of the promise, handle and
746 'e' proxies. Save them in the await expression for later expansion. */
747
748 tree awaiter_calls = make_tree_vec (3);
749 TREE_VEC_ELT (awaiter_calls, 0) = awrd_call; /* await_ready(). */
750 TREE_VEC_ELT (awaiter_calls, 1) = awsp_call; /* await_suspend(). */
751 TREE_VEC_ELT (awaiter_calls, 2) = awrs_call; /* await_resume(). */
752
753 return build5_loc (loc, CO_AWAIT_EXPR, TREE_TYPE (awrs_call), a,
754 e_proxy, o, awaiter_calls,
755 build_int_cst (integer_type_node, (int) suspend_kind));
756 }
757
758 tree
759 finish_co_await_expr (location_t kw, tree expr)
760 {
761 if (!expr || error_operand_p (expr))
762 return error_mark_node;
763
764 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
765 "co_await"))
766 return error_mark_node;
767
768 /* The current function has now become a coroutine, if it wasn't already. */
769 DECL_COROUTINE_P (current_function_decl) = 1;
770
771 if (processing_template_decl)
772 {
773 current_function_returns_value = 1;
774
775 if (check_for_bare_parameter_packs (expr))
776 return error_mark_node;
777
778 /* If we don't know the promise type, we can't proceed. */
779 tree functype = TREE_TYPE (current_function_decl);
780 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
781 return build5_loc (kw, CO_AWAIT_EXPR, TREE_TYPE (expr), expr, NULL_TREE,
782 NULL_TREE, NULL_TREE, integer_zero_node);
783 }
784
785 /* We must be able to look up the "await_transform" method in the scope of
786 the promise type, and obtain its return type. */
787 if (!coro_promise_type_found_p (current_function_decl, kw))
788 return error_mark_node;
789
790 /* [expr.await] 3.2
791 The incoming cast expression might be transformed by a promise
792 'await_transform()'. */
793 tree at_meth
794 = lookup_promise_method (current_function_decl,
795 coro_await_transform_identifier, kw,
796 /*musthave=*/ false);
797 if (at_meth == error_mark_node)
798 return error_mark_node;
799
800 tree a = expr;
801 if (at_meth)
802 {
803 /* try to build a = p.await_transform (e). */
804 tree at_fn = NULL_TREE;
805 vec<tree, va_gc> *args = make_tree_vector_single (expr);
806 a = build_new_method_call (get_coroutine_promise_proxy (
807 current_function_decl),
808 at_meth, &args, NULL_TREE, LOOKUP_NORMAL,
809 &at_fn, tf_warning_or_error);
810
811 /* As I read the section.
812 We saw an await_transform method, so it's mandatory that we replace
813 expr with p.await_transform (expr), therefore if the method call fails
814 (presumably, we don't have suitable arguments) then this part of the
815 process fails. */
816 if (!at_fn || a == error_mark_node)
817 return error_mark_node;
818 }
819
820 /* Now we want to build co_await a. */
821 tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT);
822 TREE_SIDE_EFFECTS (op) = 1;
823 SET_EXPR_LOCATION (op, kw);
824
825 return op;
826 }
827
828 /* Take the EXPR given and attempt to build:
829 co_await p.yield_value (expr);
830 per [expr.yield] para 1. */
831
832 tree
833 finish_co_yield_expr (location_t kw, tree expr)
834 {
835 if (!expr || error_operand_p (expr))
836 return error_mark_node;
837
838 /* Check the general requirements and simple syntax errors. */
839 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
840 "co_yield"))
841 return error_mark_node;
842
843 /* The current function has now become a coroutine, if it wasn't already. */
844 DECL_COROUTINE_P (current_function_decl) = 1;
845
846 if (processing_template_decl)
847 {
848 current_function_returns_value = 1;
849
850 if (check_for_bare_parameter_packs (expr))
851 return error_mark_node;
852
853 tree functype = TREE_TYPE (current_function_decl);
854 /* If we don't know the promise type, we can't proceed. */
855 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
856 return build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (expr), expr,
857 NULL_TREE);
858 }
859
860 if (!coro_promise_type_found_p (current_function_decl, kw))
861 /* We must be able to look up the "yield_value" method in the scope of
862 the promise type, and obtain its return type. */
863 return error_mark_node;
864
865 /* The incoming expr is "e" per [expr.yield] para 1, lookup and build a
866 call for p.yield_value(e). */
867 tree y_meth = lookup_promise_method (current_function_decl,
868 coro_yield_value_identifier, kw,
869 /*musthave=*/ true);
870 if (!y_meth || y_meth == error_mark_node)
871 return error_mark_node;
872
873 tree yield_fn = NULL_TREE;
874 vec<tree, va_gc> *args = make_tree_vector_single (expr);
875 tree yield_call = build_new_method_call (
876 get_coroutine_promise_proxy (current_function_decl), y_meth, &args,
877 NULL_TREE, LOOKUP_NORMAL, &yield_fn, tf_warning_or_error);
878
879 if (!yield_fn || yield_call == error_mark_node)
880 return error_mark_node;
881
882 /* So now we have the type of p.yield_value (e).
883 Now we want to build co_await p.yield_value (e).
884 Noting that for co_yield, there is no evaluation of any potential
885 promise transform_await(). */
886
887 tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT);
888
889 op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op);
890 TREE_SIDE_EFFECTS (op) = 1;
891
892 return op;
893 }
894
895 /* Check that it's valid to have a co_return keyword here.
896 If it is, then check and build the p.return_{void(),value(expr)}.
897 These are built against the promise proxy, but saved for expand time. */
898
899 tree
900 finish_co_return_stmt (location_t kw, tree expr)
901 {
902 if (expr == error_mark_node)
903 return error_mark_node;
904
905 if (!coro_common_keyword_context_valid_p (current_function_decl, kw,
906 "co_return"))
907 return error_mark_node;
908
909 /* The current function has now become a coroutine, if it wasn't
910 already. */
911 DECL_COROUTINE_P (current_function_decl) = 1;
912
913 if (processing_template_decl)
914 {
915 current_function_returns_value = 1;
916
917 if (check_for_bare_parameter_packs (expr))
918 return error_mark_node;
919
920 tree functype = TREE_TYPE (current_function_decl);
921 /* If we don't know the promise type, we can't proceed, return the
922 expression as it is. */
923 if (dependent_type_p (functype) || type_dependent_expression_p (expr))
924 {
925 expr
926 = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, NULL_TREE);
927 expr = maybe_cleanup_point_expr_void (expr);
928 expr = add_stmt (expr);
929 return expr;
930 }
931 }
932
933 if (!coro_promise_type_found_p (current_function_decl, kw))
934 return error_mark_node;
935
936 if (error_operand_p (expr))
937 return error_mark_node;
938
939 /* Suppress -Wreturn-type for co_return, we need to check indirectly
940 whether the promise type has a suitable return_void/return_value. */
941 TREE_NO_WARNING (current_function_decl) = true;
942
943 if (!processing_template_decl && warn_sequence_point)
944 verify_sequence_points (expr);
945
946 /* If the promise object doesn't have the correct return call then
947 there's a mis-match between the co_return <expr> and this. */
948 tree co_ret_call = NULL_TREE;
949 if (expr == NULL_TREE || VOID_TYPE_P (TREE_TYPE (expr)))
950 {
951 tree crv_meth
952 = lookup_promise_method (current_function_decl,
953 coro_return_void_identifier, kw,
954 /*musthave=*/ true);
955 if (!crv_meth || crv_meth == error_mark_node)
956 return error_mark_node;
957
958 co_ret_call = build_new_method_call (
959 get_coroutine_promise_proxy (current_function_decl), crv_meth, NULL,
960 NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error);
961 }
962 else
963 {
964 tree crv_meth
965 = lookup_promise_method (current_function_decl,
966 coro_return_value_identifier, kw,
967 /*musthave=*/ true);
968 if (!crv_meth || crv_meth == error_mark_node)
969 return error_mark_node;
970
971 vec<tree, va_gc> *args = make_tree_vector_single (expr);
972 co_ret_call = build_new_method_call (
973 get_coroutine_promise_proxy (current_function_decl), crv_meth, &args,
974 NULL_TREE, LOOKUP_NORMAL, NULL, tf_warning_or_error);
975 }
976
977 /* Makes no sense for a co-routine really. */
978 if (TREE_THIS_VOLATILE (current_function_decl))
979 warning_at (kw, 0,
980 "function declared %<noreturn%> has a"
981 " %<co_return%> statement");
982
983 if (!co_ret_call || co_ret_call == error_mark_node)
984 return error_mark_node;
985
986 expr = build2_loc (kw, CO_RETURN_EXPR, void_type_node, expr, co_ret_call);
987 expr = maybe_cleanup_point_expr_void (expr);
988 expr = add_stmt (expr);
989 return expr;
990 }
991
992 /* We need to validate the arguments to __builtin_coro_promise, since the
993 second two must be constant, and the builtins machinery doesn't seem to
994 deal with that properly. */
995
996 tree
997 coro_validate_builtin_call (tree call, tsubst_flags_t)
998 {
999 tree fn = TREE_OPERAND (CALL_EXPR_FN (call), 0);
1000
1001 gcc_checking_assert (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL);
1002 switch (DECL_FUNCTION_CODE (fn))
1003 {
1004 default:
1005 return call;
1006
1007 case BUILT_IN_CORO_PROMISE:
1008 {
1009 /* Argument 0 is already checked by the normal built-in machinery
1010 Argument 1 must be a constant of size type. It probably makes
1011 little sense if it's not a power of 2, but that isn't specified
1012 formally. */
1013 tree arg = CALL_EXPR_ARG (call, 1);
1014 location_t loc = EXPR_LOCATION (arg);
1015
1016 /* We expect alignof expressions in templates. */
1017 if (TREE_CODE (arg) == NON_DEPENDENT_EXPR
1018 && TREE_CODE (TREE_OPERAND (arg, 0)) == ALIGNOF_EXPR)
1019 ;
1020 else if (!TREE_CONSTANT (arg))
1021 {
1022 error_at (loc, "the align argument to %<__builtin_coro_promise%>"
1023 " must be a constant");
1024 return error_mark_node;
1025 }
1026 /* Argument 2 is the direction - to / from handle address to promise
1027 address. */
1028 arg = CALL_EXPR_ARG (call, 2);
1029 loc = EXPR_LOCATION (arg);
1030 if (!TREE_CONSTANT (arg))
1031 {
1032 error_at (loc, "the direction argument to"
1033 " %<__builtin_coro_promise%> must be a constant");
1034 return error_mark_node;
1035 }
1036 return call;
1037 break;
1038 }
1039 }
1040 }
1041
1042 /* ================= Morph and Expand. =================
1043
1044 The entry point here is morph_fn_to_coro () which is called from
1045 finish_function () when we have completed any template expansion.
1046
1047 This is preceded by helper functions that implement the phases below.
1048
1049 The process proceeds in four phases.
1050
1051 A Initial framing.
1052 The user's function body is wrapped in the initial and final suspend
1053 points and we begin building the coroutine frame.
1054 We build empty decls for the actor and destroyer functions at this
1055 time too.
1056 When exceptions are enabled, the user's function body will also be
1057 wrapped in a try-catch block with the catch invoking the promise
1058 class 'unhandled_exception' method.
1059
1060 B Analysis.
1061 The user's function body is analyzed to determine the suspend points,
1062 if any, and to capture local variables that might persist across such
1063 suspensions. In most cases, it is not necessary to capture compiler
1064 temporaries, since the tree-lowering nests the suspensions correctly.
1065 However, in the case of a captured reference, there is a lifetime
1066 extension to the end of the full expression - which can mean across a
1067 suspend point in which case it must be promoted to a frame variable.
1068
1069 At the conclusion of analysis, we have a conservative frame layout and
1070 maps of the local variables to their frame entry points.
1071
1072 C Build the ramp function.
1073 Carry out the allocation for the coroutine frame (NOTE; the actual size
1074 computation is deferred until late in the middle end to allow for future
1075 optimizations that will be allowed to elide unused frame entries).
1076 We build the return object.
1077
1078 D Build and expand the actor and destroyer function bodies.
1079 The destroyer is a trivial shim that sets a bit to indicate that the
1080 destroy dispatcher should be used and then calls into the actor.
1081
1082 The actor function is the implementation of the user's state machine.
1083 The current suspend point is noted in an index.
1084 Each suspend point is encoded as a pair of internal functions, one in
1085 the relevant dispatcher, and one representing the suspend point.
1086
1087 During this process, the user's local variables and the proxies for the
1088 self-handle and the promise class instance are re-written to their
1089 coroutine frame equivalents.
1090
1091 The complete bodies for the ramp, actor and destroy function are passed
1092 back to finish_function for folding and gimplification. */
1093
1094 /* Helpers to build EXPR_STMT and void-cast EXPR_STMT, common ops. */
1095
1096 static tree
1097 coro_build_expr_stmt (tree expr, location_t loc)
1098 {
1099 return maybe_cleanup_point_expr_void (build_stmt (loc, EXPR_STMT, expr));
1100 }
1101
1102 static tree
1103 coro_build_cvt_void_expr_stmt (tree expr, location_t loc)
1104 {
1105 tree t = build1 (CONVERT_EXPR, void_type_node, expr);
1106 return coro_build_expr_stmt (t, loc);
1107 }
1108
1109 /* Helpers for label creation:
1110 1. Create a named label in the specified context. */
1111
1112 static tree
1113 create_anon_label_with_ctx (location_t loc, tree ctx)
1114 {
1115 tree lab = build_decl (loc, LABEL_DECL, NULL_TREE, void_type_node);
1116
1117 DECL_CONTEXT (lab) = ctx;
1118 DECL_ARTIFICIAL (lab) = true;
1119 DECL_IGNORED_P (lab) = true;
1120 TREE_USED (lab) = true;
1121 return lab;
1122 }
1123
1124 /* 2. Create a named label in the specified context. */
1125
1126 static tree
1127 create_named_label_with_ctx (location_t loc, const char *name, tree ctx)
1128 {
1129 tree lab_id = get_identifier (name);
1130 tree lab = define_label (loc, lab_id);
1131 DECL_CONTEXT (lab) = ctx;
1132 DECL_ARTIFICIAL (lab) = true;
1133 TREE_USED (lab) = true;
1134 return lab;
1135 }
1136
1137 struct proxy_replace
1138 {
1139 tree from, to;
1140 };
1141
1142 static tree
1143 replace_proxy (tree *here, int *do_subtree, void *d)
1144 {
1145 proxy_replace *data = (proxy_replace *) d;
1146
1147 if (*here == data->from)
1148 {
1149 *here = data->to;
1150 *do_subtree = 0;
1151 }
1152 else
1153 *do_subtree = 1;
1154 return NULL_TREE;
1155 }
1156
1157 /* Support for expansion of co_return statements. */
1158
1159 struct coro_ret_data
1160 {
1161 tree promise_proxy;
1162 tree real_promise;
1163 tree fs_label;
1164 };
1165
1166 /* If this is a coreturn statement (or one wrapped in a cleanup) then
1167 return the list of statements to replace it. */
1168
1169 static tree
1170 coro_maybe_expand_co_return (tree co_ret_expr, coro_ret_data *data)
1171 {
1172 /* Look inside <(void) (expr)> cleanup */
1173 if (TREE_CODE (co_ret_expr) == CLEANUP_POINT_EXPR)
1174 co_ret_expr = TREE_OPERAND (co_ret_expr, 0);
1175
1176 if (TREE_CODE (co_ret_expr) != CO_RETURN_EXPR)
1177 return NULL_TREE;
1178
1179 location_t loc = EXPR_LOCATION (co_ret_expr);
1180 tree expr = TREE_OPERAND (co_ret_expr, 0);
1181 tree call = TREE_OPERAND (co_ret_expr, 1);
1182 tree stmt_list = NULL;
1183 if (expr && VOID_TYPE_P (TREE_TYPE (expr)))
1184 {
1185 /* [stmt.return.coroutine], 2.2
1186 If expr is present and void, it is placed immediately before
1187 the call for return_void; */
1188 expr = maybe_cleanup_point_expr_void (expr);
1189 append_to_statement_list (expr, &stmt_list);
1190 }
1191
1192 /* Now replace the promise proxy with its real value. */
1193 proxy_replace p_data;
1194 p_data.from = data->promise_proxy;
1195 p_data.to = data->real_promise;
1196 cp_walk_tree (&call, replace_proxy, &p_data, NULL);
1197
1198 /* The types of p.return_void and p.return_value are not explicitly stated
1199 at least in n4835, it is expected that they will return void. */
1200 call = maybe_cleanup_point_expr_void (call);
1201 append_to_statement_list (call, &stmt_list);
1202 tree r = build1_loc (loc, GOTO_EXPR, void_type_node, data->fs_label);
1203 append_to_statement_list (r, &stmt_list);
1204 return stmt_list;
1205 }
1206
1207 /* Callback that rewrites co_return as per [stmt.return.coroutine]
1208 - for co_return;
1209 { p.return_void (); goto final_suspend; }
1210 - for co_return [void expr];
1211 { expr; p.return_void(); goto final_suspend;}
1212 - for co_return [non void expr];
1213 { p.return_value(expr); goto final_suspend; } */
1214
1215 static tree
1216 co_return_expander (tree *stmt, int *do_subtree, void *d)
1217 {
1218 coro_ret_data *data = (coro_ret_data *) d;
1219
1220 /* To avoid nesting statement lists, walk them and insert as needed. */
1221 if (TREE_CODE (*stmt) == STATEMENT_LIST)
1222 {
1223 tree_stmt_iterator i;
1224 for (i = tsi_start (*stmt); !tsi_end_p (i); tsi_next (&i))
1225 {
1226 tree *new_stmt = tsi_stmt_ptr (i);
1227 tree replace = coro_maybe_expand_co_return (*new_stmt, data);
1228 /* If we got something, it will be list and we want to splice
1229 it in. */
1230 if (replace != NULL_TREE)
1231 {
1232 /* Splice it in ... */
1233 tsi_link_before (&i, replace, TSI_SAME_STMT);
1234 /* ... and delete what we expanded. */
1235 tsi_delink (&i);
1236 /* Maybe, even likely, we replaced the last in the list. */
1237 if (tsi_end_p (i))
1238 break;
1239 }
1240 else /* Continue the walk. */
1241 cp_walk_tree (new_stmt, co_return_expander, d, NULL);
1242 }
1243 *do_subtree = 0; /* Done subtrees. */
1244 }
1245 else
1246 {
1247 /* We might have a single co_return statement, in which case, we do
1248 have to replace it with a list. */
1249 tree replace = coro_maybe_expand_co_return (*stmt, data);
1250 if (replace != NULL_TREE)
1251 {
1252 *stmt = replace;
1253 *do_subtree = 0; /* Done here. */
1254 }
1255 }
1256 return NULL_TREE;
1257 }
1258
1259 /* Walk the original function body, rewriting co_returns. */
1260
1261 static tree
1262 expand_co_returns (tree *fnbody, tree promise_proxy, tree promise,
1263 tree fs_label)
1264 {
1265 coro_ret_data data = {promise_proxy, promise, fs_label};
1266 cp_walk_tree (fnbody, co_return_expander, &data, NULL);
1267 return *fnbody;
1268 }
1269
1270 /* Support for expansion of co_await statements. */
1271
1272 struct coro_aw_data
1273 {
1274 tree actor_fn; /* Decl for context. */
1275 tree coro_fp; /* Frame pointer var. */
1276 tree resume_idx; /* This is the index var in the frame. */
1277 tree self_h; /* This is a handle to the current coro (frame var). */
1278 tree cleanup; /* This is where to go once we complete local destroy. */
1279 tree cororet; /* This is where to go if we suspend. */
1280 unsigned index; /* This is our current resume index. */
1281 };
1282
1283 static tree
1284 co_await_find_in_subtree (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
1285 {
1286 tree **p = (tree **) d;
1287 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR)
1288 {
1289 *p = stmt;
1290 return *stmt;
1291 }
1292 return NULL_TREE;
1293 }
1294
1295 /* When we come here:
1296 the first operand is the [currently unused] handle for suspend.
1297 the second operand is the var to be copy-initialized
1298 the third operand is 'o' (the initializer for the second)
1299 as defined in [await.expr] (3.3)
1300 the fourth operand is the mode as per the comment on build_co_await ().
1301
1302 When we leave:
1303 the IFN_CO_YIELD carries the labels of the resume and destroy
1304 branch targets for this await. */
1305
1306 static tree
1307 co_await_expander (tree *stmt, int * /*do_subtree*/, void *d)
1308 {
1309 if (STATEMENT_CLASS_P (*stmt) || !EXPR_P (*stmt))
1310 return NULL_TREE;
1311
1312 coro_aw_data *data = (coro_aw_data *) d;
1313
1314 enum tree_code stmt_code = TREE_CODE (*stmt);
1315 tree stripped_stmt = *stmt;
1316
1317 /* Look inside <(void) (expr)> cleanup */
1318 if (stmt_code == CLEANUP_POINT_EXPR)
1319 {
1320 stripped_stmt = TREE_OPERAND (*stmt, 0);
1321 stmt_code = TREE_CODE (stripped_stmt);
1322 if (stmt_code == EXPR_STMT
1323 && (TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CONVERT_EXPR
1324 || TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CAST_EXPR)
1325 && VOID_TYPE_P (TREE_TYPE (EXPR_STMT_EXPR (stripped_stmt))))
1326 {
1327 stripped_stmt = TREE_OPERAND (EXPR_STMT_EXPR (stripped_stmt), 0);
1328 stmt_code = TREE_CODE (stripped_stmt);
1329 }
1330 }
1331
1332 tree *buried_stmt = NULL;
1333 tree saved_co_await = NULL_TREE;
1334 enum tree_code sub_code = NOP_EXPR;
1335
1336 if (stmt_code == EXPR_STMT
1337 && TREE_CODE (EXPR_STMT_EXPR (stripped_stmt)) == CO_AWAIT_EXPR)
1338 saved_co_await
1339 = EXPR_STMT_EXPR (stripped_stmt); /* hopefully, a void exp. */
1340 else if (stmt_code == MODIFY_EXPR || stmt_code == INIT_EXPR)
1341 {
1342 sub_code = TREE_CODE (TREE_OPERAND (stripped_stmt, 1));
1343 if (sub_code == CO_AWAIT_EXPR)
1344 saved_co_await = TREE_OPERAND (stripped_stmt, 1); /* Get the RHS. */
1345 else if (tree r
1346 = cp_walk_tree (&TREE_OPERAND (stripped_stmt, 1),
1347 co_await_find_in_subtree, &buried_stmt, NULL))
1348 saved_co_await = r;
1349 }
1350 else if (stmt_code == CALL_EXPR)
1351 {
1352 if (tree r = cp_walk_tree (&stripped_stmt, co_await_find_in_subtree,
1353 &buried_stmt, NULL))
1354 saved_co_await = r;
1355 }
1356
1357 if (!saved_co_await)
1358 return NULL_TREE;
1359
1360 /* We want to splice in the await_resume() value in some cases. */
1361 tree saved_statement = *stmt;
1362
1363 tree actor = data->actor_fn;
1364 location_t loc = EXPR_LOCATION (*stmt);
1365 tree sv_handle = TREE_OPERAND (saved_co_await, 0);
1366 tree var = TREE_OPERAND (saved_co_await, 1); /* frame slot. */
1367 tree expr = TREE_OPERAND (saved_co_await, 2); /* initializer. */
1368 tree awaiter_calls = TREE_OPERAND (saved_co_await, 3);
1369
1370 tree source = TREE_OPERAND (saved_co_await, 4);
1371 bool is_final = (source
1372 && TREE_INT_CST_LOW (source) == (int) FINAL_SUSPEND_POINT);
1373 bool needs_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (var));
1374 int resume_point = data->index;
1375 size_t bufsize = sizeof ("destroy.") + 10;
1376 char *buf = (char *) alloca (bufsize);
1377 snprintf (buf, bufsize, "destroy.%d", resume_point);
1378 tree destroy_label = create_named_label_with_ctx (loc, buf, actor);
1379 snprintf (buf, bufsize, "resume.%d", resume_point);
1380 tree resume_label = create_named_label_with_ctx (loc, buf, actor);
1381 tree empty_list = build_empty_stmt (loc);
1382
1383 tree dtor = NULL_TREE;
1384 tree await_type = TREE_TYPE (var);
1385 if (needs_dtor)
1386 dtor = build_special_member_call (var, complete_dtor_identifier, NULL,
1387 await_type, LOOKUP_NORMAL,
1388 tf_warning_or_error);
1389
1390 tree stmt_list = NULL;
1391 /* Initialize the var from the provided 'o' expression. */
1392 tree r = build2 (INIT_EXPR, await_type, var, expr);
1393 r = coro_build_cvt_void_expr_stmt (r, loc);
1394 append_to_statement_list (r, &stmt_list);
1395
1396 /* Use the await_ready() call to test if we need to suspend. */
1397 tree ready_cond = TREE_VEC_ELT (awaiter_calls, 0); /* await_ready(). */
1398 ready_cond = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, ready_cond);
1399 ready_cond
1400 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, ready_cond);
1401
1402 tree body_list = NULL;
1403 tree susp_idx = build_int_cst (short_unsigned_type_node, data->index);
1404 r = build2_loc (loc, MODIFY_EXPR, short_unsigned_type_node, data->resume_idx,
1405 susp_idx);
1406 r = coro_build_cvt_void_expr_stmt (r, loc);
1407 append_to_statement_list (r, &body_list);
1408
1409 tree suspend = TREE_VEC_ELT (awaiter_calls, 1); /* await_suspend(). */
1410
1411 if (sv_handle == NULL_TREE)
1412 {
1413 /* void return, we just call it and hit the yield. */
1414 suspend = coro_build_cvt_void_expr_stmt (suspend, loc);
1415 append_to_statement_list (suspend, &body_list);
1416 }
1417 else if (sv_handle == boolean_type_node)
1418 {
1419 /* Boolean return, continue if the call returns false. */
1420 suspend = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_node, suspend);
1421 suspend
1422 = build1_loc (loc, CLEANUP_POINT_EXPR, boolean_type_node, suspend);
1423 tree go_on = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1424 r = build3_loc (loc, COND_EXPR, void_type_node, suspend, go_on,
1425 empty_list);
1426 append_to_statement_list (r, &body_list);
1427 }
1428 else
1429 {
1430 r = build2_loc (loc, INIT_EXPR, TREE_TYPE (sv_handle), sv_handle,
1431 suspend);
1432 append_to_statement_list (r, &body_list);
1433 tree resume
1434 = lookup_member (TREE_TYPE (sv_handle), coro_resume_identifier, 1, 0,
1435 tf_warning_or_error);
1436 resume = build_new_method_call (sv_handle, resume, NULL, NULL_TREE,
1437 LOOKUP_NORMAL, NULL, tf_warning_or_error);
1438 resume = coro_build_cvt_void_expr_stmt (resume, loc);
1439 append_to_statement_list (resume, &body_list);
1440 }
1441
1442 tree d_l
1443 = build1 (ADDR_EXPR, build_reference_type (void_type_node), destroy_label);
1444 tree r_l
1445 = build1 (ADDR_EXPR, build_reference_type (void_type_node), resume_label);
1446 tree susp
1447 = build1 (ADDR_EXPR, build_reference_type (void_type_node), data->cororet);
1448 tree final_susp = build_int_cst (integer_type_node, is_final ? 1 : 0);
1449
1450 susp_idx = build_int_cst (integer_type_node, data->index);
1451
1452 tree sw = begin_switch_stmt ();
1453 tree cond = build_decl (loc, VAR_DECL, NULL_TREE, integer_type_node);
1454 DECL_ARTIFICIAL (cond) = 1;
1455 DECL_IGNORED_P (cond) = 1;
1456 layout_decl (cond, 0);
1457
1458 r = build_call_expr_internal_loc (loc, IFN_CO_YIELD, integer_type_node, 5,
1459 susp_idx, final_susp, r_l, d_l,
1460 data->coro_fp);
1461 r = build2 (INIT_EXPR, integer_type_node, cond, r);
1462 finish_switch_cond (r, sw);
1463 r = build_case_label (build_int_cst (integer_type_node, 0), NULL_TREE,
1464 create_anon_label_with_ctx (loc, actor));
1465 add_stmt (r); /* case 0: */
1466 /* Implement the suspend, a scope exit without clean ups. */
1467 r = build_call_expr_internal_loc (loc, IFN_CO_SUSPN, void_type_node, 1, susp);
1468 r = coro_build_cvt_void_expr_stmt (r, loc);
1469 add_stmt (r); // goto ret;
1470 r = build_case_label (build_int_cst (integer_type_node, 1), NULL_TREE,
1471 create_anon_label_with_ctx (loc, actor));
1472 add_stmt (r); // case 1:
1473 r = build1_loc (loc, GOTO_EXPR, void_type_node, resume_label);
1474 add_stmt (r); // goto resume;
1475 r = build_case_label (NULL_TREE, NULL_TREE,
1476 create_anon_label_with_ctx (loc, actor));
1477 add_stmt (r); // default:;
1478 r = build1_loc (loc, GOTO_EXPR, void_type_node, destroy_label);
1479 add_stmt (r); // goto destroy;
1480
1481 /* part of finish switch. */
1482 SWITCH_STMT_BODY (sw) = pop_stmt_list (SWITCH_STMT_BODY (sw));
1483 pop_switch ();
1484 tree scope = SWITCH_STMT_SCOPE (sw);
1485 SWITCH_STMT_SCOPE (sw) = NULL;
1486 r = do_poplevel (scope);
1487 append_to_statement_list (r, &body_list);
1488
1489 destroy_label = build_stmt (loc, LABEL_EXPR, destroy_label);
1490 append_to_statement_list (destroy_label, &body_list);
1491 if (needs_dtor)
1492 append_to_statement_list (dtor, &body_list);
1493 r = build1_loc (loc, GOTO_EXPR, void_type_node, data->cleanup);
1494 append_to_statement_list (r, &body_list);
1495
1496 r = build3_loc (loc, COND_EXPR, void_type_node, ready_cond, body_list,
1497 empty_list);
1498
1499 append_to_statement_list (r, &stmt_list);
1500
1501 /* Resume point. */
1502 resume_label = build_stmt (loc, LABEL_EXPR, resume_label);
1503 append_to_statement_list (resume_label, &stmt_list);
1504
1505 /* This will produce the value (if one is provided) from the co_await
1506 expression. */
1507 tree resume_call = TREE_VEC_ELT (awaiter_calls, 2); /* await_resume(). */
1508 switch (stmt_code)
1509 {
1510 default: /* not likely to work .. but... */
1511 append_to_statement_list (resume_call, &stmt_list);
1512 break;
1513 case INIT_EXPR:
1514 case MODIFY_EXPR:
1515 case CALL_EXPR:
1516 /* Replace the use of co_await by the resume expr. */
1517 if (sub_code == CO_AWAIT_EXPR)
1518 {
1519 /* We're updating the interior of a possibly <(void) expr>cleanup. */
1520 TREE_OPERAND (stripped_stmt, 1) = resume_call;
1521 append_to_statement_list (saved_statement, &stmt_list);
1522 }
1523 else if (buried_stmt != NULL)
1524 {
1525 *buried_stmt = resume_call;
1526 append_to_statement_list (saved_statement, &stmt_list);
1527 }
1528 else
1529 {
1530 error_at (loc, "failed to substitute the resume method in %qE",
1531 saved_statement);
1532 append_to_statement_list (saved_statement, &stmt_list);
1533 }
1534 break;
1535 }
1536 if (needs_dtor)
1537 append_to_statement_list (dtor, &stmt_list);
1538 data->index += 2;
1539 *stmt = stmt_list;
1540 return NULL_TREE;
1541 }
1542
1543 static tree
1544 expand_co_awaits (tree fn, tree *fnbody, tree coro_fp, tree resume_idx,
1545 tree cleanup, tree cororet, tree self_h)
1546 {
1547 coro_aw_data data
1548 = {fn, coro_fp, resume_idx, self_h, cleanup, cororet, 2};
1549 cp_walk_tree (fnbody, co_await_expander, &data, NULL);
1550 return *fnbody;
1551 }
1552
1553 /* Suspend point hash_map. */
1554
1555 struct suspend_point_info
1556 {
1557 /* coro frame field type. */
1558 tree awaitable_type;
1559 /* coro frame field name. */
1560 tree await_field_id;
1561 /* suspend method return type. */
1562 tree suspend_type;
1563 /* suspend handle field name, NULL_TREE if not needed. */
1564 tree susp_handle_id;
1565 };
1566
1567 static hash_map<tree, suspend_point_info> *suspend_points;
1568
1569 struct await_xform_data
1570 {
1571 tree actor_frame;
1572 tree promise_proxy;
1573 tree real_promise;
1574 tree self_h_proxy;
1575 tree real_self_h;
1576 };
1577
1578 /* When we built the await expressions, we didn't know the coro frame
1579 layout, therefore no idea where to find the promise or where to put
1580 the awaitables. Now we know these things, fill them in. */
1581
1582 static tree
1583 transform_await_expr (tree await_expr, await_xform_data *xform)
1584 {
1585 suspend_point_info *si = suspend_points->get (await_expr);
1586 location_t loc = EXPR_LOCATION (await_expr);
1587 if (!si)
1588 {
1589 error_at (loc, "no suspend point info for %qD", await_expr);
1590 return error_mark_node;
1591 }
1592
1593 /* So, on entry, we have:
1594 in : CO_AWAIT_EXPR (a, e_proxy, o, awr_call_vector, mode)
1595 We no longer need a [it had diagnostic value, maybe?]
1596 We need to replace the promise proxy in all elements
1597 We need to replace the e_proxy in the awr_call.
1598 */
1599
1600 tree coro_frame_type = TREE_TYPE (xform->actor_frame);
1601 tree ah = NULL_TREE;
1602 if (si->susp_handle_id)
1603 {
1604 tree ah_m
1605 = lookup_member (coro_frame_type, si->susp_handle_id,
1606 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
1607 ah = build_class_member_access_expr (xform->actor_frame, ah_m, NULL_TREE,
1608 true, tf_warning_or_error);
1609 }
1610 else if (TREE_CODE (si->suspend_type) == BOOLEAN_TYPE)
1611 ah = boolean_type_node;
1612
1613 /* Replace Op 0 with the frame slot for the temporary handle, if it's needed.
1614 If there's no frame type to be stored we flag boolean_type for that case
1615 and an empty pointer for void return. */
1616 TREE_OPERAND (await_expr, 0) = ah;
1617
1618 /* Get a reference to the initial suspend var in the frame. */
1619 tree as_m
1620 = lookup_member (coro_frame_type, si->await_field_id,
1621 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
1622 tree as = build_class_member_access_expr (xform->actor_frame, as_m, NULL_TREE,
1623 true, tf_warning_or_error);
1624
1625 /* Replace references to the instance proxy with the frame entry now
1626 computed. */
1627 proxy_replace data = {TREE_OPERAND (await_expr, 1), as};
1628 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1629
1630 /* .. and replace. */
1631 TREE_OPERAND (await_expr, 1) = as;
1632
1633 /* Now do the self_handle. */
1634 data.from = xform->self_h_proxy;
1635 data.to = xform->real_self_h;
1636 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1637
1638 /* Now do the promise. */
1639 data.from = xform->promise_proxy;
1640 data.to = xform->real_promise;
1641 cp_walk_tree (&await_expr, replace_proxy, &data, NULL);
1642
1643 return await_expr;
1644 }
1645
1646 /* A wrapper for the transform_await_expr function so that it can be a
1647 callback from cp_walk_tree. */
1648
1649 static tree
1650 transform_await_wrapper (tree *stmt, int *do_subtree, void *d)
1651 {
1652 if (TREE_CODE (*stmt) != CO_AWAIT_EXPR && TREE_CODE (*stmt) != CO_YIELD_EXPR)
1653 return NULL_TREE;
1654
1655 tree await_expr = *stmt;
1656 await_xform_data *xform = (await_xform_data *) d;
1657
1658 *stmt = transform_await_expr (await_expr, xform);
1659 if (*stmt == error_mark_node)
1660 *do_subtree = 0;
1661 return NULL_TREE;
1662 }
1663
1664 struct param_info
1665 {
1666 tree field_id;
1667 vec<tree *> *body_uses;
1668 tree frame_type;
1669 };
1670
1671 struct local_var_info
1672 {
1673 tree field_id;
1674 tree field_idx;
1675 tree frame_type;
1676 tree captured;
1677 location_t def_loc;
1678 };
1679
1680 /* For figuring out what local variable usage we have. */
1681 struct local_vars_transform
1682 {
1683 tree context;
1684 tree actor_frame;
1685 tree coro_frame_type;
1686 location_t loc;
1687 hash_map<tree, local_var_info> *local_var_uses;
1688 };
1689
1690 static tree
1691 transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
1692 {
1693 local_vars_transform *lvd = (local_vars_transform *) d;
1694
1695 /* For each var in this bind expr (that has a frame id, which means it was
1696 accessed), build a frame reference for each and then walk the bind expr
1697 statements, substituting the frame ref for the original var. */
1698
1699 if (TREE_CODE (*stmt) == BIND_EXPR)
1700 {
1701 tree lvar;
1702 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
1703 lvar = DECL_CHAIN (lvar))
1704 {
1705 bool existed;
1706 local_var_info &local_var
1707 = lvd->local_var_uses->get_or_insert (lvar, &existed);
1708 gcc_checking_assert (existed);
1709
1710 /* Re-write the variable's context to be in the actor func. */
1711 DECL_CONTEXT (lvar) = lvd->context;
1712
1713 /* we need to walk some of the decl trees, which might contain
1714 references to vars replaced at a higher level. */
1715 cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
1716 NULL);
1717 cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
1718 cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
1719 NULL);
1720
1721 /* TODO: implement selective generation of fields when vars are
1722 known not-used. */
1723 if (local_var.field_id == NULL_TREE)
1724 continue; /* Wasn't used. */
1725
1726 tree fld_ref
1727 = lookup_member (lvd->coro_frame_type, local_var.field_id,
1728 /*protect*/ 1, /*want_type*/ 0,
1729 tf_warning_or_error);
1730 tree fld_idx = build3_loc (lvd->loc, COMPONENT_REF, TREE_TYPE (lvar),
1731 lvd->actor_frame, fld_ref, NULL_TREE);
1732 local_var.field_idx = fld_idx;
1733 }
1734 cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
1735 /* Now we have processed and removed references to the original vars,
1736 we can drop those from the bind. */
1737 for (tree *pvar = &BIND_EXPR_VARS (*stmt); *pvar != NULL;)
1738 {
1739 bool existed;
1740 local_var_info &local_var
1741 = lvd->local_var_uses->get_or_insert (*pvar, &existed);
1742 gcc_checking_assert (existed);
1743
1744 if (local_var.field_id == NULL_TREE)
1745 pvar = &DECL_CHAIN (*pvar); /* Wasn't used. */
1746
1747 *pvar = DECL_CHAIN (*pvar); // discard this one, we replaced it.
1748 }
1749
1750 *do_subtree = 0; /* We've done the body already. */
1751 return NULL_TREE;
1752 }
1753
1754 tree var_decl = *stmt;
1755 /* Look inside cleanups, we don't want to wrap a statement list in a
1756 cleanup. */
1757 bool needs_cleanup = true;
1758 if (TREE_CODE (var_decl) == CLEANUP_POINT_EXPR)
1759 var_decl = TREE_OPERAND (var_decl, 0);
1760 else
1761 needs_cleanup = false;
1762
1763 /* Look inside the decl_expr for the actual var. */
1764 bool decl_expr_p = TREE_CODE (var_decl) == DECL_EXPR;
1765 if (decl_expr_p && TREE_CODE (DECL_EXPR_DECL (var_decl)) == VAR_DECL)
1766 var_decl = DECL_EXPR_DECL (var_decl);
1767 else if (TREE_CODE (var_decl) != VAR_DECL)
1768 return NULL_TREE;
1769
1770 /* VAR_DECLs that are not recorded can belong to the proxies we've placed
1771 for the promise and coroutine handle(s), to global vars or to compiler
1772 temporaries. Skip past these, we will handle them later. */
1773 local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
1774 if (local_var_i == NULL)
1775 return NULL_TREE;
1776
1777 /* This is our revised 'local' i.e. a frame slot. */
1778 tree revised = local_var_i->field_idx;
1779 gcc_checking_assert (DECL_CONTEXT (var_decl) == lvd->context);
1780
1781 if (decl_expr_p && DECL_INITIAL (var_decl))
1782 {
1783 location_t loc = DECL_SOURCE_LOCATION (var_decl);
1784 tree r
1785 = cp_build_modify_expr (loc, revised, INIT_EXPR,
1786 DECL_INITIAL (var_decl), tf_warning_or_error);
1787 if (needs_cleanup)
1788 r = coro_build_cvt_void_expr_stmt (r, EXPR_LOCATION (*stmt));
1789 *stmt = r;
1790 }
1791 else
1792 *stmt = revised;
1793
1794 if (decl_expr_p)
1795 *do_subtree = 0; /* We've accounted for the nested use. */
1796 return NULL_TREE;
1797 }
1798
1799 /* The actor transform. */
1800
1801 static void
1802 build_actor_fn (location_t loc, tree coro_frame_type, tree actor, tree fnbody,
1803 tree orig, hash_map<tree, param_info> *param_uses,
1804 hash_map<tree, local_var_info> *local_var_uses,
1805 vec<tree, va_gc> *param_dtor_list, tree initial_await,
1806 tree final_await, unsigned body_count)
1807 {
1808 verify_stmt_tree (fnbody);
1809 /* Some things we inherit from the original function. */
1810 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
1811 tree handle_type = get_coroutine_handle_type (orig);
1812 tree self_h_proxy = get_coroutine_self_handle_proxy (orig);
1813 tree promise_type = get_coroutine_promise_type (orig);
1814 tree promise_proxy = get_coroutine_promise_proxy (orig);
1815 tree act_des_fn_type
1816 = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
1817 tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
1818
1819 /* One param, the coro frame pointer. */
1820 tree actor_fp
1821 = build_lang_decl (PARM_DECL, get_identifier ("frame_ptr"), coro_frame_ptr);
1822 DECL_CONTEXT (actor_fp) = actor;
1823 DECL_ARG_TYPE (actor_fp) = type_passed_as (coro_frame_ptr);
1824 DECL_ARGUMENTS (actor) = actor_fp;
1825
1826 /* A void return. */
1827 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
1828 DECL_ARTIFICIAL (resdecl) = 1;
1829 DECL_IGNORED_P (resdecl) = 1;
1830 DECL_RESULT (actor) = resdecl;
1831 DECL_COROUTINE_P (actor) = 1;
1832
1833 /* We have a definition here. */
1834 TREE_STATIC (actor) = 1;
1835
1836 tree actor_outer = push_stmt_list ();
1837 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
1838 tree stmt = begin_compound_stmt (BCS_FN_BODY);
1839
1840 /* ??? Can we dispense with the enclosing bind if the function body does
1841 not start with a bind_expr? (i.e. there's no contained scopes). */
1842 tree actor_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
1843 tree top_block = make_node (BLOCK);
1844 BIND_EXPR_BLOCK (actor_bind) = top_block;
1845
1846 /* Update the block associated with the outer scope of the orig fn. */
1847 tree first = expr_first (fnbody);
1848 if (first && TREE_CODE (first) == BIND_EXPR)
1849 {
1850 /* We will discard this, since it's connected to the original scope
1851 nest. */
1852 tree block = BIND_EXPR_BLOCK (first);
1853 if (block) // For this to be missing is probably a bug.
1854 {
1855 gcc_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
1856 gcc_assert (BLOCK_CHAIN (block) == NULL_TREE);
1857 BLOCK_SUPERCONTEXT (block) = top_block;
1858 BLOCK_SUBBLOCKS (top_block) = block;
1859 }
1860 }
1861
1862 add_stmt (actor_bind);
1863 tree actor_body = push_stmt_list ();
1864
1865 /* The entry point for the actor code from the ramp. */
1866 tree actor_begin_label
1867 = create_named_label_with_ctx (loc, "actor.begin", actor);
1868 tree actor_frame = build1_loc (loc, INDIRECT_REF, coro_frame_type, actor_fp);
1869
1870 /* Re-write param references in the body, no code should be generated
1871 here. */
1872 if (DECL_ARGUMENTS (orig) && param_uses != NULL)
1873 {
1874 tree arg;
1875 for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
1876 {
1877 bool existed;
1878 param_info &parm = param_uses->get_or_insert (arg, &existed);
1879 if (parm.field_id == NULL_TREE)
1880 continue; /* Wasn't used. */
1881 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
1882 /*protect*/ 1, /*want_type*/ 0,
1883 tf_warning_or_error);
1884 tree fld_idx = build3_loc (loc, COMPONENT_REF, TREE_TYPE (arg),
1885 actor_frame, fld_ref, NULL_TREE);
1886 int i;
1887 tree *puse;
1888 FOR_EACH_VEC_ELT (*parm.body_uses, i, puse)
1889 {
1890 *puse = fld_idx;
1891 }
1892 }
1893 }
1894
1895 /* Re-write local vars, similarly. */
1896 local_vars_transform xform_vars_data
1897 = {actor, actor_frame, coro_frame_type, loc, local_var_uses};
1898 cp_walk_tree (&fnbody, transform_local_var_uses, &xform_vars_data, NULL);
1899
1900 tree resume_idx_name = get_identifier ("__resume_at");
1901 tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
1902 tf_warning_or_error);
1903 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, actor_frame,
1904 rat_field, NULL_TREE);
1905
1906 tree ret_label
1907 = create_named_label_with_ctx (loc, "actor.suspend.ret", actor);
1908
1909 tree lsb_if = begin_if_stmt ();
1910 tree chkb0 = build2 (BIT_AND_EXPR, short_unsigned_type_node, rat,
1911 build_int_cst (short_unsigned_type_node, 1));
1912 chkb0 = build2 (NE_EXPR, short_unsigned_type_node, chkb0,
1913 build_int_cst (short_unsigned_type_node, 0));
1914 finish_if_stmt_cond (chkb0, lsb_if);
1915
1916 tree destroy_dispatcher = begin_switch_stmt ();
1917 finish_switch_cond (rat, destroy_dispatcher);
1918 tree ddeflab = build_case_label (NULL_TREE, NULL_TREE,
1919 create_anon_label_with_ctx (loc, actor));
1920 add_stmt (ddeflab);
1921 tree b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1922 b = coro_build_cvt_void_expr_stmt (b, loc);
1923 add_stmt (b);
1924
1925 short unsigned lab_num = 3;
1926 for (unsigned destr_pt = 0; destr_pt < body_count + 2; destr_pt++)
1927 {
1928 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
1929 b = build_case_label (l_num, NULL_TREE,
1930 create_anon_label_with_ctx (loc, actor));
1931 add_stmt (b);
1932 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
1933 l_num);
1934 b = coro_build_cvt_void_expr_stmt (b, loc);
1935 add_stmt (b);
1936 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (ddeflab));
1937 add_stmt (b);
1938 lab_num += 2;
1939 }
1940
1941 /* Insert the prototype dispatcher. */
1942 finish_switch_stmt (destroy_dispatcher);
1943
1944 finish_then_clause (lsb_if);
1945
1946 tree dispatcher = begin_switch_stmt ();
1947 finish_switch_cond (rat, dispatcher);
1948 b = build_case_label (build_int_cst (short_unsigned_type_node, 0), NULL_TREE,
1949 create_anon_label_with_ctx (loc, actor));
1950 add_stmt (b);
1951 b = build1 (GOTO_EXPR, void_type_node, actor_begin_label);
1952 add_stmt (b);
1953
1954 tree rdeflab = build_case_label (NULL_TREE, NULL_TREE,
1955 create_anon_label_with_ctx (loc, actor));
1956 add_stmt (rdeflab);
1957 b = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
1958 b = coro_build_cvt_void_expr_stmt (b, loc);
1959 add_stmt (b);
1960
1961 lab_num = 2;
1962 /* The final resume should be made to hit the default (trap, UB) entry. */
1963 for (unsigned resu_pt = 0; resu_pt < body_count + 1; resu_pt++)
1964 {
1965 tree l_num = build_int_cst (short_unsigned_type_node, lab_num);
1966 b = build_case_label (l_num, NULL_TREE,
1967 create_anon_label_with_ctx (loc, actor));
1968 add_stmt (b);
1969 b = build_call_expr_internal_loc (loc, IFN_CO_ACTOR, void_type_node, 1,
1970 l_num);
1971 b = coro_build_cvt_void_expr_stmt (b, loc);
1972 add_stmt (b);
1973 b = build1 (GOTO_EXPR, void_type_node, CASE_LABEL (rdeflab));
1974 add_stmt (b);
1975 lab_num += 2;
1976 }
1977
1978 /* Insert the prototype dispatcher. */
1979 finish_switch_stmt (dispatcher);
1980
1981 finish_if_stmt (lsb_if);
1982
1983 tree r = build_stmt (loc, LABEL_EXPR, actor_begin_label);
1984 add_stmt (r);
1985
1986 /* actor's version of the promise. */
1987 tree ap_m = lookup_member (coro_frame_type, get_identifier ("__p"), 1, 0,
1988 tf_warning_or_error);
1989 tree ap = build_class_member_access_expr (actor_frame, ap_m, NULL_TREE, false,
1990 tf_warning_or_error);
1991
1992 /* actor's coroutine 'self handle'. */
1993 tree ash_m = lookup_member (coro_frame_type, get_identifier ("__self_h"), 1,
1994 0, tf_warning_or_error);
1995 tree ash = build_class_member_access_expr (actor_frame, ash_m, NULL_TREE,
1996 false, tf_warning_or_error);
1997 /* So construct the self-handle from the frame address. */
1998 tree hfa_m = lookup_member (handle_type, coro_from_address_identifier, 1,
1999 0, tf_warning_or_error);
2000
2001 r = build1 (CONVERT_EXPR, build_pointer_type (void_type_node), actor_fp);
2002 vec<tree, va_gc> *args = make_tree_vector_single (r);
2003 tree hfa = build_new_method_call (ash, hfa_m, &args, NULL_TREE, LOOKUP_NORMAL,
2004 NULL, tf_warning_or_error);
2005 r = build2 (INIT_EXPR, handle_type, ash, hfa);
2006 r = coro_build_cvt_void_expr_stmt (r, loc);
2007 add_stmt (r);
2008 release_tree_vector (args);
2009
2010 /* Now we know the real promise, and enough about the frame layout to
2011 decide where to put things. */
2012
2013 await_xform_data xform
2014 = {actor_frame, promise_proxy, ap, self_h_proxy, ash};
2015
2016 /* Get a reference to the initial suspend var in the frame. */
2017 transform_await_expr (initial_await, &xform);
2018 r = coro_build_expr_stmt (initial_await, loc);
2019 add_stmt (r);
2020
2021 /* Now we've built the promise etc, process fnbody for co_returns.
2022 We want the call to return_void () below and it has no params so
2023 we can create it once here.
2024 Calls to return_value () will have to be checked and created as
2025 required. */
2026
2027 tree return_void = NULL_TREE;
2028 tree rvm
2029 = lookup_promise_method (orig, coro_return_void_identifier, loc,
2030 /*musthave=*/ false);
2031 if (rvm && rvm != error_mark_node)
2032 return_void
2033 = build_new_method_call (ap, rvm, NULL, NULL_TREE, LOOKUP_NORMAL, NULL,
2034 tf_warning_or_error);
2035
2036 /* co_return branches to the final_suspend label, so declare that now. */
2037 tree fs_label = create_named_label_with_ctx (loc, "final.suspend", actor);
2038
2039 /* Expand co_returns in the saved function body */
2040 fnbody = expand_co_returns (&fnbody, promise_proxy, ap, fs_label);
2041
2042 /* Transform the await expressions in the function body. Only do each
2043 await tree once! */
2044 hash_set<tree> pset;
2045 cp_walk_tree (&fnbody, transform_await_wrapper, &xform, &pset);
2046
2047 /* Add in our function body with the co_returns rewritten to final form. */
2048 add_stmt (fnbody);
2049
2050 /* [stmt.return.coroutine] (2.2 : 3) if p.return_void() is a valid
2051 expression, flowing off the end of a coroutine is equivalent to
2052 co_return; otherwise UB.
2053 We just inject the call to p.return_void() here, and fall through to
2054 the final_suspend: label (eliding the goto). If the function body has
2055 a co_return, then this statement will be unreachable and DCEd. */
2056 if (return_void != NULL_TREE)
2057 add_stmt (return_void);
2058
2059 /* Final suspend starts here. */
2060 r = build_stmt (loc, LABEL_EXPR, fs_label);
2061 add_stmt (r);
2062
2063 /* Set the actor pointer to null, so that 'done' will work.
2064 Resume from here is UB anyway - although a 'ready' await will
2065 branch to the final resume, and fall through to the destroy. */
2066 tree resume_m
2067 = lookup_member (coro_frame_type, get_identifier ("__resume"),
2068 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
2069 tree res_x = build_class_member_access_expr (actor_frame, resume_m, NULL_TREE,
2070 false, tf_warning_or_error);
2071 r = build1 (CONVERT_EXPR, act_des_fn_ptr, integer_zero_node);
2072 r = build2 (INIT_EXPR, act_des_fn_ptr, res_x, r);
2073 r = coro_build_cvt_void_expr_stmt (r, loc);
2074 add_stmt (r);
2075
2076 /* Get a reference to the final suspend var in the frame. */
2077 transform_await_expr (final_await, &xform);
2078 r = coro_build_expr_stmt (final_await, loc);
2079 add_stmt (r);
2080
2081 /* now do the tail of the function. */
2082 tree del_promise_label
2083 = create_named_label_with_ctx (loc, "coro.delete.promise", actor);
2084 r = build_stmt (loc, LABEL_EXPR, del_promise_label);
2085 add_stmt (r);
2086
2087 /* Destructors for the things we built explicitly. */
2088 r = build_special_member_call (ap, complete_dtor_identifier, NULL,
2089 promise_type, LOOKUP_NORMAL,
2090 tf_warning_or_error);
2091 add_stmt (r);
2092
2093 tree del_frame_label
2094 = create_named_label_with_ctx (loc, "coro.delete.frame", actor);
2095 r = build_stmt (loc, LABEL_EXPR, del_frame_label);
2096 add_stmt (r);
2097
2098 /* Here deallocate the frame (if we allocated it), which we will have at
2099 present. */
2100 tree fnf_m
2101 = lookup_member (coro_frame_type, get_identifier ("__frame_needs_free"), 1,
2102 0, tf_warning_or_error);
2103 tree fnf2_x = build_class_member_access_expr (actor_frame, fnf_m, NULL_TREE,
2104 false, tf_warning_or_error);
2105
2106 tree need_free_if = begin_if_stmt ();
2107 fnf2_x = build1 (CONVERT_EXPR, integer_type_node, fnf2_x);
2108 tree cmp = build2 (NE_EXPR, integer_type_node, fnf2_x, integer_zero_node);
2109 finish_if_stmt_cond (cmp, need_free_if);
2110 if (param_dtor_list != NULL)
2111 {
2112 int i;
2113 tree pid;
2114 FOR_EACH_VEC_ELT (*param_dtor_list, i, pid)
2115 {
2116 tree m
2117 = lookup_member (coro_frame_type, pid, 1, 0, tf_warning_or_error);
2118 tree a = build_class_member_access_expr (actor_frame, m, NULL_TREE,
2119 false, tf_warning_or_error);
2120 tree t = TREE_TYPE (a);
2121 tree dtor;
2122 dtor
2123 = build_special_member_call (a, complete_dtor_identifier, NULL, t,
2124 LOOKUP_NORMAL, tf_warning_or_error);
2125 add_stmt (dtor);
2126 }
2127 }
2128
2129 tree delname = ovl_op_identifier (false, DELETE_EXPR);
2130 tree arg = build1 (CONVERT_EXPR, ptr_type_node, actor_fp);
2131 vec<tree, va_gc> *arglist = make_tree_vector_single (arg);
2132
2133 /* The user can (optionally) provide a delete function in the promise
2134 type, it's not a failure for it to be absent. */
2135 tree fns = lookup_promise_method (orig, delname, loc, false);
2136 tree del_coro_fr = NULL_TREE;
2137 if (fns && fns != error_mark_node)
2138 {
2139 del_coro_fr = lookup_arg_dependent (delname, fns, arglist);
2140 if (OVL_P (del_coro_fr))
2141 del_coro_fr = OVL_FIRST (del_coro_fr);
2142 else
2143 del_coro_fr = BASELINK_FUNCTIONS (del_coro_fr);
2144
2145 gcc_checking_assert (DECL_STATIC_FUNCTION_P (del_coro_fr));
2146 TREE_USED (del_coro_fr) = 1;
2147 del_coro_fr = build_call_expr_loc_vec (loc, del_coro_fr, arglist);
2148 }
2149
2150 /* If that fails, then fall back to the global delete operator. */
2151 if (del_coro_fr == NULL_TREE || del_coro_fr == error_mark_node)
2152 {
2153 fns =lookup_name_real (delname, 0, 1, /*block_p=*/true, 0, 0);
2154 del_coro_fr = lookup_arg_dependent (del_coro_fr, fns, arglist);
2155 del_coro_fr = build_new_function_call (del_coro_fr, &arglist, true);
2156 }
2157
2158 del_coro_fr = coro_build_cvt_void_expr_stmt (del_coro_fr, loc);
2159 add_stmt (del_coro_fr);
2160 finish_then_clause (need_free_if);
2161 tree scope = IF_SCOPE (need_free_if);
2162 IF_SCOPE (need_free_if) = NULL;
2163 r = do_poplevel (scope);
2164 add_stmt (r);
2165
2166 /* done. */
2167 r = build_stmt (loc, RETURN_EXPR, NULL);
2168 TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this. */
2169 r = maybe_cleanup_point_expr_void (r);
2170 add_stmt (r);
2171
2172 /* This is the suspend return point. */
2173 r = build_stmt (loc, LABEL_EXPR, ret_label);
2174 add_stmt (r);
2175
2176 r = build_stmt (loc, RETURN_EXPR, NULL);
2177 TREE_NO_WARNING (r) |= 1; /* We don't want a warning about this. */
2178 r = maybe_cleanup_point_expr_void (r);
2179 add_stmt (r);
2180
2181 /* We need the resume index to work with. */
2182 tree res_idx_m
2183 = lookup_member (coro_frame_type, resume_idx_name,
2184 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
2185 tree res_idx
2186 = build_class_member_access_expr (actor_frame, res_idx_m, NULL_TREE, false,
2187 tf_warning_or_error);
2188
2189 /* We've now rewritten the tree and added the initial and final
2190 co_awaits. Now pass over the tree and expand the co_awaits. */
2191 actor_body = expand_co_awaits (actor, &actor_body, actor_fp, res_idx,
2192 del_promise_label, ret_label, ash);
2193
2194 actor_body = pop_stmt_list (actor_body);
2195 BIND_EXPR_BODY (actor_bind) = actor_body;
2196
2197 finish_compound_stmt (stmt);
2198 DECL_SAVED_TREE (actor) = pop_stmt_list (actor_outer);
2199 verify_stmt_tree (DECL_SAVED_TREE (actor));
2200 }
2201
2202 /* The prototype 'destroy' function :
2203 frame->__resume_at |= 1;
2204 actor (frame); */
2205
2206 static void
2207 build_destroy_fn (location_t loc, tree coro_frame_type, tree destroy,
2208 tree actor)
2209 {
2210 /* One param, the coro frame pointer. */
2211 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
2212 tree destr_fp
2213 = build_lang_decl (PARM_DECL, get_identifier ("frame_ptr"), coro_frame_ptr);
2214 DECL_CONTEXT (destr_fp) = destroy;
2215 DECL_ARG_TYPE (destr_fp) = type_passed_as (coro_frame_ptr);
2216 DECL_ARGUMENTS (destroy) = destr_fp;
2217
2218 /* A void return. */
2219 tree resdecl = build_decl (loc, RESULT_DECL, 0, void_type_node);
2220 DECL_ARTIFICIAL (resdecl) = 1;
2221 DECL_IGNORED_P (resdecl) = 1;
2222 DECL_RESULT (destroy) = resdecl;
2223
2224 /* We have a definition here. */
2225 TREE_STATIC (destroy) = 1;
2226 DECL_COROUTINE_P (destroy) = 1;
2227
2228 tree destr_outer = push_stmt_list ();
2229 current_stmt_tree ()->stmts_are_full_exprs_p = 1;
2230 tree dstr_stmt = begin_compound_stmt (BCS_FN_BODY);
2231
2232 tree destr_frame = build1 (INDIRECT_REF, coro_frame_type, destr_fp);
2233
2234 tree resume_idx_name = get_identifier ("__resume_at");
2235 tree rat_field = lookup_member (coro_frame_type, resume_idx_name, 1, 0,
2236 tf_warning_or_error);
2237 tree rat = build3 (COMPONENT_REF, short_unsigned_type_node, destr_frame,
2238 rat_field, NULL_TREE);
2239
2240 /* _resume_at |= 1 */
2241 tree dstr_idx = build2 (BIT_IOR_EXPR, short_unsigned_type_node, rat,
2242 build_int_cst (short_unsigned_type_node, 1));
2243 tree r = build2 (MODIFY_EXPR, short_unsigned_type_node, rat, dstr_idx);
2244 r = coro_build_cvt_void_expr_stmt (r, loc);
2245 add_stmt (r);
2246
2247 /* So .. call the actor .. */
2248 r = build_call_expr_loc (loc, actor, 1, destr_fp);
2249 r = coro_build_cvt_void_expr_stmt (r, loc);
2250 add_stmt (r);
2251
2252 /* done. */
2253 r = build_stmt (loc, RETURN_EXPR, NULL);
2254 r = maybe_cleanup_point_expr_void (r);
2255 add_stmt (r);
2256
2257 finish_compound_stmt (dstr_stmt);
2258 DECL_SAVED_TREE (destroy) = pop_stmt_list (destr_outer);
2259 }
2260
2261 /* Helper that returns an identifier for an appended extension to the
2262 current un-mangled function name. */
2263
2264 static tree
2265 get_fn_local_identifier (tree orig, const char *append)
2266 {
2267 /* Figure out the bits we need to generate names for the outlined things
2268 For consistency, this needs to behave the same way as
2269 ASM_FORMAT_PRIVATE_NAME does. */
2270 tree nm = DECL_NAME (orig);
2271 const char *sep, *pfx = "";
2272 #ifndef NO_DOT_IN_LABEL
2273 sep = ".";
2274 #else
2275 #ifndef NO_DOLLAR_IN_LABEL
2276 sep = "$";
2277 #else
2278 sep = "_";
2279 pfx = "__";
2280 #endif
2281 #endif
2282
2283 char *an;
2284 if (DECL_ASSEMBLER_NAME (orig))
2285 an = ACONCAT ((IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (orig)), sep, append,
2286 (char *) 0));
2287 else if (DECL_USE_TEMPLATE (orig) && DECL_TEMPLATE_INFO (orig)
2288 && DECL_TI_ARGS (orig))
2289 {
2290 tree tpl_args = DECL_TI_ARGS (orig);
2291 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), (char *) 0));
2292 for (int i = 0; i < TREE_VEC_LENGTH (tpl_args); ++i)
2293 {
2294 tree typ = DECL_NAME (TYPE_NAME (TREE_VEC_ELT (tpl_args, i)));
2295 an = ACONCAT ((an, sep, IDENTIFIER_POINTER (typ), (char *) 0));
2296 }
2297 an = ACONCAT ((an, sep, append, (char *) 0));
2298 }
2299 else
2300 an = ACONCAT ((pfx, IDENTIFIER_POINTER (nm), sep, append, (char *) 0));
2301
2302 return get_identifier (an);
2303 }
2304
2305 static tree
2306 build_init_or_final_await (location_t loc, bool is_final)
2307 {
2308 tree suspend_alt = is_final ? coro_final_suspend_identifier
2309 : coro_initial_suspend_identifier;
2310 tree setup_meth = lookup_promise_method (current_function_decl, suspend_alt,
2311 loc, /*musthave=*/ true);
2312 if (!setup_meth || setup_meth == error_mark_node)
2313 return error_mark_node;
2314
2315 tree s_fn = NULL_TREE;
2316 tree setup_call = build_new_method_call (
2317 get_coroutine_promise_proxy (current_function_decl), setup_meth, NULL,
2318 NULL_TREE, LOOKUP_NORMAL, &s_fn, tf_warning_or_error);
2319
2320 if (!s_fn || setup_call == error_mark_node)
2321 return error_mark_node;
2322
2323 /* So build the co_await for this */
2324 /* For initial/final suspends the call is is "a" per [expr.await] 3.2. */
2325 return build_co_await (loc, setup_call, (is_final ? FINAL_SUSPEND_POINT
2326 : INITIAL_SUSPEND_POINT));
2327 }
2328
2329 /* Callback to record the essential data for each await point found in the
2330 function. */
2331
2332 static bool
2333 register_await_info (tree await_expr, tree aw_type, tree aw_nam, tree susp_type,
2334 tree susp_handle_nam)
2335 {
2336 bool seen;
2337 suspend_point_info &s
2338 = suspend_points->get_or_insert (await_expr, &seen);
2339 if (seen)
2340 {
2341 error_at (EXPR_LOCATION (await_expr), "duplicate info for %qE",
2342 await_expr);
2343 return false;
2344 }
2345 s.awaitable_type = aw_type;
2346 s.await_field_id = aw_nam;
2347 s.suspend_type = susp_type;
2348 s.susp_handle_id = susp_handle_nam;
2349 return true;
2350 }
2351
2352 /* Small helper for the repetitive task of adding a new field to the coro
2353 frame type. */
2354
2355 static tree
2356 coro_make_frame_entry (tree *field_list, const char *name, tree fld_type,
2357 location_t loc)
2358 {
2359 tree id = get_identifier (name);
2360 tree decl = build_decl (loc, FIELD_DECL, id, fld_type);
2361 DECL_CHAIN (decl) = *field_list;
2362 *field_list = decl;
2363 return id;
2364 }
2365
2366 struct susp_frame_data
2367 {
2368 tree *field_list;
2369 tree handle_type;
2370 hash_set<tree> captured_temps;
2371 vec<tree, va_gc> *to_replace;
2372 vec<tree, va_gc> *block_stack;
2373 unsigned count;
2374 unsigned saw_awaits;
2375 bool captures_temporary;
2376 };
2377
2378 /* Helper to return the type of an awaiter's await_suspend() method.
2379 We start with the result of the build method call, which will be either
2380 a call expression (void, bool) or a target expressions (handle). */
2381
2382 static tree
2383 get_await_suspend_return_type (tree aw_expr)
2384 {
2385 tree susp_fn = TREE_VEC_ELT (TREE_OPERAND (aw_expr, 3), 1);
2386 if (TREE_CODE (susp_fn) == CALL_EXPR)
2387 {
2388 susp_fn = CALL_EXPR_FN (susp_fn);
2389 if (TREE_CODE (susp_fn) == ADDR_EXPR)
2390 susp_fn = TREE_OPERAND (susp_fn, 0);
2391 return TREE_TYPE (TREE_TYPE (susp_fn));
2392 }
2393 else if (TREE_CODE (susp_fn) == TARGET_EXPR)
2394 return TREE_TYPE (susp_fn);
2395 return TREE_TYPE (susp_fn);
2396 }
2397
2398 /* Walk the sub-tree looking for call expressions that both capture
2399 references and have compiler-temporaries as parms. */
2400
2401 static tree
2402 captures_temporary (tree *stmt, int *do_subtree, void *d)
2403 {
2404 /* Stop recursing if we see an await expression, the subtrees
2405 of that will be handled when it it processed. */
2406 if (TREE_CODE (*stmt) == CO_AWAIT_EXPR || TREE_CODE (*stmt) == CO_YIELD_EXPR)
2407 {
2408 *do_subtree = 0;
2409 return NULL_TREE;
2410 }
2411
2412 /* We're only interested in calls. */
2413 if (TREE_CODE (*stmt) != CALL_EXPR)
2414 return NULL_TREE;
2415
2416 /* Does this call capture references?
2417 Strip the ADDRESS_EXPR to get the fn decl and inspect it. */
2418 tree fn = TREE_OPERAND (CALL_EXPR_FN (*stmt), 0);
2419 bool is_meth = TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE;
2420 tree arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
2421 unsigned offset = 3;
2422 for (unsigned anum = 0; arg != NULL; arg = TREE_CHAIN (arg), anum++)
2423 {
2424 tree parm_type = TREE_VALUE (arg);
2425 if (anum == 0 && is_meth && INDIRECT_TYPE_P (parm_type))
2426 {
2427 /* Account for 'this' when the fn is a method. Unless it
2428 belongs to a CTOR or DTOR. */
2429 if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
2430 continue;
2431 }
2432 else if (!TYPE_REF_P (parm_type))
2433 /* If it's not a reference, we don't care. */
2434 continue;
2435
2436 /* Fetch the value presented to the fn. */
2437 tree parm = TREE_OPERAND (*stmt, anum + offset);
2438
2439 while (TREE_CODE (parm) == NOP_EXPR)
2440 parm = TREE_OPERAND (parm, 0);
2441
2442 /* We only care if we're taking the addr of a temporary. */
2443 if (TREE_CODE (parm) != ADDR_EXPR)
2444 continue;
2445
2446 parm = TREE_OPERAND (parm, 0);
2447 if (TREE_CODE (parm) == VAR_DECL && !DECL_ARTIFICIAL (parm))
2448 /* This isn't a temporary... */
2449 continue;
2450
2451 if (TREE_CODE (parm) == PARM_DECL)
2452 /* .. nor is this... */
2453 continue;
2454
2455 if (TREE_CODE (parm) == TARGET_EXPR)
2456 {
2457 /* We're taking the address of a temporary and using it as a ref. */
2458 tree tvar = TREE_OPERAND (parm, 0);
2459 gcc_checking_assert (DECL_ARTIFICIAL (tvar));
2460
2461 susp_frame_data *data = (susp_frame_data *) d;
2462 data->captures_temporary = true;
2463 /* Record this one so we don't duplicate, and on the first
2464 occurrence note the target expr to be replaced. */
2465 if (!data->captured_temps.add (tvar))
2466 vec_safe_push (data->to_replace, parm);
2467 /* Now see if the initializer contains any more cases. */
2468 hash_set<tree> visited;
2469 tree res = cp_walk_tree (&TREE_OPERAND (parm, 1),
2470 captures_temporary, d, &visited);
2471 if (res)
2472 return res;
2473 /* Otherwise, we're done with sub-trees for this. */
2474 }
2475 else if (TREE_CODE (parm) == CO_AWAIT_EXPR)
2476 {
2477 /* CO_AWAIT expressions behave in a similar manner to target
2478 expressions when the await_resume call is contained in one. */
2479 tree awr = TREE_OPERAND (parm, 3); /* call vector. */
2480 awr = TREE_VEC_ELT (awr, 2); /* resume call. */
2481 if (TREE_CODE (awr) == TARGET_EXPR)
2482 {
2483 tree tvar = TREE_OPERAND (awr, 0);
2484 gcc_checking_assert (DECL_ARTIFICIAL (tvar));
2485
2486 susp_frame_data *data = (susp_frame_data *) d;
2487 data->captures_temporary = true;
2488 /* Use this as a place-holder. */
2489 if (!data->captured_temps.add (tvar))
2490 vec_safe_push (data->to_replace, parm);
2491 }
2492 /* We will walk the sub-trees of this co_await separately. */
2493 }
2494 else
2495 gcc_unreachable ();
2496 }
2497 /* As far as it's necessary, we've walked the subtrees of the call
2498 expr. */
2499 do_subtree = 0;
2500 return NULL_TREE;
2501 }
2502
2503 /* If this is an await, then register it and decide on what coro
2504 frame storage is needed.
2505 If this is a co_yield (which embeds an await), drop the yield
2506 and record the await (the yield was kept for diagnostics only). */
2507
2508 static tree
2509 register_awaits (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
2510 {
2511 susp_frame_data *data = (susp_frame_data *) d;
2512
2513 if (TREE_CODE (*stmt) != CO_AWAIT_EXPR && TREE_CODE (*stmt) != CO_YIELD_EXPR)
2514 return NULL_TREE;
2515
2516 /* co_yield is syntactic sugar, re-write it to co_await. */
2517 tree aw_expr = *stmt;
2518 location_t aw_loc = EXPR_LOCATION (aw_expr); /* location of the co_xxxx. */
2519 if (TREE_CODE (aw_expr) == CO_YIELD_EXPR)
2520 {
2521 aw_expr = TREE_OPERAND (aw_expr, 1);
2522 *stmt = aw_expr;
2523 }
2524
2525 /* Count how many awaits full expression contains. This is not the same
2526 as the counter used for the function-wide await point number. */
2527 data->saw_awaits++;
2528
2529 /* The required field has the same type as the proxy stored in the
2530 await expr. */
2531 tree aw_field_type = TREE_TYPE (TREE_OPERAND (aw_expr, 1));
2532
2533 size_t bufsize = sizeof ("__aw_s.") + 10;
2534 char *buf = (char *) alloca (bufsize);
2535 snprintf (buf, bufsize, "__aw_s.%d", data->count);
2536 tree aw_field_nam
2537 = coro_make_frame_entry (data->field_list, buf, aw_field_type, aw_loc);
2538
2539 /* Find out what we have to do with the awaiter's suspend method (this
2540 determines if we need somewhere to stash the suspend method's handle).
2541 Cache the result of this in the suspend point info.
2542 [expr.await]
2543 (5.1) If the result of await-ready is false, the coroutine is considered
2544 suspended. Then:
2545 (5.1.1) If the type of await-suspend is std::coroutine_handle<Z>,
2546 await-suspend.resume() is evaluated.
2547 (5.1.2) if the type of await-suspend is bool, await-suspend is evaluated,
2548 and the coroutine is resumed if the result is false.
2549 (5.1.3) Otherwise, await-suspend is evaluated.
2550 */
2551 tree susp_typ = get_await_suspend_return_type (aw_expr);
2552 tree handle_field_nam;
2553 if (VOID_TYPE_P (susp_typ) || TREE_CODE (susp_typ) == BOOLEAN_TYPE)
2554 handle_field_nam = NULL_TREE; /* no handle is needed. */
2555 else
2556 {
2557 snprintf (buf, bufsize, "__aw_h.%u", data->count);
2558 handle_field_nam
2559 = coro_make_frame_entry (data->field_list, buf, susp_typ, aw_loc);
2560 }
2561 register_await_info (aw_expr, aw_field_type, aw_field_nam, susp_typ,
2562 handle_field_nam);
2563
2564 data->count++; /* Each await suspend context is unique. */
2565
2566 /* We now need to know if to take special action on lifetime extension
2567 of temporaries captured by reference. This can only happen if such
2568 a case appears in the initializer for the awaitable. The callback
2569 records captured temporaries including subtrees of initializers. */
2570 hash_set<tree> visited;
2571 tree res = cp_walk_tree (&TREE_OPERAND (aw_expr, 2), captures_temporary, d,
2572 &visited);
2573 return res;
2574 }
2575
2576 /* The gimplifier correctly extends the lifetime of temporaries captured
2577 by reference (per. [class.temporary] (6.9) "A temporary object bound
2578 to a reference parameter in a function call persists until the completion
2579 of the full-expression containing the call"). However, that is not
2580 sufficient to work across a suspension - and we need to promote such
2581 temporaries to be regular vars that will then get a coro frame slot.
2582 We don't want to incur the effort of checking for this unless we have
2583 an await expression in the current full expression. */
2584
2585 static tree
2586 maybe_promote_captured_temps (tree *stmt, void *d)
2587 {
2588 susp_frame_data *awpts = (susp_frame_data *) d;
2589 hash_set<tree> visited;
2590 awpts->saw_awaits = 0;
2591
2592 /* When register_awaits sees an await, it walks the initializer for
2593 that await looking for temporaries captured by reference and notes
2594 them in awpts->captured_temps. We only need to take any action
2595 here if the statement contained any awaits, and any of those had
2596 temporaries captured by reference in the initializers for their class.
2597 */
2598
2599 tree res = cp_walk_tree (stmt, register_awaits, d, &visited);
2600 if (!res && awpts->saw_awaits > 0 && !awpts->captured_temps.is_empty ())
2601 {
2602 location_t sloc = EXPR_LOCATION (*stmt);
2603 tree aw_bind
2604 = build3_loc (sloc, BIND_EXPR, void_type_node, NULL, NULL, NULL);
2605 tree aw_statement_current;
2606 if (TREE_CODE (*stmt) == CLEANUP_POINT_EXPR)
2607 aw_statement_current = TREE_OPERAND (*stmt, 0);
2608 else
2609 aw_statement_current = *stmt;
2610 /* Collected the scope vars we need move the temps to regular. */
2611 tree aw_bind_body = push_stmt_list ();
2612 tree varlist = NULL_TREE;
2613 unsigned vnum = 0;
2614 while (!awpts->to_replace->is_empty ())
2615 {
2616 size_t bufsize = sizeof ("__aw_.tmp.") + 20;
2617 char *buf = (char *) alloca (bufsize);
2618 snprintf (buf, bufsize, "__aw_%d.tmp.%d", awpts->count, vnum);
2619 tree to_replace = awpts->to_replace->pop ();
2620 tree orig_temp;
2621 if (TREE_CODE (to_replace) == CO_AWAIT_EXPR)
2622 {
2623 orig_temp = TREE_OPERAND (to_replace, 3);
2624 orig_temp = TREE_VEC_ELT (orig_temp, 2);
2625 orig_temp = TREE_OPERAND (orig_temp, 0);
2626 }
2627 else
2628 orig_temp = TREE_OPERAND (to_replace, 0);
2629
2630 tree var_type = TREE_TYPE (orig_temp);
2631 gcc_assert (same_type_p (TREE_TYPE (to_replace), var_type));
2632 tree newvar
2633 = build_lang_decl (VAR_DECL, get_identifier (buf), var_type);
2634 DECL_CONTEXT (newvar) = DECL_CONTEXT (orig_temp);
2635 if (DECL_SOURCE_LOCATION (orig_temp))
2636 sloc = DECL_SOURCE_LOCATION (orig_temp);
2637 DECL_SOURCE_LOCATION (newvar) = sloc;
2638 DECL_CHAIN (newvar) = varlist;
2639 varlist = newvar;
2640 tree stmt
2641 = build2_loc (sloc, INIT_EXPR, var_type, newvar, to_replace);
2642 stmt = coro_build_cvt_void_expr_stmt (stmt, sloc);
2643 add_stmt (stmt);
2644 proxy_replace pr = {to_replace, newvar};
2645 /* Replace all instances of that temp in the original expr. */
2646 cp_walk_tree (&aw_statement_current, replace_proxy, &pr, NULL);
2647 }
2648 /* What's left should be the original statement with any temporaries
2649 broken out. */
2650 add_stmt (aw_statement_current);
2651 BIND_EXPR_BODY (aw_bind) = pop_stmt_list (aw_bind_body);
2652 awpts->captured_temps.empty ();
2653
2654 BIND_EXPR_VARS (aw_bind) = nreverse (varlist);
2655 tree b_block = make_node (BLOCK);
2656 if (!awpts->block_stack->is_empty ())
2657 {
2658 tree s_block = awpts->block_stack->last ();
2659 if (s_block)
2660 {
2661 BLOCK_SUPERCONTEXT (b_block) = s_block;
2662 BLOCK_CHAIN (b_block) = BLOCK_SUBBLOCKS (s_block);
2663 BLOCK_SUBBLOCKS (s_block) = b_block;
2664 }
2665 }
2666 BIND_EXPR_BLOCK (aw_bind) = b_block;
2667
2668 *stmt = aw_bind;
2669 }
2670 return res;
2671 }
2672
2673 static tree
2674 await_statement_walker (tree *stmt, int *do_subtree, void *d)
2675 {
2676 tree res = NULL_TREE;
2677 susp_frame_data *awpts = (susp_frame_data *) d;
2678
2679 /* We might need to insert a new bind expression, and want to link it
2680 into the correct scope, so keep a note of the current block scope. */
2681 if (TREE_CODE (*stmt) == BIND_EXPR)
2682 {
2683 tree *body = &BIND_EXPR_BODY (*stmt);
2684 tree blk = BIND_EXPR_BLOCK (*stmt);
2685 vec_safe_push (awpts->block_stack, blk);
2686
2687 if (TREE_CODE (*body) == STATEMENT_LIST)
2688 {
2689 tree_stmt_iterator i;
2690 for (i = tsi_start (*body); !tsi_end_p (i); tsi_next (&i))
2691 {
2692 tree *new_stmt = tsi_stmt_ptr (i);
2693 if (STATEMENT_CLASS_P (*new_stmt) || !EXPR_P (*new_stmt)
2694 || TREE_CODE (*new_stmt) == BIND_EXPR)
2695 res = cp_walk_tree (new_stmt, await_statement_walker, d, NULL);
2696 else
2697 res = maybe_promote_captured_temps (new_stmt, d);
2698 if (res)
2699 return res;
2700 }
2701 *do_subtree = 0; /* Done subtrees. */
2702 }
2703 else if (!STATEMENT_CLASS_P (*body) && EXPR_P (*body)
2704 && TREE_CODE (*body) != BIND_EXPR)
2705 {
2706 res = maybe_promote_captured_temps (body, d);
2707 *do_subtree = 0; /* Done subtrees. */
2708 }
2709 awpts->block_stack->pop ();
2710 }
2711 else if (!STATEMENT_CLASS_P (*stmt) && EXPR_P (*stmt)
2712 && TREE_CODE (*stmt) != BIND_EXPR)
2713 {
2714 res = maybe_promote_captured_temps (stmt, d);
2715 *do_subtree = 0; /* Done subtrees. */
2716 }
2717 /* If it wasn't a statement list, or a single statement, continue. */
2718 return res;
2719 }
2720
2721 /* For figuring out what param usage we have. */
2722
2723 struct param_frame_data
2724 {
2725 tree *field_list;
2726 hash_map<tree, param_info> *param_uses;
2727 location_t loc;
2728 bool param_seen;
2729 };
2730
2731 static tree
2732 register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
2733 {
2734 param_frame_data *data = (param_frame_data *) d;
2735
2736 if (TREE_CODE (*stmt) != PARM_DECL)
2737 return NULL_TREE;
2738
2739 bool existed;
2740 param_info &parm = data->param_uses->get_or_insert (*stmt, &existed);
2741 gcc_checking_assert (existed);
2742
2743 if (parm.field_id == NULL_TREE)
2744 {
2745 tree actual_type = TREE_TYPE (*stmt);
2746
2747 if (!COMPLETE_TYPE_P (actual_type))
2748 actual_type = complete_type_or_else (actual_type, *stmt);
2749
2750 if (actual_type == NULL_TREE)
2751 /* Diagnostic emitted by complete_type_or_else. */
2752 actual_type = error_mark_node;
2753
2754 if (TREE_CODE (actual_type) == REFERENCE_TYPE)
2755 actual_type = build_pointer_type (TREE_TYPE (actual_type));
2756
2757 parm.frame_type = actual_type;
2758 tree pname = DECL_NAME (*stmt);
2759 size_t namsize = sizeof ("__parm.") + IDENTIFIER_LENGTH (pname) + 1;
2760 char *buf = (char *) alloca (namsize);
2761 snprintf (buf, namsize, "__parm.%s", IDENTIFIER_POINTER (pname));
2762 parm.field_id
2763 = coro_make_frame_entry (data->field_list, buf, actual_type, data->loc);
2764 vec_alloc (parm.body_uses, 4);
2765 parm.body_uses->quick_push (stmt);
2766 data->param_seen = true;
2767 }
2768 else
2769 parm.body_uses->safe_push (stmt);
2770
2771 return NULL_TREE;
2772 }
2773
2774 /* For figuring out what local variable usage we have. */
2775
2776 struct local_vars_frame_data
2777 {
2778 tree *field_list;
2779 hash_map<tree, local_var_info> *local_var_uses;
2780 vec<local_var_info> *captures;
2781 unsigned int nest_depth, bind_indx;
2782 location_t loc;
2783 bool saw_capture;
2784 bool local_var_seen;
2785 };
2786
2787 static tree
2788 register_local_var_uses (tree *stmt, int *do_subtree, void *d)
2789 {
2790 local_vars_frame_data *lvd = (local_vars_frame_data *) d;
2791
2792 /* As we enter a bind expression - record the vars there and then recurse.
2793 As we exit drop the nest depth.
2794 The bind index is a growing count of how many bind indices we've seen.
2795 We build a space in the frame for each local var.
2796 */
2797 if (TREE_CODE (*stmt) == BIND_EXPR)
2798 {
2799 lvd->bind_indx++;
2800 lvd->nest_depth++;
2801 tree lvar;
2802 for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
2803 lvar = DECL_CHAIN (lvar))
2804 {
2805 bool existed;
2806 local_var_info &local_var
2807 = lvd->local_var_uses->get_or_insert (lvar, &existed);
2808 gcc_checking_assert (!existed);
2809 tree lvtype = TREE_TYPE (lvar);
2810 tree lvname = DECL_NAME (lvar);
2811 bool captured = is_normal_capture_proxy (lvar);
2812 /* Make names depth+index unique, so that we can support nested
2813 scopes with identically named locals. */
2814 char *buf;
2815 size_t namsize = sizeof ("__lv...") + 18;
2816 const char *nm = (captured ? "cp" : "lv");
2817 if (lvname != NULL_TREE)
2818 {
2819 namsize += IDENTIFIER_LENGTH (lvname);
2820 buf = (char *) alloca (namsize);
2821 snprintf (buf, namsize, "__%s.%u.%u.%s", nm, lvd->bind_indx,
2822 lvd->nest_depth, IDENTIFIER_POINTER (lvname));
2823 }
2824 else
2825 {
2826 namsize += 10; // 'D' followed by an unsigned.
2827 buf = (char *) alloca (namsize);
2828 snprintf (buf, namsize, "__%s.%u.%u.D%u", nm, lvd->bind_indx,
2829 lvd->nest_depth, DECL_UID (lvar));
2830 }
2831 /* TODO: Figure out if we should build a local type that has any
2832 excess alignment or size from the original decl. */
2833 local_var.field_id
2834 = coro_make_frame_entry (lvd->field_list, buf, lvtype, lvd->loc);
2835 local_var.def_loc = DECL_SOURCE_LOCATION (lvar);
2836 local_var.frame_type = lvtype;
2837 local_var.field_idx = NULL_TREE;
2838 if (captured)
2839 {
2840 gcc_checking_assert (DECL_INITIAL (lvar) == NULL_TREE);
2841 local_var.captured = lvar;
2842 lvd->captures->safe_push (local_var);
2843 lvd->saw_capture = true;
2844 }
2845 else
2846 local_var.captured = NULL;
2847 lvd->local_var_seen = true;
2848 /* We don't walk any of the local var sub-trees, they won't contain
2849 any bind exprs. */
2850 }
2851 cp_walk_tree (&BIND_EXPR_BODY (*stmt), register_local_var_uses, d, NULL);
2852 *do_subtree = 0; /* We've done this. */
2853 lvd->nest_depth--;
2854 }
2855 return NULL_TREE;
2856 }
2857
2858 /* Here we:
2859 a) Check that the function and promise type are valid for a
2860 coroutine.
2861 b) Carry out the initial morph to create the skeleton of the
2862 coroutine ramp function and the rewritten body.
2863
2864 Assumptions.
2865
2866 1. We only hit this code once all dependencies are resolved.
2867 2. The function body will be either a bind expr or a statement list
2868 3. That cfun and current_function_decl are valid for the case we're
2869 expanding.
2870 4. 'input_location' will be of the final brace for the function.
2871
2872 We do something like this:
2873 declare a dummy coro frame.
2874 struct _R_frame {
2875 using handle_type = coro::coroutine_handle<coro1::promise_type>;
2876 void (*__resume)(_R_frame *);
2877 void (*__destroy)(_R_frame *);
2878 coro1::promise_type __p;
2879 bool frame_needs_free; // free the coro frame mem if set.
2880 short __resume_at; // this is where clang puts it - but it's a smaller entity.
2881 coro1::suspend_never_prt __is;
2882 (maybe) handle_type i_hand;
2883 coro1::suspend_always_prt __fs;
2884 (maybe) handle_type f_hand;
2885 (maybe) parameters used in the body.
2886 (maybe) local variables saved
2887 (maybe) trailing space.
2888 }; */
2889
2890 bool
2891 morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer)
2892 {
2893 gcc_checking_assert (orig && TREE_CODE (orig) == FUNCTION_DECL);
2894
2895 if (!coro_function_valid_p (orig))
2896 return false;
2897
2898 /* The ramp function does return a value. */
2899 current_function_returns_value = 1;
2900
2901 /* We can't validly get here with an empty statement list, since there's no
2902 way for the FE to decide it's a coroutine in the absence of any code. */
2903 tree fnbody = pop_stmt_list (DECL_SAVED_TREE (orig));
2904 if (fnbody == NULL_TREE)
2905 return false;
2906
2907 /* We don't have the locus of the opening brace - it's filled in later (and
2908 there doesn't really seem to be any easy way to get at it).
2909 The closing brace is assumed to be input_location. */
2910 location_t fn_start = DECL_SOURCE_LOCATION (orig);
2911 gcc_rich_location fn_start_loc (fn_start);
2912
2913 /* Initial processing of the captured body.
2914 If we have no expressions or just an error then punt. */
2915 tree body_start = expr_first (fnbody);
2916 if (body_start == NULL_TREE || body_start == error_mark_node)
2917 {
2918 DECL_SAVED_TREE (orig) = push_stmt_list ();
2919 append_to_statement_list (DECL_SAVED_TREE (orig), &fnbody);
2920 return false;
2921 }
2922
2923 /* So, we've tied off the original body. Now start the replacement.
2924 If we encounter a fatal error we might return a now-empty body.
2925 TODO: determine if it would help to restore the original.
2926 determine if looking for more errors in coro_function_valid_p()
2927 and stashing types is a better solution.
2928 */
2929
2930 tree newbody = push_stmt_list ();
2931 DECL_SAVED_TREE (orig) = newbody;
2932
2933 /* If our original body is noexcept, then that's what we apply to our
2934 generated functions. Remember that we're NOEXCEPT and fish out the
2935 contained list (we tied off to the top level already). */
2936 bool is_noexcept = TREE_CODE (body_start) == MUST_NOT_THROW_EXPR;
2937 if (is_noexcept)
2938 {
2939 /* Simplified abstract from begin_eh_spec_block, since we already
2940 know the outcome. */
2941 fnbody = TREE_OPERAND (body_start, 0); /* Stash the original... */
2942 add_stmt (body_start); /* ... and start the new. */
2943 TREE_OPERAND (body_start, 0) = push_stmt_list ();
2944 }
2945
2946 /* Create the coro frame type, as far as it can be known at this stage.
2947 1. Types we already know. */
2948
2949 tree fn_return_type = TREE_TYPE (TREE_TYPE (orig));
2950 gcc_assert (!VOID_TYPE_P (fn_return_type));
2951 tree handle_type = get_coroutine_handle_type (orig);
2952 tree promise_type = get_coroutine_promise_type (orig);
2953
2954 /* 2. Types we need to define or look up. */
2955
2956 /* We need to know, and inspect, each suspend point in the function
2957 in several places. It's convenient to place this map out of line
2958 since it's used from tree walk callbacks. */
2959 suspend_points = new hash_map<tree, suspend_point_info>;
2960
2961 /* Initial and final suspend types are special in that the co_awaits for
2962 them are synthetic. We need to find the type for each awaiter from
2963 the coroutine promise. */
2964 tree initial_await = build_init_or_final_await (fn_start, false);
2965 if (initial_await == error_mark_node)
2966 return false;
2967 /* The type of the frame var for this is the type of its temp proxy. */
2968 tree initial_suspend_type = TREE_TYPE (TREE_OPERAND (initial_await, 1));
2969
2970 tree final_await = build_init_or_final_await (fn_start, true);
2971 if (final_await == error_mark_node)
2972 return false;
2973
2974 /* The type of the frame var for this is the type of its temp proxy. */
2975 tree final_suspend_type = TREE_TYPE (TREE_OPERAND (final_await, 1));
2976
2977 tree fr_name = get_fn_local_identifier (orig, "frame");
2978 tree coro_frame_type = xref_tag (record_type, fr_name, ts_current, false);
2979 DECL_CONTEXT (TYPE_NAME (coro_frame_type)) = current_scope ();
2980 tree coro_frame_ptr = build_pointer_type (coro_frame_type);
2981 tree act_des_fn_type
2982 = build_function_type_list (void_type_node, coro_frame_ptr, NULL_TREE);
2983 tree act_des_fn_ptr = build_pointer_type (act_des_fn_type);
2984
2985 /* Declare the actor function. */
2986 tree actor_name = get_fn_local_identifier (orig, "actor");
2987 tree actor = build_lang_decl (FUNCTION_DECL, actor_name, act_des_fn_type);
2988 DECL_CONTEXT (actor) = DECL_CONTEXT (orig);
2989 DECL_INITIAL (actor) = error_mark_node;
2990
2991 /* Declare the destroyer function. */
2992 tree destr_name = get_fn_local_identifier (orig, "destroy");
2993 tree destroy = build_lang_decl (FUNCTION_DECL, destr_name, act_des_fn_type);
2994 DECL_CONTEXT (destroy) = DECL_CONTEXT (orig);
2995 DECL_INITIAL (destroy) = error_mark_node;
2996
2997 /* Build our dummy coro frame layout. */
2998 coro_frame_type = begin_class_definition (coro_frame_type);
2999
3000 tree field_list = NULL_TREE;
3001 tree resume_name
3002 = coro_make_frame_entry (&field_list, "__resume", act_des_fn_ptr, fn_start);
3003 tree destroy_name = coro_make_frame_entry (&field_list, "__destroy",
3004 act_des_fn_ptr, fn_start);
3005 tree promise_name
3006 = coro_make_frame_entry (&field_list, "__p", promise_type, fn_start);
3007 tree fnf_name = coro_make_frame_entry (&field_list, "__frame_needs_free",
3008 boolean_type_node, fn_start);
3009 tree resume_idx_name
3010 = coro_make_frame_entry (&field_list, "__resume_at",
3011 short_unsigned_type_node, fn_start);
3012
3013 /* We need a handle to this coroutine, which is passed to every
3014 await_suspend(). There's no point in creating it over and over. */
3015 (void) coro_make_frame_entry (&field_list, "__self_h", handle_type, fn_start);
3016
3017 /* Initial suspend is mandated. */
3018 tree init_susp_name = coro_make_frame_entry (&field_list, "__aw_s.is",
3019 initial_suspend_type, fn_start);
3020
3021 /* Figure out if we need a saved handle from the awaiter type. */
3022 tree ret_typ = get_await_suspend_return_type (initial_await);
3023 tree init_hand_name;
3024 if (VOID_TYPE_P (ret_typ) || TREE_CODE (ret_typ) == BOOLEAN_TYPE)
3025 init_hand_name = NULL_TREE; /* no handle is needed. */
3026 else
3027 {
3028 init_hand_name
3029 = coro_make_frame_entry (&field_list, "__ih", ret_typ, fn_start);
3030 }
3031
3032 register_await_info (initial_await, initial_suspend_type, init_susp_name,
3033 ret_typ, init_hand_name);
3034
3035 /* Now insert the data for any body await points, at this time we also need
3036 to promote any temporaries that are captured by reference (to regular
3037 vars) they will get added to the coro frame along with other locals. */
3038 susp_frame_data body_aw_points
3039 = {&field_list, handle_type, hash_set<tree> (), NULL, NULL, 0, 0, false};
3040 body_aw_points.to_replace = make_tree_vector ();
3041 body_aw_points.block_stack = make_tree_vector ();
3042 cp_walk_tree (&fnbody, await_statement_walker, &body_aw_points, NULL);
3043
3044 /* Final suspend is mandated. */
3045 tree fin_susp_name = coro_make_frame_entry (&field_list, "__aw_s.fs",
3046 final_suspend_type, fn_start);
3047
3048 ret_typ = get_await_suspend_return_type (final_await);
3049 tree fin_hand_name;
3050 if (VOID_TYPE_P (ret_typ) || TREE_CODE (ret_typ) == BOOLEAN_TYPE)
3051 fin_hand_name = NULL_TREE; /* no handle is needed. */
3052 else
3053 {
3054 fin_hand_name
3055 = coro_make_frame_entry (&field_list, "__fh", ret_typ, fn_start);
3056 }
3057
3058 register_await_info (final_await, final_suspend_type, fin_susp_name,
3059 void_type_node, fin_hand_name);
3060
3061 /* 3. Now add in fields for function params (if there are any) that are used
3062 within the function body. This is conservative; we can't tell at this
3063 stage if such uses might be optimized away, or if they might turn out not
3064 to persist across any suspend points. Of course, even if they don't
3065 persist across suspend points, when the actor is out of line the saved
3066 frame version is still needed. */
3067 hash_map<tree, param_info> *param_uses = NULL;
3068 if (DECL_ARGUMENTS (orig))
3069 {
3070 /* Build a hash map with an entry for each param.
3071 The key is the param tree.
3072 Then we have an entry for the frame field name.
3073 Then a cache for the field ref when we come to use it.
3074 Then a tree list of the uses.
3075 The second two entries start out empty - and only get populated
3076 when we see uses. */
3077 param_uses = new hash_map<tree, param_info>;
3078
3079 for (tree arg = DECL_ARGUMENTS (orig); arg != NULL;
3080 arg = DECL_CHAIN (arg))
3081 {
3082 bool existed;
3083 param_info &parm = param_uses->get_or_insert (arg, &existed);
3084 gcc_checking_assert (!existed);
3085 parm.field_id = NULL_TREE;
3086 parm.body_uses = NULL;
3087 }
3088
3089 param_frame_data param_data
3090 = {&field_list, param_uses, fn_start, false};
3091 /* We want to record every instance of param's use, so don't include
3092 a 'visited' hash_set. */
3093 cp_walk_tree (&fnbody, register_param_uses, &param_data, NULL);
3094
3095 /* If no uses for any param were seen, act as if there were no
3096 params (it could be that they are only used to construct the
3097 promise). */
3098 if (!param_data.param_seen)
3099 {
3100 delete param_uses;
3101 param_uses = NULL;
3102 }
3103 }
3104
3105 /* 4. Now make space for local vars, this is conservative again, and we
3106 would expect to delete unused entries later. */
3107 hash_map<tree, local_var_info> local_var_uses;
3108 auto_vec<local_var_info> captures;
3109
3110 local_vars_frame_data local_vars_data
3111 = {&field_list, &local_var_uses, &captures, 0, 0, fn_start, false, false};
3112 cp_walk_tree (&fnbody, register_local_var_uses, &local_vars_data, NULL);
3113
3114 /* Tie off the struct for now, so that we can build offsets to the
3115 known entries. */
3116 TYPE_FIELDS (coro_frame_type) = field_list;
3117 TYPE_BINFO (coro_frame_type) = make_tree_binfo (0);
3118 BINFO_OFFSET (TYPE_BINFO (coro_frame_type)) = size_zero_node;
3119 BINFO_TYPE (TYPE_BINFO (coro_frame_type)) = coro_frame_type;
3120
3121 coro_frame_type = finish_struct (coro_frame_type, NULL_TREE);
3122
3123 /* Ramp: */
3124 /* Now build the ramp function pieces. */
3125 tree ramp_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3126 add_stmt (ramp_bind);
3127 tree ramp_body = push_stmt_list ();
3128 tree empty_list = build_empty_stmt (fn_start);
3129
3130 tree coro_fp = build_lang_decl (VAR_DECL, get_identifier ("coro.frameptr"),
3131 coro_frame_ptr);
3132 tree varlist = coro_fp;
3133 local_var_info *cap;
3134 if (!captures.is_empty())
3135 for (int ix = 0; captures.iterate (ix, &cap); ix++)
3136 {
3137 if (cap->field_id == NULL_TREE)
3138 continue;
3139 tree t = cap->captured;
3140 DECL_CHAIN (t) = varlist;
3141 varlist = t;
3142 }
3143
3144 /* Collected the scope vars we need ... only one for now. */
3145 BIND_EXPR_VARS (ramp_bind) = nreverse (varlist);
3146
3147 /* We're now going to create a new top level scope block for the ramp
3148 function. */
3149 tree top_block = make_node (BLOCK);
3150
3151 BIND_EXPR_BLOCK (ramp_bind) = top_block;
3152 BLOCK_VARS (top_block) = BIND_EXPR_VARS (ramp_bind);
3153 BLOCK_SUBBLOCKS (top_block) = NULL_TREE;
3154
3155 /* The decl_expr for the coro frame pointer, initialize to zero so that we
3156 can pass it to the IFN_CO_FRAME (since there's no way to pass a type,
3157 directly apparently). This avoids a "used uninitialized" warning. */
3158 tree r = build_stmt (fn_start, DECL_EXPR, coro_fp);
3159 tree zeroinit = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
3160 r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, zeroinit);
3161 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3162 add_stmt (r);
3163
3164 /* We are going to copy the behavior of clang w.r.t to failed allocation
3165 of the coroutine frame.
3166 1. If the promise has a 'get_return_object_on_allocation_failure()'
3167 method, then we use a nothrow new and check the return value, calling
3168 the method on failure to initialize an early return.
3169 2. Otherwise, we call new and the ramp is expected to terminate with an
3170 unhandled exception in the case of failure to allocate.
3171
3172 The get_return_object_on_allocation_failure() must be a static method.
3173 */
3174 tree grooaf_meth
3175 = lookup_promise_method (orig, coro_gro_on_allocation_fail_identifier,
3176 fn_start, /*musthave=*/ false);
3177
3178 /* The CO_FRAME internal function is a mechanism to allow the middle end
3179 to adjust the allocation in response to optimisations. We provide the
3180 current conservative estimate of the frame size (as per the current)
3181 computed layout. */
3182 tree resizeable
3183 = build_call_expr_internal_loc (fn_start, IFN_CO_FRAME, size_type_node, 2,
3184 TYPE_SIZE_UNIT (coro_frame_type), coro_fp);
3185
3186 /* We need to adjust the operator new call as per the description above when
3187 there is a return on allocation fail function provided in the promise. */
3188 tree grooaf = NULL_TREE;
3189 vec<tree, va_gc> *arglist;
3190 vec_alloc (arglist, 2);
3191 arglist->quick_push (resizeable);
3192 if (grooaf_meth && BASELINK_P (grooaf_meth))
3193 {
3194 tree fn = BASELINK_FUNCTIONS (grooaf_meth);
3195 if (TREE_CODE (fn) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (fn))
3196 {
3197 grooaf = build_call_expr_loc (fn_start, fn, 0);
3198 TREE_USED (fn) = 1;
3199 }
3200 tree nth_ns = lookup_qualified_name (std_node, get_identifier ("nothrow"),
3201 0, /*complain=*/ true, false);
3202 arglist->quick_push (nth_ns);
3203 }
3204
3205 /* Allocate the frame. */
3206
3207 tree nwname = ovl_op_identifier (false, NEW_EXPR);
3208 /* The user can (optionally) provide an allocation function in the promise
3209 type, it's not a failure for it to be absent. */
3210 tree fns = lookup_promise_method (orig, nwname, fn_start,
3211 /*musthave=*/ false);
3212 tree new_fn = NULL_TREE;
3213 if (fns && fns != error_mark_node)
3214 {
3215 new_fn = lookup_arg_dependent (nwname, fns, arglist);
3216 if (OVL_P (new_fn))
3217 new_fn = OVL_FIRST (new_fn);
3218 else
3219 new_fn = BASELINK_FUNCTIONS (new_fn);
3220
3221 gcc_checking_assert (DECL_STATIC_FUNCTION_P (new_fn));
3222 TREE_USED (new_fn) = 1;
3223 new_fn = build_call_expr_loc_vec (fn_start, new_fn, arglist);
3224 }
3225
3226 /* If that fails, then fall back to the global operator new. */
3227 if (new_fn == NULL_TREE || new_fn == error_mark_node)
3228 {
3229 fns =lookup_name_real (nwname, 0, 1, /*block_p=*/true, 0, 0);
3230 new_fn = lookup_arg_dependent (nwname, fns, arglist);
3231 new_fn = build_new_function_call (new_fn, &arglist, /*complain=*/ true);
3232 }
3233
3234 tree allocated = build1 (CONVERT_EXPR, coro_frame_ptr, new_fn);
3235 r = build2 (INIT_EXPR, TREE_TYPE (coro_fp), coro_fp, allocated);
3236 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3237 add_stmt (r);
3238
3239 /* If the user provided a method to return an object on alloc fail, then
3240 check the returned pointer and call the func if it's null.
3241 Otherwise, no check, and we fail for noexcept/fno-exceptions cases. */
3242
3243 if (grooaf)
3244 {
3245 tree cfra_label
3246 = create_named_label_with_ctx (fn_start, "coro.frame.active",
3247 current_scope ());
3248 tree early_ret_list = NULL;
3249 /* init the retval using the user's func. */
3250 r = build2 (INIT_EXPR, TREE_TYPE (DECL_RESULT (orig)), DECL_RESULT (orig),
3251 grooaf);
3252 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3253 append_to_statement_list (r, &early_ret_list);
3254 // We know it's the correct type.
3255 r = DECL_RESULT (orig);
3256 r = build_stmt (fn_start, RETURN_EXPR, r);
3257 TREE_NO_WARNING (r) |= 1;
3258 r = maybe_cleanup_point_expr_void (r);
3259 append_to_statement_list (r, &early_ret_list);
3260
3261 tree goto_st = NULL;
3262 r = build1 (GOTO_EXPR, void_type_node, cfra_label);
3263 append_to_statement_list (r, &goto_st);
3264
3265 tree ckk = build1 (CONVERT_EXPR, coro_frame_ptr, integer_zero_node);
3266 tree ckz = build2 (EQ_EXPR, boolean_type_node, coro_fp, ckk);
3267 r = build3 (COND_EXPR, void_type_node, ckz, early_ret_list, empty_list);
3268 add_stmt (r);
3269
3270 cfra_label = build_stmt (fn_start, LABEL_EXPR, cfra_label);
3271 add_stmt (cfra_label);
3272 }
3273
3274 /* deref the frame pointer, to use in member access code. */
3275 tree deref_fp = build_x_arrow (fn_start, coro_fp, tf_warning_or_error);
3276
3277 /* For now, we always assume that this needs destruction, there's no impl.
3278 for frame allocation elision. */
3279 tree fnf_m
3280 = lookup_member (coro_frame_type, fnf_name, 1, 0, tf_warning_or_error);
3281 tree fnf_x = build_class_member_access_expr (deref_fp, fnf_m, NULL_TREE,
3282 false, tf_warning_or_error);
3283 r = build2 (INIT_EXPR, boolean_type_node, fnf_x, boolean_true_node);
3284 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3285 add_stmt (r);
3286
3287 /* Put the resumer and destroyer functions in. */
3288
3289 tree actor_addr = build1 (ADDR_EXPR, act_des_fn_ptr, actor);
3290 tree resume_m
3291 = lookup_member (coro_frame_type, resume_name,
3292 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
3293 tree resume_x = build_class_member_access_expr (deref_fp, resume_m, NULL_TREE,
3294 false, tf_warning_or_error);
3295 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, resume_x, actor_addr);
3296 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3297 add_stmt (r);
3298
3299 tree destroy_addr = build1 (ADDR_EXPR, act_des_fn_ptr, destroy);
3300 tree destroy_m
3301 = lookup_member (coro_frame_type, destroy_name,
3302 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
3303 tree destroy_x
3304 = build_class_member_access_expr (deref_fp, destroy_m, NULL_TREE, false,
3305 tf_warning_or_error);
3306 r = build2_loc (fn_start, INIT_EXPR, act_des_fn_ptr, destroy_x, destroy_addr);
3307 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3308 add_stmt (r);
3309
3310 /* Set up the promise. */
3311 tree promise_m
3312 = lookup_member (coro_frame_type, promise_name,
3313 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
3314
3315 tree p = build_class_member_access_expr (deref_fp, promise_m, NULL_TREE,
3316 false, tf_warning_or_error);
3317
3318 if (TYPE_NEEDS_CONSTRUCTING (promise_type))
3319 {
3320 /* Do a placement new constructor for the promise type (we never call
3321 the new operator, just the constructor on the object in place in the
3322 frame).
3323
3324 First try to find a constructor with the same parameter list as the
3325 original function (if it has params), failing that find a constructor
3326 with no parameter list.
3327 */
3328
3329 if (DECL_ARGUMENTS (orig))
3330 {
3331 vec<tree, va_gc> *args = make_tree_vector ();
3332 tree arg;
3333 for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
3334 vec_safe_push (args, arg);
3335 r = build_special_member_call (p, complete_ctor_identifier, &args,
3336 promise_type, LOOKUP_NORMAL, tf_none);
3337 release_tree_vector (args);
3338 }
3339 else
3340 r = NULL_TREE;
3341
3342 if (r == NULL_TREE || r == error_mark_node)
3343 r = build_special_member_call (p, complete_ctor_identifier, NULL,
3344 promise_type, LOOKUP_NORMAL,
3345 tf_warning_or_error);
3346
3347 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3348 add_stmt (r);
3349 }
3350
3351 /* Copy in any of the function params we found to be used.
3352 Param types with non-trivial dtors will have to be moved into position
3353 and the dtor run before the frame is freed. */
3354 vec<tree, va_gc> *param_dtor_list = NULL;
3355 if (DECL_ARGUMENTS (orig) && param_uses != NULL)
3356 {
3357 tree arg;
3358 for (arg = DECL_ARGUMENTS (orig); arg != NULL; arg = DECL_CHAIN (arg))
3359 {
3360 bool existed;
3361 param_info &parm = param_uses->get_or_insert (arg, &existed);
3362 if (parm.field_id == NULL_TREE)
3363 continue; /* Wasn't used. */
3364
3365 tree fld_ref = lookup_member (coro_frame_type, parm.field_id,
3366 /*protect*/ 1, /*want_type*/ 0,
3367 tf_warning_or_error);
3368 tree fld_idx
3369 = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
3370 false, tf_warning_or_error);
3371
3372 if (TYPE_NEEDS_CONSTRUCTING (parm.frame_type))
3373 {
3374 vec<tree, va_gc> *p_in;
3375 if (TYPE_REF_P (DECL_ARG_TYPE (arg))
3376 && (CLASSTYPE_LAZY_MOVE_CTOR (parm.frame_type)
3377 || CLASSTYPE_LAZY_MOVE_ASSIGN (parm.frame_type)
3378 || classtype_has_move_assign_or_move_ctor_p
3379 (parm.frame_type, /* user-declared */ true)))
3380 p_in = make_tree_vector_single (rvalue (arg));
3381 else
3382 p_in = make_tree_vector_single (arg);
3383 /* Construct in place or move as relevant. */
3384 r = build_special_member_call (fld_idx, complete_ctor_identifier,
3385 &p_in, parm.frame_type,
3386 LOOKUP_NORMAL,
3387 tf_warning_or_error);
3388 release_tree_vector (p_in);
3389 if (param_dtor_list == NULL)
3390 param_dtor_list = make_tree_vector ();
3391 vec_safe_push (param_dtor_list, parm.field_id);
3392 }
3393 else
3394 {
3395 if (!same_type_p (parm.frame_type, DECL_ARG_TYPE (arg)))
3396 r = build1_loc (DECL_SOURCE_LOCATION (arg), CONVERT_EXPR,
3397 parm.frame_type, arg);
3398 else
3399 r = arg;
3400 r = build_modify_expr (fn_start, fld_idx, parm.frame_type,
3401 INIT_EXPR, DECL_SOURCE_LOCATION (arg), r,
3402 TREE_TYPE (r));
3403 }
3404 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3405 add_stmt (r);
3406 }
3407 }
3408
3409 vec<tree, va_gc> *captures_dtor_list = NULL;
3410 while (!captures.is_empty())
3411 {
3412 local_var_info cap = captures.pop();
3413 if (cap.field_id == NULL_TREE)
3414 continue;
3415
3416 tree fld_ref = lookup_member (coro_frame_type, cap.field_id,
3417 /*protect*/ 1, /*want_type*/ 0,
3418 tf_warning_or_error);
3419 tree fld_idx
3420 = build_class_member_access_expr (deref_fp, fld_ref, NULL_TREE,
3421 false, tf_warning_or_error);
3422
3423 tree cap_type = cap.frame_type;
3424
3425 /* When we have a reference, we do not want to change the referenced
3426 item, but actually to set the reference to the proxy var. */
3427 if (REFERENCE_REF_P (fld_idx))
3428 fld_idx = TREE_OPERAND (fld_idx, 0);
3429
3430 if (TYPE_NEEDS_CONSTRUCTING (cap_type))
3431 {
3432 vec<tree, va_gc> *p_in;
3433 if (TYPE_REF_P (cap_type)
3434 && (CLASSTYPE_LAZY_MOVE_CTOR (cap_type)
3435 || CLASSTYPE_LAZY_MOVE_ASSIGN (cap_type)
3436 || classtype_has_move_assign_or_move_ctor_p
3437 (cap_type, /* user-declared */ true)))
3438 p_in = make_tree_vector_single (rvalue (cap.captured));
3439 else
3440 p_in = make_tree_vector_single (cap.captured);
3441 /* Construct in place or move as relevant. */
3442 r = build_special_member_call (fld_idx, complete_ctor_identifier,
3443 &p_in, cap_type, LOOKUP_NORMAL,
3444 tf_warning_or_error);
3445 release_tree_vector (p_in);
3446 if (captures_dtor_list == NULL)
3447 captures_dtor_list = make_tree_vector ();
3448 vec_safe_push (captures_dtor_list, cap.field_id);
3449 }
3450 else
3451 {
3452 if (!same_type_p (cap_type, TREE_TYPE (cap.captured)))
3453 r = build1_loc (DECL_SOURCE_LOCATION (cap.captured), CONVERT_EXPR,
3454 cap_type, cap.captured);
3455 else
3456 r = cap.captured;
3457 r = build_modify_expr (fn_start, fld_idx, cap_type,
3458 INIT_EXPR, DECL_SOURCE_LOCATION (cap.captured),
3459 r, TREE_TYPE (r));
3460 }
3461 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3462 add_stmt (r);
3463 }
3464
3465 /* Set up a new bind context for the GRO. */
3466 tree gro_context_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3467 /* Make and connect the scope blocks. */
3468 tree gro_block = make_node (BLOCK);
3469 BLOCK_SUPERCONTEXT (gro_block) = top_block;
3470 BLOCK_SUBBLOCKS (top_block) = gro_block;
3471 BIND_EXPR_BLOCK (gro_context_bind) = gro_block;
3472 add_stmt (gro_context_bind);
3473
3474 tree gro_meth = lookup_promise_method (orig,
3475 coro_get_return_object_identifier,
3476 fn_start, /*musthave=*/ true );
3477 tree get_ro
3478 = build_new_method_call (p, gro_meth, NULL, NULL_TREE, LOOKUP_NORMAL, NULL,
3479 tf_warning_or_error);
3480 /* Without a return object we haven't got much clue what's going on. */
3481 if (get_ro == error_mark_node)
3482 {
3483 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
3484 DECL_SAVED_TREE (orig) = newbody;
3485 return false;
3486 }
3487
3488 tree gro_context_body = push_stmt_list ();
3489 tree gro, gro_bind_vars;
3490 if (same_type_p (TREE_TYPE (get_ro), fn_return_type))
3491 {
3492 gro = DECL_RESULT (orig);
3493 gro_bind_vars = NULL_TREE; // We don't need a separate var.
3494 }
3495 else
3496 {
3497 gro = build_lang_decl (VAR_DECL, get_identifier ("coro.gro"),
3498 TREE_TYPE (TREE_OPERAND (get_ro, 0)));
3499 DECL_CONTEXT (gro) = current_scope ();
3500 r = build_stmt (fn_start, DECL_EXPR, gro);
3501 add_stmt (r);
3502 gro_bind_vars = gro; // We need a temporary var.
3503 }
3504
3505 // init our actual var.
3506 r = build2_loc (fn_start, INIT_EXPR, TREE_TYPE (gro), gro, get_ro);
3507 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3508 add_stmt (r);
3509
3510 /* Initialize the resume_idx_name to 0, meaning "not started". */
3511 tree resume_idx_m
3512 = lookup_member (coro_frame_type, resume_idx_name,
3513 /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error);
3514 tree resume_idx
3515 = build_class_member_access_expr (deref_fp, resume_idx_m, NULL_TREE, false,
3516 tf_warning_or_error);
3517 r = build_int_cst (short_unsigned_type_node, 0);
3518 r = build2_loc (fn_start, INIT_EXPR, short_unsigned_type_node, resume_idx, r);
3519 r = coro_build_cvt_void_expr_stmt (r, fn_start);
3520 add_stmt (r);
3521
3522 /* So .. call the actor .. */
3523 r = build_call_expr_loc (fn_start, actor, 1, coro_fp);
3524 r = maybe_cleanup_point_expr_void (r);
3525 add_stmt (r);
3526
3527 /* Switch to using 'input_location' as the loc, since we're now more
3528 logically doing things related to the end of the function. */
3529 /* done, we just need the return value. */
3530 bool no_warning;
3531 if (same_type_p (TREE_TYPE (gro), fn_return_type))
3532 {
3533 /* Already got the result. */
3534 r = check_return_expr (DECL_RESULT (orig), &no_warning);
3535 }
3536 else
3537 {
3538 // construct the return value with a single GRO param.
3539 vec<tree, va_gc> *args = make_tree_vector_single (gro);
3540 r = build_special_member_call (DECL_RESULT (orig),
3541 complete_ctor_identifier, &args,
3542 fn_return_type, LOOKUP_NORMAL,
3543 tf_warning_or_error);
3544 r = coro_build_cvt_void_expr_stmt (r, input_location);
3545 add_stmt (r);
3546 release_tree_vector (args);
3547 }
3548
3549 r = build_stmt (input_location, RETURN_EXPR, DECL_RESULT (orig));
3550 TREE_NO_WARNING (r) |= no_warning;
3551 r = maybe_cleanup_point_expr_void (r);
3552 add_stmt (r);
3553 BIND_EXPR_VARS (gro_context_bind) = gro_bind_vars;
3554 BIND_EXPR_BODY (gro_context_bind) = pop_stmt_list (gro_context_body);
3555 BIND_EXPR_BODY (ramp_bind) = pop_stmt_list (ramp_body);
3556
3557 /* We know the "real" promise and have a frame layout with a slot for each
3558 suspend point, so we can build an actor function (which contains the
3559 functionality for both 'resume' and 'destroy').
3560
3561 wrap the function body in a try {} catch (...) {} block, if exceptions
3562 are enabled. */
3563
3564 /* First make a new block for the body - that will be embedded in the
3565 re-written function. */
3566 tree first = expr_first (fnbody);
3567 bool orig_fn_has_outer_bind = false;
3568 tree replace_blk = NULL_TREE;
3569 if (first && TREE_CODE (first) == BIND_EXPR)
3570 {
3571 orig_fn_has_outer_bind = true;
3572 tree block = BIND_EXPR_BLOCK (first);
3573 replace_blk = make_node (BLOCK);
3574 if (block) // missing block is probably an error.
3575 {
3576 gcc_assert (BLOCK_SUPERCONTEXT (block) == NULL_TREE);
3577 gcc_assert (BLOCK_CHAIN (block) == NULL_TREE);
3578 BLOCK_VARS (replace_blk) = BLOCK_VARS (block);
3579 BLOCK_SUBBLOCKS (replace_blk) = BLOCK_SUBBLOCKS (block);
3580 for (tree b = BLOCK_SUBBLOCKS (replace_blk); b; b = BLOCK_CHAIN (b))
3581 BLOCK_SUPERCONTEXT (b) = replace_blk;
3582 }
3583 BIND_EXPR_BLOCK (first) = replace_blk;
3584 }
3585
3586 if (flag_exceptions)
3587 {
3588 tree ueh_meth
3589 = lookup_promise_method (orig, coro_unhandled_exception_identifier,
3590 fn_start, /*musthave=*/ true);
3591 /* Build promise.unhandled_exception(); */
3592 tree ueh
3593 = build_new_method_call (p, ueh_meth, NULL, NULL_TREE, LOOKUP_NORMAL,
3594 NULL, tf_warning_or_error);
3595
3596 /* The try block is just the original function, there's no real
3597 need to call any function to do this. */
3598 tree tcb = build_stmt (fn_start, TRY_BLOCK, NULL_TREE, NULL_TREE);
3599 TRY_STMTS (tcb) = fnbody;
3600 TRY_HANDLERS (tcb) = push_stmt_list ();
3601 /* Mimic what the parser does for the catch. */
3602 tree handler = begin_handler ();
3603 finish_handler_parms (NULL_TREE, handler); /* catch (...) */
3604 ueh = maybe_cleanup_point_expr_void (ueh);
3605 add_stmt (ueh);
3606 finish_handler (handler);
3607 TRY_HANDLERS (tcb) = pop_stmt_list (TRY_HANDLERS (tcb));
3608 /* If the function starts with a BIND_EXPR, then we need to create
3609 one here to contain the try-catch and to link up the scopes. */
3610 if (orig_fn_has_outer_bind)
3611 {
3612 tree tcb_bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
3613 /* Make and connect the scope blocks. */
3614 tree tcb_block = make_node (BLOCK);
3615 /* .. and connect it here. */
3616 BLOCK_SUPERCONTEXT (replace_blk) = tcb_block;
3617 BLOCK_SUBBLOCKS (tcb_block) = replace_blk;
3618 BIND_EXPR_BLOCK (tcb_bind) = tcb_block;
3619 BIND_EXPR_BODY (tcb_bind) = tcb;
3620 fnbody = tcb_bind;
3621 }
3622 else
3623 fnbody = tcb;
3624 }
3625 else if (pedantic)
3626 {
3627 /* We still try to look for the promise method and warn if it's not
3628 present. */
3629 tree ueh_meth
3630 = lookup_promise_method (orig, coro_unhandled_exception_identifier,
3631 fn_start, /*musthave=*/ false);
3632 if (!ueh_meth || ueh_meth == error_mark_node)
3633 warning_at (fn_start, 0, "no member named %qE in %qT",
3634 coro_unhandled_exception_identifier,
3635 get_coroutine_promise_type (orig));
3636 }
3637 /* Else we don't check and don't care if the method is missing. */
3638
3639 /* Start to build the final functions.
3640
3641 We push_deferring_access_checks to avoid these routines being seen as
3642 nested by the middle end; we are doing the outlining here. */
3643
3644 push_deferring_access_checks (dk_no_check);
3645
3646 /* Actor ... */
3647 build_actor_fn (fn_start, coro_frame_type, actor, fnbody, orig, param_uses,
3648 &local_var_uses, param_dtor_list, initial_await, final_await,
3649 body_aw_points.count);
3650
3651 /* Destroyer ... */
3652 build_destroy_fn (fn_start, coro_frame_type, destroy, actor);
3653
3654 pop_deferring_access_checks ();
3655
3656 DECL_SAVED_TREE (orig) = newbody;
3657 /* Link our new functions into the list. */
3658 TREE_CHAIN (destroy) = TREE_CHAIN (orig);
3659 TREE_CHAIN (actor) = destroy;
3660 TREE_CHAIN (orig) = actor;
3661
3662 *resumer = actor;
3663 *destroyer = destroy;
3664
3665 delete suspend_points;
3666 suspend_points = NULL;
3667 return true;
3668 }
3669
3670 #include "gt-cp-coroutines.h"
3671