GCC Middle and Back End API Reference
tree-eh.cc File Reference
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "rtl.h"
#include "tree.h"
#include "gimple.h"
#include "cfghooks.h"
#include "tree-pass.h"
#include "ssa.h"
#include "cgraph.h"
#include "diagnostic-core.h"
#include "fold-const.h"
#include "calls.h"
#include "except.h"
#include "cfganal.h"
#include "cfgcleanup.h"
#include "tree-eh.h"
#include "gimple-iterator.h"
#include "tree-cfg.h"
#include "tree-into-ssa.h"
#include "tree-ssa.h"
#include "tree-inline.h"
#include "langhooks.h"
#include "cfgloop.h"
#include "gimple-low.h"
#include "stringpool.h"
#include "attribs.h"
#include "asan.h"
#include "gimplify.h"
Include dependency graph for tree-eh.cc:

Data Structures

union  treemple
struct  finally_tree_node
struct  finally_tree_hasher
struct  goto_queue_node
struct  leh_state
struct  leh_tf_state


#define LARGE_GOTO_QUEUE   20
#define verify_norecord_switch_expr(state, switch_expr)


static void add_stmt_to_eh_lp_fn (struct function *ifun, gimple *t, int num)
void add_stmt_to_eh_lp (gimple *t, int num)
static void record_stmt_eh_region (eh_region region, gimple *t)
bool remove_stmt_from_eh_lp_fn (struct function *ifun, gimple *t)
bool remove_stmt_from_eh_lp (gimple *t)
int lookup_stmt_eh_lp_fn (struct function *ifun, const gimple *t)
int lookup_stmt_eh_lp (const gimple *t)
static void record_in_finally_tree (treemple child, gtry *parent)
static void collect_finally_tree (gimple *stmt, gtry *region)
static void collect_finally_tree_1 (gimple_seq seq, gtry *region)
static bool outside_finally_tree (treemple start, gimple *target)
static gimple_seq lower_eh_must_not_throw (struct leh_state *, gtry *)
static void lower_eh_constructs_1 (struct leh_state *state, gimple_seq *seq)
static gimple_seq find_goto_replacement (struct leh_tf_state *tf, treemple stmt)
static void replace_goto_queue_cond_clause (tree *tp, struct leh_tf_state *tf, gimple_stmt_iterator *gsi)
static void replace_goto_queue_stmt_list (gimple_seq *, struct leh_tf_state *)
static void replace_goto_queue_1 (gimple *stmt, struct leh_tf_state *tf, gimple_stmt_iterator *gsi)
static void replace_goto_queue (struct leh_tf_state *tf)
static void record_in_goto_queue (struct leh_tf_state *tf, treemple new_stmt, int index, bool is_label, location_t location)
static void record_in_goto_queue_label (struct leh_tf_state *tf, treemple stmt, tree label, location_t location)
static void maybe_record_in_goto_queue (struct leh_state *state, gimple *stmt)
static void do_return_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod)
static void do_goto_redirection (struct goto_queue_node *q, tree finlab, gimple_seq mod, struct leh_tf_state *tf)
static void emit_post_landing_pad (gimple_seq *seq, eh_region region)
static void emit_resx (gimple_seq *seq, eh_region region)
static void note_eh_region_may_contain_throw (eh_region region)
static bool eh_region_may_contain_throw (eh_region r)
static gimple_seq frob_into_branch_around (gtry *tp, eh_region region, tree over)
static gimple_seq lower_try_finally_dup_block (gimple_seq seq, struct leh_state *outer_state, location_t loc)
static tree lower_try_finally_fallthru_label (struct leh_tf_state *tf)
static geh_elseget_eh_else (gimple_seq finally)
static void honor_protect_cleanup_actions (struct leh_state *outer_state, struct leh_state *this_state, struct leh_tf_state *tf)
static void lower_try_finally_nofallthru (struct leh_state *state, struct leh_tf_state *tf)
static void lower_try_finally_onedest (struct leh_state *state, struct leh_tf_state *tf)
static void lower_try_finally_copy (struct leh_state *state, struct leh_tf_state *tf)
static void lower_try_finally_switch (struct leh_state *state, struct leh_tf_state *tf)
static bool decide_copy_try_finally (int ndests, bool may_throw, gimple_seq finally)
static bool cleanup_is_dead_in (leh_state *state)
static gimple_seq lower_try_finally (struct leh_state *state, gtry *tp)
static gimple_seq lower_catch (struct leh_state *state, gtry *tp)
static gimple_seq lower_eh_filter (struct leh_state *state, gtry *tp)
static gimple_seq lower_cleanup (struct leh_state *state, gtry *tp)
static void lower_eh_constructs_2 (struct leh_state *state, gimple_stmt_iterator *gsi)
gimple_opt_passmake_pass_lower_eh (gcc::context *ctxt)
bool make_eh_dispatch_edges (geh_dispatch *stmt)
edge make_eh_edge (gimple *stmt)
static void redirect_eh_edge_1 (edge edge_in, basic_block new_bb, bool change_region)
edge redirect_eh_edge (edge edge_in, basic_block new_bb)
void redirect_eh_dispatch_edge (geh_dispatch *stmt, edge e, basic_block new_bb)
bool operation_could_trap_helper_p (enum tree_code op, bool fp_operation, bool honor_trapv, bool honor_nans, bool honor_snans, tree divisor, bool *handled)
bool operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv, tree divisor)
static bool in_array_bounds_p (tree ref)
static bool range_in_array_bounds_p (tree ref)
bool tree_could_trap_p (tree expr)
static tree find_trapping_overflow (tree *tp, int *walk_subtrees, void *data)
static tree replace_trapping_overflow (tree *tp, int *walk_subtrees, void *data)
tree rewrite_to_non_trapping_overflow (tree expr)
static bool stmt_could_throw_1_p (gassign *stmt)
bool stmt_could_throw_p (function *fun, gimple *stmt)
bool stmt_unremovable_because_of_non_call_eh_p (function *fun, gimple *stmt)
bool tree_could_throw_p (tree t)
bool stmt_can_throw_external (function *fun, gimple *stmt)
bool stmt_can_throw_internal (function *fun, gimple *stmt)
bool maybe_clean_eh_stmt_fn (struct function *ifun, gimple *stmt)
bool maybe_clean_eh_stmt (gimple *stmt)
bool maybe_clean_or_replace_eh_stmt (gimple *old_stmt, gimple *new_stmt)
bool maybe_duplicate_eh_stmt_fn (struct function *new_fun, gimple *new_stmt, struct function *old_fun, gimple *old_stmt, hash_map< void *, void * > *map, int default_lp_nr)
bool maybe_duplicate_eh_stmt (gimple *new_stmt, gimple *old_stmt)
static bool same_handler_p (gimple_seq oneh, gimple_seq twoh)
static void optimize_double_finally (gtry *one, gtry *two)
static void refactor_eh_r (gimple_seq seq)
gimple_opt_passmake_pass_refactor_eh (gcc::context *ctxt)
static bool lower_resx (basic_block bb, gresx *stmt, hash_map< eh_region, tree > *mnt_map)
gimple_opt_passmake_pass_lower_resx (gcc::context *ctxt)
static void optimize_clobbers (basic_block bb)
static int sink_clobbers (basic_block bb, gimple_seq *sunk=NULL, bool *found_opportunity=NULL)
static bool lower_eh_dispatch (basic_block src, geh_dispatch *stmt)
gimple_opt_passmake_pass_lower_eh_dispatch (gcc::context *ctxt)
static void mark_reachable_handlers (sbitmap *r_reachablep, sbitmap *lp_reachablep)
static void remove_unreachable_handlers (void)
void maybe_remove_unreachable_handlers (void)
static void remove_unreachable_handlers_no_lp (void)
static bool unsplit_eh (eh_landing_pad lp)
static bool unsplit_all_eh (void)
void unsplit_eh_edges (void)
static bool cleanup_empty_eh_merge_phis (basic_block new_bb, basic_block old_bb, edge old_bb_out, bool change_region)
static void cleanup_empty_eh_move_lp (basic_block bb, edge e_out, eh_landing_pad lp, eh_region new_region)
static bool cleanup_empty_eh_unsplit (basic_block bb, edge e_out, eh_landing_pad lp)
static bool infinite_empty_loop_p (edge e_first)
static bool cleanup_empty_eh (eh_landing_pad lp)
static bool cleanup_all_empty_eh (void)
static unsigned int execute_cleanup_eh_1 (void)
gimple_opt_passmake_pass_cleanup_eh (gcc::context *ctxt)
DEBUG_FUNCTION bool verify_eh_edges (gimple *stmt)
DEBUG_FUNCTION bool verify_eh_dispatch_edge (geh_dispatch *stmt)


static hash_table< finally_tree_hasher > * finally_tree
static gimple_seq eh_seq
static bitmap eh_region_may_contain_throw_map

Macro Definition Documentation


#define LARGE_GOTO_QUEUE   20
Search for STMT in the goto queue.  Return the replacement,
or null if the statement isn't in the queue.   

Referenced by find_goto_replacement().

◆ verify_norecord_switch_expr

#define verify_norecord_switch_expr ( state,
switch_expr )

Referenced by lower_eh_constructs_2().

Function Documentation

◆ add_stmt_to_eh_lp()

◆ add_stmt_to_eh_lp_fn()

static void add_stmt_to_eh_lp_fn ( struct function * ifun,
gimple * t,
int num )
Misc functions used in this file.   
Remember and lookup EH landing pad data for arbitrary statements.
Really this means any statement that could_throw_p.  We could
stuff this information into the stmt_ann data structure, but:

(1) We absolutely rely on this information being kept until
we get to rtl.  Once we're done with lowering here, if we lose
the information there's no way to recover it!

(2) There are many more statements that *cannot* throw as
compared to those that can.  We should be saving some amount
of space by only allocating memory for those that can throw.   
Add statement T in function IFUN to landing pad NUM.   

References gcc_assert, get_eh_throw_stmt_table(), ggc_alloc(), and set_eh_throw_stmt_table().

Referenced by add_stmt_to_eh_lp(), maybe_duplicate_eh_stmt_fn(), and record_stmt_eh_region().

◆ cleanup_all_empty_eh()

static bool cleanup_all_empty_eh ( void )
Do a post-order traversal of the EH region tree.  Examine each
post_landing_pad block and see if we can eliminate it as empty.   

References cfun, changed, cleanup_empty_eh(), i, vec_safe_iterate(), and vec_safe_length().

Referenced by execute_cleanup_eh_1().

◆ cleanup_empty_eh()

◆ cleanup_empty_eh_merge_phis()

static bool cleanup_empty_eh_merge_phis ( basic_block new_bb,
basic_block old_bb,
edge old_bb_out,
bool change_region )
A subroutine of cleanup_empty_eh.  Redirect all EH edges incoming
to OLD_BB to NEW_BB; return true on success, false on failure.

OLD_BB_OUT is the edge into NEW_BB from OLD_BB, so if we miss any
PHI variables from OLD_BB we can pick them up from OLD_BB_OUT.
Virtual PHIs may be deleted and marked for renaming.   

References BITMAP_ALLOC, bitmap_bit_p, BITMAP_FREE, bitmap_set_bit, ei_next(), ei_safe_edge(), ei_start, find_edge(), flush_pending_stmts(), FOR_EACH_EDGE, FOR_EACH_IMM_USE_FAST, ggc_alloc(), gimple_bb(), gimple_debug_bind_p(), gimple_phi_arg_def(), gimple_phi_arg_location(), gimple_phi_result(), gsi_end_p(), gsi_next(), gsi_start_phis(), has_single_use(), loop::latch, basic_block_def::loop_father, LOOPS_MAY_HAVE_MULTIPLE_LATCHES, loops_state_set(), mark_loop_for_removal(), NULL, redirect_edge_succ(), redirect_edge_var_map_add(), redirect_edge_var_map_clear(), redirect_eh_edge_1(), single_pred_p(), SSA_NAME_VERSION, and USE_STMT.

Referenced by cleanup_empty_eh(), and cleanup_empty_eh_unsplit().

◆ cleanup_empty_eh_move_lp()

static void cleanup_empty_eh_move_lp ( basic_block bb,
edge e_out,
eh_landing_pad lp,
eh_region new_region )
A subroutine of cleanup_empty_eh.  Move a landing pad LP from its
old region to NEW_REGION at BB.   

References profile_probability::always(), ggc_alloc(), gsi_last_bb(), gsi_remove(), gsi_stmt(), eh_region_d::landing_pads, eh_landing_pad_d::next_lp, eh_landing_pad_d::region, and unlink_stmt_vdef().

Referenced by cleanup_empty_eh().

◆ cleanup_empty_eh_unsplit()

static bool cleanup_empty_eh_unsplit ( basic_block bb,
edge e_out,
eh_landing_pad lp )
A subroutine of cleanup_empty_eh.  Handle more complex cases of
unsplitting than unsplit_eh was prepared to handle, e.g. when
multiple incoming edges and phis are involved.   

References cleanup_empty_eh_merge_phis(), dump_file, dump_flags, EH_LANDING_PAD_NR, gcc_assert, get_eh_region_from_lp_number(), ggc_alloc(), gimple_label_label(), gsi_end_p(), gsi_next(), gsi_start_bb(), gsi_stmt(), eh_landing_pad_d::index, NULL, eh_landing_pad_d::region, and TDF_DETAILS.

Referenced by cleanup_empty_eh().

◆ cleanup_is_dead_in()

static bool cleanup_is_dead_in ( leh_state * state)
REG is current region of a LEH state.
is the enclosing region for a possible cleanup region, or the region
itself.  Returns TRUE if such a region would be unreachable.

Cleanup regions within a must-not-throw region aren't actually reachable
even if there are throwing stmts within them, because the personality
routine will call terminate before unwinding.   

References ERT_CLEANUP, ERT_MUST_NOT_THROW, gcc_assert, ggc_alloc(), eh_region_d::outer, and eh_region_d::type.

Referenced by lower_cleanup(), and lower_try_finally().

◆ collect_finally_tree()

◆ collect_finally_tree_1()

static void collect_finally_tree_1 ( gimple_seq seq,
gtry * region )
Go through the gimple sequence.  Works with collect_finally_tree to
record all GIMPLE_LABEL and GIMPLE_TRY statements.  

References collect_finally_tree(), gsi_end_p(), gsi_next(), gsi_start(), and gsi_stmt().

Referenced by collect_finally_tree(), and lower_try_finally_dup_block().

◆ decide_copy_try_finally()

static bool decide_copy_try_finally ( int ndests,
bool may_throw,
gimple_seq finally )
Decide whether or not we are going to duplicate the finally block.
There are several considerations.

Second, we'd like to prevent egregious code growth.  One way to
do this is to estimate the size of the finally block, multiply
that by the number of copies we'd need to make, and compare against
the estimate of the size of the switch machinery we'd have to add.   

References cfun, eni_size_weights, estimate_num_insns_seq(), get_eh_else(), ggc_alloc(), gimple_call_builtin_p(), gimple_clobber_p(), gimple_eh_else_n_body(), gsi_end_p(), gsi_next(), gsi_start(), gsi_stmt(), is_gimple_debug(), optimize_function_for_size_p(), and goto_queue_node::stmt.

Referenced by lower_try_finally().

◆ do_goto_redirection()

◆ do_return_redirection()

◆ eh_region_may_contain_throw()

static bool eh_region_may_contain_throw ( eh_region r)
Check if REGION has been marked as containing a throw.  If REGION is
NULL, this predicate is false.   

References bitmap_bit_p, eh_region_may_contain_throw_map, and r.

Referenced by lower_catch(), lower_cleanup(), lower_eh_filter(), and lower_try_finally().

◆ emit_post_landing_pad()

◆ emit_resx()

◆ execute_cleanup_eh_1()

static unsigned int execute_cleanup_eh_1 ( void )
Perform cleanups and lowering of exception handling
   1) cleanups regions with handlers doing nothing are optimized out
   2) MUST_NOT_THROW regions that became dead because of 1) are optimized out
   3) Info about regions that are containing instructions, and regions
      reachable via local EH edges is collected
   4) Eh tree is pruned for regions no longer necessary.

  TODO: Push MUST_NOT_THROW regions to the root of the EH tree.
        Unify those that have the same failure decl and locus.

References CDI_DOMINATORS, CDI_POST_DOMINATORS, cfun, changed, cleanup_all_empty_eh(), delete_unreachable_blocks(), free_dominance_info(), ggc_alloc(), remove_unreachable_handlers(), remove_unreachable_handlers_no_lp(), TODO_cleanup_cfg, TODO_update_ssa_only_virtuals, and unsplit_all_eh().

◆ find_goto_replacement()

◆ find_trapping_overflow()

static tree find_trapping_overflow ( tree * tp,
int * walk_subtrees,
void * data )
Return non-NULL if there is an integer operation with trapping overflow
we can rewrite into non-trapping.  Called via walk_tree from

References ANY_INTEGRAL_TYPE_P, EXPR_P, ggc_alloc(), IS_TYPE_OR_DECL_P, NULL, NULL_TREE, operation_no_trapping_overflow(), TREE_CODE, and TREE_TYPE.

Referenced by replace_trapping_overflow(), and rewrite_to_non_trapping_overflow().

◆ frob_into_branch_around()

static gimple_seq frob_into_branch_around ( gtry * tp,
eh_region region,
tree over )
We want to transform
     try { body; } catch { stuff; }
       goto over;

TP is a GIMPLE_TRY node.  REGION is the region whose post_landing_pad
should be placed before the second operand, or NULL.  OVER is
an existing label that should be put at the exit, or NULL.   

References create_artificial_label(), eh_seq, emit_post_landing_pad(), ggc_alloc(), gimple_build_goto(), gimple_build_label(), gimple_location(), gimple_seq_add_seq(), gimple_seq_add_stmt(), gimple_seq_may_fallthru(), gimple_set_location(), gimple_try_cleanup(), gimple_try_eval(), and leh_tf_state::region.

Referenced by lower_catch(), lower_cleanup(), and lower_eh_filter().

◆ get_eh_else()

static geh_else * get_eh_else ( gimple_seq finally)

◆ honor_protect_cleanup_actions()

static void honor_protect_cleanup_actions ( struct leh_state * outer_state,
struct leh_state * this_state,
struct leh_tf_state * tf )
A subroutine of lower_try_finally.  If the eh_protect_cleanup_actions
langhook returns non-null, then the language requires that the exception
path out of a try_finally be treated specially.  To wit: the code within
the finally block may not itself throw an exception.  We have two choices
here. First we can duplicate the finally block and wrap it in a
must_not_throw region.  Second, we can generate code like

     try {
     } catch {
       if (fintmp == eh_edge)

where "fintmp" is the temporary used in the switch statement generation
alternative considered below.  For the nonce, we always choose the first

THIS_STATE may be null if this is a try-cleanup, not a try-finally.   

References lang_hooks::eh_protect_cleanup_actions, eh_seq, emit_post_landing_pad(), emit_resx(), get_eh_else(), ggc_alloc(), gimple_build_eh_must_not_throw(), gimple_build_try(), gimple_eh_else_e_body(), gimple_eh_else_n_body(), gimple_location(), gimple_seq_add_seq(), gimple_seq_alloc_with_stmt(), gimple_seq_may_fallthru(), GIMPLE_TRY_CATCH, gimple_try_catch_is_cleanup(), gimple_try_cleanup(), gimple_try_eval(), gimple_try_kind(), gimple_try_set_cleanup(), gsi_insert_seq_before(), gsi_remove(), GSI_SAME_STMT, gsi_start(), gsi_stmt(), lower_eh_constructs_1(), lower_eh_must_not_throw(), lower_try_finally_dup_block(), leh_tf_state::may_throw, NULL, leh_tf_state::region, leh_tf_state::top_p, and leh_tf_state::try_finally_expr.

Referenced by lower_cleanup(), and lower_try_finally().

◆ in_array_bounds_p()

static bool in_array_bounds_p ( tree ref)
Returns true if it is possible to prove that the index of
an array access REF (an ARRAY_REF expression) falls into the
array bounds.   

References array_ref_low_bound(), array_ref_up_bound(), ggc_alloc(), TREE_CODE, tree_int_cst_lt(), and TREE_OPERAND.

Referenced by tree_could_trap_p().

◆ infinite_empty_loop_p()

static bool infinite_empty_loop_p ( edge e_first)
Return true if edge E_FIRST is part of an empty infinite loop
or leads to such a loop through a series of single successor
empty bbs.   

References ggc_alloc(), gsi_after_labels(), gsi_end_p(), gsi_next_nondebug(), gsi_stmt(), is_gimple_debug(), NULL, single_succ_edge(), and single_succ_p().

Referenced by cleanup_empty_eh().

◆ lookup_stmt_eh_lp()

◆ lookup_stmt_eh_lp_fn()

int lookup_stmt_eh_lp_fn ( struct function * ifun,
const gimple * t )
Determine if statement T is inside an EH region in function IFUN.
Positive numbers indicate a landing pad index; negative numbers
indicate a MUST_NOT_THROW region index; zero indicates that the
statement is not recorded in the region table.   

References ggc_alloc(), and NULL.

Referenced by ipa_icf_gimple::func_checker::compare_bb(), find_outermost_region_in_block(), lookup_stmt_eh_lp(), maybe_duplicate_eh_stmt_fn(), merge_stmts_p(), output_bb(), stmt_can_throw_external(), and stmt_can_throw_internal().

◆ lower_catch()

◆ lower_cleanup()

static gimple_seq lower_cleanup ( struct leh_state * state,
gtry * tp )

◆ lower_eh_constructs_1()

◆ lower_eh_constructs_2()

◆ lower_eh_dispatch()

◆ lower_eh_filter()

◆ lower_eh_must_not_throw()

static gimple_seq lower_eh_must_not_throw ( struct leh_state * state,
gtry * tp )
A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY with
an GIMPLE_EH_MUST_NOT_THROW to a sequence of labels and blocks,
plus the exception region trees that record all the magic.   

References gen_eh_region_must_not_throw(), ggc_alloc(), gimple_eh_must_not_throw_fndecl(), gimple_location(), gimple_seq_first_stmt(), gimple_try_cleanup(), gimple_try_eval(), gimple_try_eval_ptr(), LOCATION_LOCUS, lower_eh_constructs_1(), and TREE_USED.

Referenced by honor_protect_cleanup_actions(), and lower_eh_constructs_2().

◆ lower_resx()

◆ lower_try_finally()

static gimple_seq lower_try_finally ( struct leh_state * state,
gtry * tp )
A subroutine of lower_eh_constructs_1.  Lower a GIMPLE_TRY_FINALLY nodes
to a sequence of labels and blocks, plus the exception region trees
that record all the magic.  This is complicated by the need to
arrange for the FINALLY block to be executed on all exits.   

References cleanup_is_dead_in(), decide_copy_try_finally(), eh_region_may_contain_throw(), eh_seq, free(), gen_eh_region_cleanup(), ggc_alloc(), gimple_build_label(), gimple_seq_add_seq(), gimple_seq_add_stmt(), gimple_seq_may_fallthru(), gimple_try_cleanup(), gimple_try_eval(), gimple_try_eval_ptr(), gimple_try_set_cleanup(), honor_protect_cleanup_actions(), lower_eh_constructs_1(), lower_try_finally_copy(), lower_try_finally_nofallthru(), lower_try_finally_onedest(), lower_try_finally_switch(), NULL, and using_eh_for_cleanups_p().

Referenced by lower_eh_constructs_2().

◆ lower_try_finally_copy()

◆ lower_try_finally_dup_block()

static gimple_seq lower_try_finally_dup_block ( gimple_seq seq,
struct leh_state * outer_state,
location_t loc )

◆ lower_try_finally_fallthru_label()

static tree lower_try_finally_fallthru_label ( struct leh_tf_state * tf)
A subroutine of lower_try_finally.  Create a fallthru label for
the given try_finally state.  The only tricky bit here is that
we have to make sure to record the label in our outer context.   

References create_artificial_label(), leh_tf_state::fallthru_label, gimple_location(), leh_tf_state::outer, record_in_finally_tree(), treemple::t, leh_state::tf, and leh_tf_state::try_finally_expr.

Referenced by lower_try_finally_copy(), and lower_try_finally_switch().

◆ lower_try_finally_nofallthru()

◆ lower_try_finally_onedest()

◆ lower_try_finally_switch()

◆ make_eh_dispatch_edges()

bool make_eh_dispatch_edges ( geh_dispatch * stmt)
Create the multiple edges from an EH_DISPATCH statement to all of
the possible handlers for its EH region.  Return true if there's
no fallthru edge; false if there is.   

References cfun, ERT_ALLOWED_EXCEPTIONS, ERT_TRY, gcc_unreachable, get_eh_region_from_number(), gimple_bb(), gimple_eh_dispatch_region(), eh_catch_d::label, label_to_block(), make_edge(), eh_catch_d::next_catch, NULL, r, and eh_catch_d::type_list.

Referenced by copy_edges_for_bb(), and make_edges_bb().

◆ make_eh_edge()

edge make_eh_edge ( gimple * stmt)
Create the single EH edge from STMT to its nearest landing pad,
if there is such a landing pad within the current function.   

References cfun, gcc_assert, get_eh_landing_pad_from_number(), ggc_alloc(), gimple_bb(), label_to_block(), lookup_stmt_eh_lp(), make_edge(), NULL, and eh_landing_pad_d::post_landing_pad.

Referenced by copy_edges_for_bb(), gsi_insert_finally_seq_after_call(), and make_edges_bb().

◆ make_pass_cleanup_eh()

gimple_opt_pass * make_pass_cleanup_eh ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_lower_eh()

gimple_opt_pass * make_pass_lower_eh ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_lower_eh_dispatch()

gimple_opt_pass * make_pass_lower_eh_dispatch ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_lower_resx()

gimple_opt_pass * make_pass_lower_resx ( gcc::context * ctxt)

References ggc_alloc().

◆ make_pass_refactor_eh()

gimple_opt_pass * make_pass_refactor_eh ( gcc::context * ctxt)

References ggc_alloc().

◆ mark_reachable_handlers()

static void mark_reachable_handlers ( sbitmap * r_reachablep,
sbitmap * lp_reachablep )
Walk statements, see what regions and, optionally, landing pads
are really referenced.

Returns in R_REACHABLEP an sbitmap with bits set for reachable regions,
and in LP_REACHABLE an sbitmap with bits set for reachable landing pads.

Passing NULL for LP_REACHABLE is valid, in this case only reachable
regions are marked.

The caller is responsible for freeing the returned sbitmaps.   

References bitmap_clear(), bitmap_set_bit, cfun, FOR_EACH_BB_FN, gcc_assert, gcc_checking_assert, get_eh_region_from_lp_number(), ggc_alloc(), gimple_call_arg(), gimple_call_builtin_p(), gimple_eh_dispatch_region(), gimple_resx_region(), gsi_end_p(), gsi_next(), gsi_one_before_end_p(), gsi_start_bb(), gsi_stmt(), i, eh_region_d::index, lookup_stmt_eh_lp(), NULL, sbitmap_alloc(), and tree_to_shwi().

Referenced by remove_unreachable_handlers(), and remove_unreachable_handlers_no_lp().

◆ maybe_clean_eh_stmt()

◆ maybe_clean_eh_stmt_fn()

bool maybe_clean_eh_stmt_fn ( struct function * ifun,
gimple * stmt )
Given a statement STMT in IFUN, if STMT can no longer throw, then
remove any entry it might have from the EH table.  Return true if
any change was made.   

References ggc_alloc(), remove_stmt_from_eh_lp_fn(), and stmt_could_throw_p().

Referenced by maybe_clean_eh_stmt(), and update_call_expr().

◆ maybe_clean_or_replace_eh_stmt()

bool maybe_clean_or_replace_eh_stmt ( gimple * old_stmt,
gimple * new_stmt )

◆ maybe_duplicate_eh_stmt()

bool maybe_duplicate_eh_stmt ( gimple * new_stmt,
gimple * old_stmt )
Similar, but both OLD_STMT and NEW_STMT are within the current function,
and thus no remapping is required.   

References add_stmt_to_eh_lp(), cfun, ggc_alloc(), lookup_stmt_eh_lp(), and stmt_could_throw_p().

Referenced by gimple_duplicate_bb().

◆ maybe_duplicate_eh_stmt_fn()

bool maybe_duplicate_eh_stmt_fn ( struct function * new_fun,
gimple * new_stmt,
struct function * old_fun,
gimple * old_stmt,
hash_map< void *, void * > * map,
int default_lp_nr )
Given a statement OLD_STMT in OLD_FUN and a duplicate statement NEW_STMT
in NEW_FUN, copy the EH table data from OLD_STMT to NEW_STMT.  The MAP
operand is the return value of duplicate_eh_regions.   

References add_stmt_to_eh_lp_fn(), ggc_alloc(), lookup_stmt_eh_lp_fn(), map, and stmt_could_throw_p().

Referenced by copy_bb(), and move_block_to_fn().

◆ maybe_record_in_goto_queue()

static void maybe_record_in_goto_queue ( struct leh_state * state,
gimple * stmt )
For any GIMPLE_GOTO or GIMPLE_RETURN, decide whether it leaves a try_finally
node, and if so record that fact in the goto queue associated with that
try_finally node.   

References EXPR_LOCATION, gcc_unreachable, ggc_alloc(), gimple_cond_false_label(), gimple_cond_true_label(), gimple_goto_dest(), gimple_location(), gimple_op_ptr(), leh_tf_state::may_return, record_in_goto_queue(), and record_in_goto_queue_label().

Referenced by lower_eh_constructs_2(), lower_try_finally_copy(), lower_try_finally_onedest(), and lower_try_finally_switch().

◆ maybe_remove_unreachable_handlers()

void maybe_remove_unreachable_handlers ( void )
Remove unreachable handlers if any landing pads have been removed after
last ehcleanup pass (due to gimple_purge_dead_eh_edges).   

References cfun, FOR_EACH_VEC_SAFE_ELT, i, label_to_block(), NULL, NULL_TREE, eh_landing_pad_d::post_landing_pad, and remove_unreachable_handlers().

Referenced by execute_cleanup_cfg_post_optimizing(), and unsplit_eh_edges().

◆ note_eh_region_may_contain_throw()

static void note_eh_region_may_contain_throw ( eh_region region)
Note that the current EH region may contain a throw, or a
call to a function which itself may contain a throw.   

References bitmap_set_bit, eh_region_may_contain_throw_map, ERT_MUST_NOT_THROW, eh_region_d::index, NULL, eh_region_d::outer, leh_tf_state::region, and eh_region_d::type.

Referenced by lower_eh_constructs_2().

◆ operation_could_trap_helper_p()

bool operation_could_trap_helper_p ( enum tree_code op,
bool fp_operation,
bool honor_trapv,
bool honor_nans,
bool honor_snans,
tree divisor,
bool * handled )

◆ operation_could_trap_p()

bool operation_could_trap_p ( enum tree_code op,
bool fp_operation,
bool honor_trapv,
tree divisor )
Return true if operation OP may trap.  FP_OPERATION is true if OP is applied
on floating-point values.  HONOR_TRAPV is true if OP is applied on integer
type operands that may trap.  If OP is a division operator, DIVISOR contains
the value of the divisor.   

References gcc_assert, ggc_alloc(), operation_could_trap_helper_p(), tcc_binary, tcc_comparison, tcc_unary, and TREE_CODE_CLASS.

Referenced by expand_omp_for_init_vars(), fold_binary_op_with_conditional_arg(), gimple_could_trap_p_1(), maybe_resimplify_conditional_op(), replace_stmt_with_simplification(), stmt_could_throw_p(), and tree_could_trap_p().

◆ optimize_clobbers()

static void optimize_clobbers ( basic_block bb)

◆ optimize_double_finally()

static void optimize_double_finally ( gtry * one,
gtry * two )
 try { A() } finally { try { ~B() } catch { ~A() } }
 try { ... } finally { ~A() }
 try { A() } catch { ~B() }
 try { ~B() ... } finally { ~A() }

This occurs frequently in C++, where A is a local variable and B is a
temporary used in the initializer for A.   

References copy_gimple_seq_and_replace_locals(), ggc_alloc(), gimple_seq_add_seq(), GIMPLE_TRY_CATCH, gimple_try_cleanup(), gimple_try_eval(), gimple_try_kind(), gimple_try_set_cleanup(), gimple_try_set_eval(), gimple_try_set_kind(), gsi_one_before_end_p(), gsi_start(), gsi_stmt(), and same_handler_p().

Referenced by refactor_eh_r().

◆ outside_finally_tree()

static bool outside_finally_tree ( treemple start,
gimple * target )
Use the finally tree to determine if a jump from START to TARGET
would leave the try_finally node that START lives in.   

References finally_tree_node::child, finally_tree, and finally_tree_node::parent.

Referenced by record_in_goto_queue_label().

◆ range_in_array_bounds_p()

static bool range_in_array_bounds_p ( tree ref)
Returns true if it is possible to prove that the range of
an array access REF (an ARRAY_RANGE_REF expression) falls
into the array bounds.   

References array_ref_low_bound(), array_ref_up_bound(), ggc_alloc(), TREE_CODE, tree_int_cst_lt(), TREE_TYPE, TYPE_DOMAIN, TYPE_MAX_VALUE, and TYPE_MIN_VALUE.

Referenced by tree_could_trap_p().

◆ record_in_finally_tree()

◆ record_in_goto_queue()

static void record_in_goto_queue ( struct leh_tf_state * tf,
treemple new_stmt,
int index,
bool is_label,
location_t location )
Add a new record to the goto queue contained in TF. NEW_STMT is the
data to be added, IS_LABEL indicates whether NEW_STMT is a label or
a gimple return.  

References gcc_assert, ggc_alloc(), leh_tf_state::goto_queue, leh_tf_state::goto_queue_active, leh_tf_state::goto_queue_map, leh_tf_state::goto_queue_size, goto_queue_node::index, goto_queue_node::is_label, goto_queue_node::location, and goto_queue_node::stmt.

Referenced by maybe_record_in_goto_queue(), and record_in_goto_queue_label().

◆ record_in_goto_queue_label()

static void record_in_goto_queue_label ( struct leh_tf_state * tf,
treemple stmt,
tree label,
location_t location )

◆ record_stmt_eh_region()

static void record_stmt_eh_region ( eh_region region,
gimple * t )

◆ redirect_eh_dispatch_edge()

void redirect_eh_dispatch_edge ( geh_dispatch * stmt,
edge e,
basic_block new_bb )
This is a subroutine of gimple_redirect_edge_and_branch.  Update the
labels for redirecting a non-fallthru EH_DISPATCH edge E to NEW_BB.
The actual edge update will happen in the caller.   

References cfun, ERT_ALLOWED_EXCEPTIONS, ERT_TRY, gcc_assert, gcc_unreachable, get_eh_region_from_number(), ggc_alloc(), gimple_block_label(), gimple_eh_dispatch_region(), eh_catch_d::label, label_to_block(), eh_catch_d::next_catch, and r.

Referenced by gimple_redirect_edge_and_branch().

◆ redirect_eh_edge()

edge redirect_eh_edge ( edge edge_in,
basic_block new_bb )
Redirect EH edge E to NEW_BB.   

References ggc_alloc(), redirect_eh_edge_1(), and ssa_redirect_edge().

Referenced by gimple_redirect_edge_and_branch().

◆ redirect_eh_edge_1()

static void redirect_eh_edge_1 ( edge edge_in,
basic_block new_bb,
bool change_region )
Do the work in redirecting EDGE_IN to NEW_BB within the EH region tree;
do not actually perform the final edge redirection.

CHANGE_REGION is true when we're being called from cleanup_empty_eh and
we intend to change the destination EH region as well; this means
EH_LANDING_PAD_NR must already be set on the destination block label.
If false, we're being called from generic cfg manipulation code and we
should preserve our place within the region tree.   

References add_stmt_to_eh_lp(), EH_LANDING_PAD_NR, FOR_EACH_EDGE, gcc_assert, gcc_checking_assert, gen_eh_landing_pad(), get_eh_landing_pad_from_number(), ggc_alloc(), gimple_block_label(), gsi_last_bb(), lookup_stmt_eh_lp(), NULL, remove_eh_landing_pad(), and remove_stmt_from_eh_lp().

Referenced by cleanup_empty_eh_merge_phis(), redirect_eh_edge(), and unsplit_eh().

◆ refactor_eh_r()

static void refactor_eh_r ( gimple_seq seq)

◆ remove_stmt_from_eh_lp()

bool remove_stmt_from_eh_lp ( gimple * t)
Remove statement T in the current function (cfun) from its
EH landing pad.   

References cfun, and remove_stmt_from_eh_lp_fn().

Referenced by cleanup_empty_eh(), gsi_remove(), maybe_clean_or_replace_eh_stmt(), cgraph_edge::redirect_call_stmt_to_callee(), and redirect_eh_edge_1().

◆ remove_stmt_from_eh_lp_fn()

bool remove_stmt_from_eh_lp_fn ( struct function * ifun,
gimple * t )
Remove statement T in function IFUN from its EH landing pad.   

References get_eh_throw_stmt_table(), ggc_alloc(), and hash_map< KeyId, Value, Traits >::remove().

Referenced by maybe_clean_eh_stmt_fn(), move_block_to_fn(), and remove_stmt_from_eh_lp().

◆ remove_unreachable_handlers()

◆ remove_unreachable_handlers_no_lp()

static void remove_unreachable_handlers_no_lp ( void )
Remove regions that do not have landing pads.  This assumes
that remove_unreachable_handlers has already been run, and
that we've just manipulated the landing pads since then.

Preserve regions with landing pads and regions that prevent
exceptions from propagating further, even if these regions
are not reachable.   

References bitmap_bit_p, bitmap_set_bit, cfun, dump_file, ERT_MUST_NOT_THROW, FOR_EACH_VEC_SAFE_ELT, ggc_alloc(), i, eh_region_d::index, eh_region_d::landing_pads, mark_reachable_handlers(), NULL, remove_unreachable_eh_regions(), sbitmap_free(), and eh_region_d::type.

Referenced by execute_cleanup_eh_1().

◆ replace_goto_queue()

◆ replace_goto_queue_1()

◆ replace_goto_queue_cond_clause()

static void replace_goto_queue_cond_clause ( tree * tp,
struct leh_tf_state * tf,
gimple_stmt_iterator * gsi )
A subroutine of replace_goto_queue_1.  Handles the sub-clauses of a
lowered GIMPLE_COND.  If, by chance, the replacement is a simple goto,
then we can just splat it in, otherwise we add the new stmts immediately
after the GIMPLE_COND and redirect.   

References create_artificial_label(), find_goto_replacement(), ggc_alloc(), gimple_build_label(), gimple_goto_dest(), gimple_location(), gimple_seq_copy(), gimple_seq_first_stmt(), gimple_seq_singleton_p(), GSI_CONTINUE_LINKING, gsi_insert_after(), gsi_insert_seq_after(), gsi_stmt(), and treemple::tp.

Referenced by replace_goto_queue_1().

◆ replace_goto_queue_stmt_list()

static void replace_goto_queue_stmt_list ( gimple_seq * seq,
struct leh_tf_state * tf )
The real work of replace_goto_queue.  Returns with TSI updated to
point to the next statement.   
A subroutine of replace_goto_queue.  Handles GIMPLE_SEQ.   

References gsi_end_p(), gsi_start(), gsi_stmt(), and replace_goto_queue_1().

Referenced by replace_goto_queue(), and replace_goto_queue_1().

◆ replace_trapping_overflow()

static tree replace_trapping_overflow ( tree * tp,
int * walk_subtrees,
void * data )

◆ rewrite_to_non_trapping_overflow()

tree rewrite_to_non_trapping_overflow ( tree expr)

◆ same_handler_p()

static bool same_handler_p ( gimple_seq oneh,
gimple_seq twoh )
Returns TRUE if oneh and twoh are exception handlers (gimple_try_cleanup of
GIMPLE_TRY) that are similar enough to be considered the same.  Currently
this only handles handlers consisting of a single call, as that's the
important case for C++: a destructor call for a particular object showing
up in multiple handlers.   

References ggc_alloc(), gimple_call_arg(), gimple_call_chain(), gimple_call_lhs(), gimple_call_num_args(), gimple_call_same_target_p(), gsi_one_before_end_p(), gsi_start(), gsi_stmt(), is_gimple_call(), and operand_equal_p().

Referenced by optimize_double_finally().

◆ sink_clobbers()

◆ stmt_can_throw_external()

bool stmt_can_throw_external ( function * fun,
gimple * stmt )
Return true if STMT can throw an exception that is not caught within its
function FUN.  FUN can be NULL but the function is extra conservative

References lookup_stmt_eh_lp_fn(), and stmt_could_throw_p().

Referenced by analyze_function(), check_call(), check_stmt(), cleanup_empty_eh(), compute_avail(), symbol_table::create_edge(), find_tail_calls(), cgraph_edge::set_call_stmt(), stmt_can_terminate_bb_p(), stmt_kills_ref_p(), and stmt_may_terminate_function_p().

◆ stmt_can_throw_internal()

◆ stmt_could_throw_1_p()

static bool stmt_could_throw_1_p ( gassign * stmt)

◆ stmt_could_throw_p()

bool stmt_could_throw_p ( function * fun,
gimple * stmt )

◆ stmt_unremovable_because_of_non_call_eh_p()

bool stmt_unremovable_because_of_non_call_eh_p ( function * fun,
gimple * stmt )
Return true if STMT in function FUN must be assumed necessary because of
non-call exceptions.   

References function::can_delete_dead_exceptions, function::can_throw_non_call_exceptions, and stmt_could_throw_p().

Referenced by simple_dce_from_worklist().

◆ tree_could_throw_p()

◆ tree_could_trap_p()

◆ unsplit_all_eh()

static bool unsplit_all_eh ( void )
Examine each landing pad block and see if it matches unsplit_eh.   

References cfun, changed, i, unsplit_eh(), and vec_safe_iterate().

Referenced by execute_cleanup_eh_1(), and unsplit_eh_edges().

◆ unsplit_eh()

static bool unsplit_eh ( eh_landing_pad lp)
Undo critical edge splitting on an EH landing pad.  Earlier, we
optimisticaly split all sorts of edges, including EH edges.  The
optimization passes in between may not have needed them; if not,
we should undo the split.

Recognize this case by having one EH edge incoming to the BB and
one normal edge outgoing; BB should be empty apart from the
post_landing_pad label.

Note that this is slightly different from the empty handler case
handled by cleanup_empty_eh, in that the actual handler may yet
have actual code but the landing pad has been separated from the
handler.  As such, cleanup_empty_eh relies on this transformation
having been done first.   

References cfun, dump_file, dump_flags, EH_LANDING_PAD_NR, find_edge(), FOR_EACH_IMM_USE_ON_STMT, FOR_EACH_IMM_USE_STMT, get_eh_region_from_lp_number(), ggc_alloc(), gimple_label_label(), gimple_phi_arg_def(), gimple_phi_result(), gimple_seq_empty_p(), gsi_after_labels(), gsi_end_p(), gsi_next(), gsi_next_nondebug(), gsi_start_bb(), gsi_start_phis(), gsi_stmt(), eh_landing_pad_d::index, is_gimple_debug(), label_to_block(), phi_nodes(), eh_landing_pad_d::post_landing_pad, redirect_edge_pred(), redirect_eh_edge_1(), eh_landing_pad_d::region, remove_edge(), remove_phi_node(), SET_USE, single_pred_edge(), single_pred_p(), single_succ_edge(), single_succ_p(), SSA_NAME_OCCURS_IN_ABNORMAL_PHI, and TDF_DETAILS.

Referenced by unsplit_all_eh().

◆ unsplit_eh_edges()

void unsplit_eh_edges ( void )
Wrapper around unsplit_all_eh that makes it usable everywhere.   

References CDI_DOMINATORS, CDI_POST_DOMINATORS, changed, delete_unreachable_blocks(), free_dominance_info(), maybe_remove_unreachable_handlers(), and unsplit_all_eh().

◆ verify_eh_dispatch_edge()

◆ verify_eh_edges()

DEBUG_FUNCTION bool verify_eh_edges ( gimple * stmt)
Disable warnings about missing quoting in GCC diagnostics for
the verification errors.  Their format strings don't follow GCC
diagnostic conventions but are only used for debugging.   
Verify that BB containing STMT as the last statement, has precisely the
edge that make_eh_edge would create.   

References cfun, error(), FOR_EACH_EDGE, get_eh_landing_pad_from_number(), ggc_alloc(), gimple_bb(), basic_block_def::index, label_to_block(), lookup_stmt_eh_lp(), NULL, eh_landing_pad_d::post_landing_pad, stmt_could_throw_p(), and basic_block_def::succs.

Referenced by gimple_verify_flow_info().

Variable Documentation

◆ eh_region_may_contain_throw_map

bitmap eh_region_may_contain_throw_map
Record whether an EH region contains something that can throw,
indexed by EH region number.   

Referenced by eh_region_may_contain_throw(), and note_eh_region_may_contain_throw().

◆ eh_seq

gimple_seq eh_seq
Second pass of EH node decomposition.  Actually transform the GIMPLE_TRY
nodes into a set of gotos, magic labels, and eh regions.
The eh region creation is straight-forward, but frobbing all the gotos
and such into shape isn't.   
The sequence into which we record all EH stuff.  This will be
placed at the end of the function when we're all done.   

Referenced by frob_into_branch_around(), honor_protect_cleanup_actions(), lower_catch(), lower_try_finally(), lower_try_finally_copy(), lower_try_finally_nofallthru(), lower_try_finally_onedest(), lower_try_finally_switch(), and replace_goto_queue().

◆ finally_tree

hash_table<finally_tree_hasher>* finally_tree
Note that this table is *not* marked GTY.  It is short-lived.   

Referenced by outside_finally_tree(), and record_in_finally_tree().