On Thu, Jul 4, 2019 at 10:19 AM Alexandre Oliva <ol...@adacore.com> wrote:
>
> On Jul  1, 2019, Richard Biener <richard.guent...@gmail.com> wrote:
>
> > On Fri, Jun 28, 2019 at 5:21 AM Alexandre Oliva <ol...@adacore.com> wrote:
> >>
> >> On Jun 27, 2019, Richard Biener <richard.guent...@gmail.com> wrote:
> >>
> >> > On Thu, Jun 27, 2019 at 10:18 AM Alexandre Oliva <ol...@adacore.com> 
> >> > wrote:
> >>
> >> >> @@ -909,6 +909,13 @@ DEFTREECODE (TRY_CATCH_EXPR, "try_catch_expr", 
> >> >> tcc_statement, 2)
> >> >> 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)
> >> >> +
> >> >> +/* 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 is used as a cleanup, otherwise the second operand is
> >> >> +   used.  */
> >> >> +DEFTREECODE (EH_ELSE, "eh_else", tcc_statement, 2)
> >>
> >> > It's a bit weird that this is a tcc_statement as opposed to 
> >> > tcc_expression,
>
> >> Erhm...  What's weird about it?  It is not something that belongs in an
> >> arbitrary expr, it's a lot more like a top-level statement, like
> >> try_finally, having side effects but no useful value.
>
> > It's weird because it appears in a TRY_FINALLY statement operand.
>
> The other operand could be a nested TRY_FINALLY, but that doesn't make
> TRY_FINALLY a tcc_expression.
>
> > But I guess the line between statements and expressions in GENERIC
> > is muddy...
>
> My understanding of the general rule is that tcc_expressions have
> values, whereas tcc_statements don't.

Oh, that makes sense indeed.

> >> > also I'd have called it EH_ELSE_EXPR for clarity.
>
> >> Now *that* would be weird IMHO.  No offense intended, but I'd have
> >> dropped the _EXPR from TRY_FINALLY_EXPR to make it match the
> >> "try_finally" string.
>
> > OK, let me say for consistency then ...
>
> Ok, I like that one ;-) I've adjusted the "try_finally" string, and
> changed EH_ELSE to EH_ELSE_EXPR all over (but not in GIMPLE_EH_ELSE).
>
> I've also changed the way TRY_FINALLY_EXPR/EH_ELSE_EXPR are output in
> generic and gimple dumps, using the notation try/finally/else (this is
> the notation I started using in my unfinished gimplefe attempt, to avoid
> adding more keywords; more in another message).  I've retained the
> ability to dump GIMPLE_EH_EXPR separately, because I'm not entirely sure
> it could never be separated from the enclosing TRY_FINALLY_EXPR.
>
>
> 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.
>
> Regstrapped on x86_64-linux-gnu.  Ok to install?

OK.

Thanks,
Richard.

>
>
> 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.
> ---
>  gcc/doc/generic.texi      |    5 +++++
>  gcc/except.c              |   12 ++++++------
>  gcc/expr.c                |    1 +
>  gcc/gimple-pretty-print.c |   20 +++++++++++++++++++-
>  gcc/gimplify.c            |   18 +++++++++++++++++-
>  gcc/tree-dump.c           |    1 +
>  gcc/tree-pretty-print.c   |   28 +++++++++++++++++++++++++---
>  gcc/tree.c                |    3 +++
>  gcc/tree.def              |    9 ++++++++-
>  9 files changed, 85 insertions(+), 12 deletions(-)
>
> diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
> index 67f7ad53af6b..8901d5f357e2 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 edaeeb4cfd1b..29f333912d15 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.
> diff --git a/gcc/expr.c b/gcc/expr.c
> index 4acf250dd3ce..c922aaa45b9b 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -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 0ccbd6c63527..ea845492b0be 100644
> --- a/gcc/gimple-pretty-print.c
> +++ b/gcc/gimple-pretty-print.c
> @@ -1228,6 +1228,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);
> @@ -1241,12 +1243,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 9e5e42309412..a3792d16742e 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 58cb1ee5a729..51c0965861f8 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 dacda7bd0534..742c2840cd53 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;
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 76d94c6578a5..563af6fbdda6 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -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 10a14fc23b0c..d2e693892cd6 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.  */
>
>
> --
> Alexandre Oliva, freedom fighter  he/him   https://FSFLA.org/blogs/lxo
> Be the change, be Free!                 FSF Latin America board member
> GNU Toolchain Engineer                        Free Software Evangelist
> Hay que enGNUrecerse, pero sin perder la terGNUra jamás - Che GNUevara

Reply via email to