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