GCC Middle and Back End API Reference
coroutine-passes.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "target.h"
#include "tree.h"
#include "gimple.h"
#include "tree-pass.h"
#include "ssa.h"
#include "cgraph.h"
#include "pretty-print.h"
#include "diagnostic-core.h"
#include "fold-const.h"
#include "internal-fn.h"
#include "langhooks.h"
#include "gimplify.h"
#include "gimple-iterator.h"
#include "gimplify-me.h"
#include "gimple-walk.h"
#include "gimple-fold.h"
#include "tree-cfg.h"
#include "tree-into-ssa.h"
#include "tree-ssa-propagate.h"
#include "gimple-pretty-print.h"
#include "cfghooks.h"
Include dependency graph for coroutine-passes.cc:


static tree lower_coro_builtin (gimple_stmt_iterator *gsi, bool *handled_ops_p, struct walk_stmt_info *wi)
static unsigned int execute_lower_coro_builtins (void)
gimple_opt_passmake_pass_coroutine_lower_builtins (gcc::context *ctxt)
static void move_edge_and_update (edge e, basic_block old_bb, basic_block new_bb)
static unsigned int execute_early_expand_coro_ifns (void)
gimple_opt_passmake_pass_coroutine_early_expand_ifns (gcc::context *ctxt)

Function Documentation

◆ execute_early_expand_coro_ifns()

◆ execute_lower_coro_builtins()

static unsigned int execute_lower_coro_builtins ( void )
Main entry point for lowering coroutine FE builtins.   

References current_function_decl, ggc_alloc(), gimple_body(), gimple_set_body(), lower_coro_builtin(), NULL, and walk_gimple_seq_mod().

◆ lower_coro_builtin()

static tree lower_coro_builtin ( gimple_stmt_iterator * gsi,
bool * handled_ops_p,
struct walk_stmt_info * wi )
coroutine expansion and optimisation passes.

   Copyright (C) 2018-2024 Free Software Foundation, Inc.

 Contributed by Iain Sandoe <iain@sandoe.co.uk> under contract to Facebook.

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
Here we:
* lower the internal function that implements an exit from scope.
* expand the builtins that are used to implement the library
  interfaces to the coroutine frame.   

References boolean_type_node, build2(), build_int_cst(), build_pointer_type(), BUILT_IN_NORMAL, DECL_FUNCTION_CODE(), fndecl_built_in_p(), fold_build2, g, gcc_checking_assert, ggc_alloc(), gimple_build_assign(), gimple_build_goto(), gimple_call_arg(), gimple_call_fndecl(), gimple_call_internal_fn(), gimple_call_internal_p(), gimple_call_lhs(), gimple_call_set_fn(), gimple_has_substatements(), gsi_insert_before(), gsi_remove(), gsi_replace(), GSI_SAME_STMT, gsi_stmt(), make_ssa_name(), MAX, null_pointer_node, NULL_TREE, offset, ptr_type_node, ROUND_UP, size_int, wi::to_wide(), TREE_CODE, TREE_INT_CST_LOW, TREE_OPERAND, TREE_TYPE, TYPE_ALIGN_UNIT, TYPE_MAIN_VARIANT, and TYPE_SIZE_UNIT.

Referenced by execute_lower_coro_builtins().

◆ make_pass_coroutine_early_expand_ifns()

gimple_opt_pass * make_pass_coroutine_early_expand_ifns ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_coroutine_lower_builtins()

gimple_opt_pass * make_pass_coroutine_lower_builtins ( gcc::context * ctxt)

References ggc_alloc().

◆ move_edge_and_update()

static void move_edge_and_update ( edge e,
basic_block old_bb,
basic_block new_bb )
Expand the remaining coroutine IFNs.

In the front end we construct a single actor function that contains
the coroutine state machine.

The actor function has three entry conditions:
 1. from the ramp, resume point 0 - to initial-suspend.
 2. when resume () is executed (resume point N).
 3. from the destroy () shim when that is executed.

The actor function begins with two dispatchers; one for resume and
one for destroy (where the initial entry from the ramp is a special-
case of resume point 0).

Each suspend point and each dispatch entry is marked with an IFN such
that we can connect the relevant dispatchers to their target labels.

So, if we have:


This is await point NUM, and is the final await if FINAL is non-zero.
The resume point is RES_LAB, and the destroy point is DEST_LAB.

We expect to find a CO_ACTOR (NUM) in the resume dispatcher and a
CO_ACTOR (NUM+1) in the destroy dispatcher.

Initially, the intent of keeping the resume and destroy paths together
is that the conditionals controlling them are identical, and thus there
would be duplication of any optimisation of those paths if the split
were earlier.

Subsequent inlining of the actor (and DCE) is then able to extract the
resume and destroy paths as separate functions if that is found
profitable by the optimisers.

Once we have remade the connections to their correct postions, we elide
the labels that the front end inserted.   

References dump_file, gcc_checking_assert, ggc_alloc(), basic_block_def::index, and redirect_edge_and_branch().

Referenced by execute_early_expand_coro_ifns().