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