diff options
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/doc/generic.texi | 5 | ||||
-rw-r--r-- | gcc/except.c | 12 | ||||
-rw-r--r-- | gcc/expr.c | 1 | ||||
-rw-r--r-- | gcc/gimple-pretty-print.c | 20 | ||||
-rw-r--r-- | gcc/gimplify.c | 18 | ||||
-rw-r--r-- | gcc/tree-dump.c | 1 | ||||
-rw-r--r-- | gcc/tree-pretty-print.c | 28 | ||||
-rw-r--r-- | gcc/tree.c | 3 | ||||
-rw-r--r-- | gcc/tree.def | 9 |
10 files changed, 99 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19ab956..41b8b14 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index 67f7ad5..8901d5f 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -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 diff --git a/gcc/except.c b/gcc/except.c index edaeeb4..29f3339 100644 --- a/gcc/except.c +++ b/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 (); diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 45e7260..ce339ee 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -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); } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9e5e423..a3792d1 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -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 diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 58cb1ee..51c0965 100644 --- a/gcc/tree-dump.c +++ b/gcc/tree-dump.c @@ -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; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index dacda7b..742c284 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -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); diff --git a/gcc/tree.def b/gcc/tree.def index 10a14fc..d2e6938 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -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. */ |