mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 09:50:33 +08:00
introduce EH_ELSE_EXPR tree and gimplifier
I found GIMPLE_EH_ELSE offered exactly the semantics I needed for some Ada changes yet to be contributed, but GIMPLE_EH_ELSE was only built by GIMPLE passes, and I needed to build earlier something that eventually became GIMPLE_EH_ELSE. This patch does that, introducing an EH_ELSE_EXPR tree, and logic to dump it and to gimplify it. for gcc/ChangeLog * doc/generic.texi (Cleanups): Document EH_ELSE_EXPR. * except.c: Likewise. * expr.c (expand_expr_real_1): Reject it. * gimplify.c (gimplify_expr): Gimplify it, within TRY_FINALLY_EXPR. * tree-dump.c (dequeue_and_dump): Dump it. * tree-pretty-print.c (dump_generic_node): Likewise. * tree.c (block_may_fallthru): Handle it. * tree.def (EH_ELSE_EXPR): Introduce it. * gimple-pretty-print.c (dump_gimple_try): Dump TRY_FINALLY with GIMPLE_EH_ELSE as try/finally/else. From-SVN: r273084
This commit is contained in:
parent
e57c896e86
commit
ebebc928d8
@ -1,3 +1,17 @@
|
||||
2019-07-04 Alexandre Oliva <oliva@adacore.com>
|
||||
|
||||
* doc/generic.texi (Cleanups): Document EH_ELSE_EXPR.
|
||||
* except.c: Likewise.
|
||||
* expr.c (expand_expr_real_1): Reject it.
|
||||
* gimplify.c (gimplify_expr): Gimplify it, within
|
||||
TRY_FINALLY_EXPR.
|
||||
* tree-dump.c (dequeue_and_dump): Dump it.
|
||||
* tree-pretty-print.c (dump_generic_node): Likewise.
|
||||
* tree.c (block_may_fallthru): Handle it.
|
||||
* tree.def (EH_ELSE_EXPR): Introduce it.
|
||||
* gimple-pretty-print.c (dump_gimple_try): Dump TRY_FINALLY
|
||||
with GIMPLE_EH_ELSE as try/finally/else.
|
||||
|
||||
2019-07-04 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR ipa/91062
|
||||
|
@ -2180,6 +2180,11 @@ After the second sequence is executed, if it completes normally by
|
||||
falling off the end, execution continues wherever the first sequence
|
||||
would have continued, by falling off the end, or doing a goto, etc.
|
||||
|
||||
If the second sequence is an @code{EH_ELSE_EXPR} selector, then the
|
||||
sequence in its first operand is used when the first sequence completes
|
||||
normally, and that in its second operand is used for exceptional
|
||||
cleanups, i.e., when an exception propagates out of the first sequence.
|
||||
|
||||
@code{TRY_FINALLY_EXPR} complicates the flow graph, since the cleanup
|
||||
needs to appear on every edge out of the controlled block; this
|
||||
reduces the freedom to move code across these edges. Therefore, the
|
||||
|
12
gcc/except.c
12
gcc/except.c
@ -27,14 +27,14 @@ along with GCC; see the file COPYING3. If not see
|
||||
the compilation process:
|
||||
|
||||
In the beginning, in the front end, we have the GENERIC trees
|
||||
TRY_CATCH_EXPR, TRY_FINALLY_EXPR, WITH_CLEANUP_EXPR,
|
||||
TRY_CATCH_EXPR, TRY_FINALLY_EXPR, EH_ELSE_EXPR, WITH_CLEANUP_EXPR,
|
||||
CLEANUP_POINT_EXPR, CATCH_EXPR, and EH_FILTER_EXPR.
|
||||
|
||||
During initial gimplification (gimplify.c) these are lowered
|
||||
to the GIMPLE_TRY, GIMPLE_CATCH, and GIMPLE_EH_FILTER nodes.
|
||||
The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are converted
|
||||
into GIMPLE_TRY_FINALLY nodes; the others are a more direct 1-1
|
||||
conversion.
|
||||
During initial gimplification (gimplify.c) these are lowered to the
|
||||
GIMPLE_TRY, GIMPLE_CATCH, GIMPLE_EH_ELSE, and GIMPLE_EH_FILTER
|
||||
nodes. The WITH_CLEANUP_EXPR and CLEANUP_POINT_EXPR nodes are
|
||||
converted into GIMPLE_TRY_FINALLY nodes; the others are a more
|
||||
direct 1-1 conversion.
|
||||
|
||||
During pass_lower_eh (tree-eh.c) we record the nested structure
|
||||
of the TRY nodes in EH_REGION nodes in CFUN->EH->REGION_TREE.
|
||||
|
@ -11292,6 +11292,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
|
||||
case CATCH_EXPR:
|
||||
case EH_FILTER_EXPR:
|
||||
case TRY_FINALLY_EXPR:
|
||||
case EH_ELSE_EXPR:
|
||||
/* Lowered by tree-eh.c. */
|
||||
gcc_unreachable ();
|
||||
|
||||
|
@ -1232,6 +1232,8 @@ dump_gimple_try (pretty_printer *buffer, gtry *gs, int spc,
|
||||
newline_and_indent (buffer, spc + 2);
|
||||
pp_right_brace (buffer);
|
||||
|
||||
gimple_seq seq = gimple_try_cleanup (gs);
|
||||
|
||||
if (gimple_try_kind (gs) == GIMPLE_TRY_CATCH)
|
||||
{
|
||||
newline_and_indent (buffer, spc);
|
||||
@ -1245,12 +1247,28 @@ dump_gimple_try (pretty_printer *buffer, gtry *gs, int spc,
|
||||
pp_string (buffer, "finally");
|
||||
newline_and_indent (buffer, spc + 2);
|
||||
pp_left_brace (buffer);
|
||||
|
||||
if (seq && is_a <geh_else *> (gimple_seq_first_stmt (seq))
|
||||
&& gimple_seq_nondebug_singleton_p (seq))
|
||||
{
|
||||
geh_else *stmt = as_a <geh_else *> (gimple_seq_first_stmt (seq));
|
||||
seq = gimple_eh_else_n_body (stmt);
|
||||
pp_newline (buffer);
|
||||
dump_gimple_seq (buffer, seq, spc + 4, flags);
|
||||
newline_and_indent (buffer, spc + 2);
|
||||
pp_right_brace (buffer);
|
||||
seq = gimple_eh_else_e_body (stmt);
|
||||
newline_and_indent (buffer, spc);
|
||||
pp_string (buffer, "else");
|
||||
newline_and_indent (buffer, spc + 2);
|
||||
pp_left_brace (buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
pp_string (buffer, " <UNKNOWN GIMPLE_TRY> {");
|
||||
|
||||
pp_newline (buffer);
|
||||
dump_gimple_seq (buffer, gimple_try_cleanup (gs), spc + 4, flags);
|
||||
dump_gimple_seq (buffer, seq, spc + 4, flags);
|
||||
newline_and_indent (buffer, spc + 2);
|
||||
pp_right_brace (buffer);
|
||||
}
|
||||
|
@ -13079,7 +13079,22 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
input_location = UNKNOWN_LOCATION;
|
||||
eval = cleanup = NULL;
|
||||
gimplify_and_add (TREE_OPERAND (*expr_p, 0), &eval);
|
||||
gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
|
||||
if (TREE_CODE (*expr_p) == TRY_FINALLY_EXPR
|
||||
&& TREE_CODE (TREE_OPERAND (*expr_p, 1)) == EH_ELSE_EXPR)
|
||||
{
|
||||
gimple_seq n = NULL, e = NULL;
|
||||
gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
|
||||
0), &n);
|
||||
gimplify_and_add (TREE_OPERAND (TREE_OPERAND (*expr_p, 1),
|
||||
1), &e);
|
||||
if (!gimple_seq_empty_p (n) && !gimple_seq_empty_p (e))
|
||||
{
|
||||
geh_else *stmt = gimple_build_eh_else (n, e);
|
||||
gimple_seq_add_stmt (&cleanup, stmt);
|
||||
}
|
||||
}
|
||||
else
|
||||
gimplify_and_add (TREE_OPERAND (*expr_p, 1), &cleanup);
|
||||
/* Don't create bogus GIMPLE_TRY with empty cleanup. */
|
||||
if (gimple_seq_empty_p (cleanup))
|
||||
{
|
||||
@ -13637,6 +13652,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
|
||||
&& code != LOOP_EXPR
|
||||
&& code != SWITCH_EXPR
|
||||
&& code != TRY_FINALLY_EXPR
|
||||
&& code != EH_ELSE_EXPR
|
||||
&& code != OACC_PARALLEL
|
||||
&& code != OACC_KERNELS
|
||||
&& code != OACC_DATA
|
||||
|
@ -604,6 +604,7 @@ dequeue_and_dump (dump_info_p di)
|
||||
break;
|
||||
|
||||
case TRY_FINALLY_EXPR:
|
||||
case EH_ELSE_EXPR:
|
||||
dump_child ("op 0", TREE_OPERAND (t, 0));
|
||||
dump_child ("op 1", TREE_OPERAND (t, 1));
|
||||
break;
|
||||
|
@ -2815,12 +2815,34 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags,
|
||||
newline_and_indent (pp, spc+2);
|
||||
pp_right_brace (pp);
|
||||
newline_and_indent (pp, spc);
|
||||
pp_string (pp,
|
||||
(TREE_CODE (node) == TRY_CATCH_EXPR) ? "catch" : "finally");
|
||||
if (TREE_CODE (node) == TRY_CATCH_EXPR)
|
||||
{
|
||||
node = TREE_OPERAND (node, 1);
|
||||
pp_string (pp, "catch");
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (TREE_CODE (node) == TRY_FINALLY_EXPR);
|
||||
node = TREE_OPERAND (node, 1);
|
||||
pp_string (pp, "finally");
|
||||
if (TREE_CODE (node) == EH_ELSE_EXPR)
|
||||
{
|
||||
newline_and_indent (pp, spc+2);
|
||||
pp_left_brace (pp);
|
||||
newline_and_indent (pp, spc+4);
|
||||
dump_generic_node (pp, TREE_OPERAND (node, 0), spc+4,
|
||||
flags, true);
|
||||
newline_and_indent (pp, spc+2);
|
||||
pp_right_brace (pp);
|
||||
newline_and_indent (pp, spc);
|
||||
node = TREE_OPERAND (node, 1);
|
||||
pp_string (pp, "else");
|
||||
}
|
||||
}
|
||||
newline_and_indent (pp, spc+2);
|
||||
pp_left_brace (pp);
|
||||
newline_and_indent (pp, spc+4);
|
||||
dump_generic_node (pp, TREE_OPERAND (node, 1), spc+4, flags, true);
|
||||
dump_generic_node (pp, node, spc+4, flags, true);
|
||||
newline_and_indent (pp, spc+2);
|
||||
pp_right_brace (pp);
|
||||
is_expr = false;
|
||||
|
@ -13415,6 +13415,9 @@ block_may_fallthru (const_tree block)
|
||||
return (block_may_fallthru (TREE_OPERAND (stmt, 0))
|
||||
&& block_may_fallthru (TREE_OPERAND (stmt, 1)));
|
||||
|
||||
case EH_ELSE_EXPR:
|
||||
return block_may_fallthru (TREE_OPERAND (stmt, 0));
|
||||
|
||||
case MODIFY_EXPR:
|
||||
if (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)
|
||||
stmt = TREE_OPERAND (stmt, 1);
|
||||
|
@ -908,7 +908,14 @@ DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", tcc_statement, 2)
|
||||
/* Evaluate the first operand.
|
||||
The second operand is a cleanup expression which is evaluated
|
||||
on any exit (normal, exception, or jump out) from this expression. */
|
||||
DEFTREECODE (TRY_FINALLY_EXPR, "try_finally", tcc_statement, 2)
|
||||
DEFTREECODE (TRY_FINALLY_EXPR, "try_finally_expr", tcc_statement, 2)
|
||||
|
||||
/* Evaluate either the normal or the exceptional cleanup. This must
|
||||
only be present as the cleanup expression in a TRY_FINALLY_EXPR.
|
||||
If the TRY_FINALLY_EXPR completes normally, the first operand of
|
||||
EH_ELSE_EXPR is used as a cleanup, otherwise the second operand is
|
||||
used. */
|
||||
DEFTREECODE (EH_ELSE_EXPR, "eh_else_expr", tcc_statement, 2)
|
||||
|
||||
/* These types of expressions have no useful value,
|
||||
and always have side effects. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user