introduce EH_ELSE_EXPR tree and gimplifier
authorAlexandre Oliva <oliva@adacore.com>
Thu, 4 Jul 2019 15:00:00 +0000 (15:00 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Thu, 4 Jul 2019 15:00:00 +0000 (15:00 +0000)
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

gcc/ChangeLog
gcc/doc/generic.texi
gcc/except.c
gcc/expr.c
gcc/gimple-pretty-print.c
gcc/gimplify.c
gcc/tree-dump.c
gcc/tree-pretty-print.c
gcc/tree.c
gcc/tree.def

index 19ab956a98cf0a659a5e9c311b97ef5928b8f792..41b8b14400ae2f98f797daee397889bef7b309e3 100644 (file)
@@ -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
index 67f7ad53af6b98085b691a41206385980d52b247..8901d5f357e2cc98fea02f36a48639155e8f9ba4 100644 (file)
@@ -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
index edaeeb4cfd1b8f57e0ad75167302d4e6614e4a3f..29f333912d15ae6f7dd85342675c87f23e68278e 100644 (file)
@@ -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.
index 4acf250dd3ce0e5cf995cd2f3dfe32ce028d97a6..c922aaa45b9bc1aa2e5e6e319352616428683faf 100644 (file)
@@ -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 ();
 
index 45e7260e072c69af5d27a94319d244522cf034d2..ce339eeddac40806b3d2c7d5d6c4b5e3bf35b104 100644 (file)
@@ -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);
     }
index 9e5e4230941254de5eae4777eb9a4aa7ea692308..a3792d16742ecb2389229a07b341697bfa81736d 100644 (file)
@@ -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
index 58cb1ee5a72928a753275b404c8b80908191cf6f..51c0965861f81a720c23dfc0495a0b742e42f613 100644 (file)
@@ -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;
index dacda7bd0534627e0fef24dcc3bddb972fcd7cd1..742c2840cd530551af26fd4345317f22d7787aee 100644 (file)
@@ -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;
index 76d94c6578a5ed9216e72d275d7400815a47c21f..563af6fbdda66d92be47bc9a8efa3b5e0cb8e7c1 100644 (file)
@@ -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);
index 10a14fc23b0c19a6ef4e405c230fa68850bdf596..d2e693892cd6792a55e4b6dd1d1e1176d35c87be 100644 (file)
@@ -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)
 \f
 /* These types of expressions have no useful value,
    and always have side effects.  */