From patchwork Thu Jun 27 07:34:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Oliva X-Patchwork-Id: 1123185 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-503851-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=adacore.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="MLVdOVTM"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45ZCT62MpWz9sLt for ; Thu, 27 Jun 2019 18:18:17 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=DOoaE7+Z7nkBerlC SkMSlYEHNuMgYkSBt/tEr9FQl18xbO/h5emoPvpmG4vTP81WkdVneKtBfS1uYXI+ uGuXOAhqdQ26FfMQMB+DP6rND/XVeeiXiKZhQ2lxSuxKzqcEw/x5wAPTv1Crgtg2 6aZ6+i62IAe4aJSGwJxiY2c6agQ= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=iTiZrOVECg3/IWjy0XBznO N3wo4=; b=MLVdOVTMMXTd97MmcCUoYPOoQhwocSvY1YpAdrPF4FpOnyVezoHzwO C8D1mJFyfHgUhsll78mL/+CTckoHKceMyo8vs6SmmyQzjkiu6gB7sIw31URrqaZQ SEKQ1Y57sALnsIgF2MILeMQ3xIbI/C5rSUoxGc47H7XadAaXKbNbM= Received: (qmail 90880 invoked by alias); 27 Jun 2019 08:17:59 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 90847 invoked by uid 89); 27 Jun 2019 08:17:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=hay, 1-1, gimplify.c, gimplifyc X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 27 Jun 2019 08:17:56 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 56B2256083; Thu, 27 Jun 2019 04:17:54 -0400 (EDT) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 8Z+RaMgErnij; Thu, 27 Jun 2019 04:17:54 -0400 (EDT) Received: from free.home (tron.gnat.com [IPv6:2620:20:4000:0:46a8:42ff:fe0e:e294]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by rock.gnat.com (Postfix) with ESMTPS id 11F55116FB5; Thu, 27 Jun 2019 04:17:53 -0400 (EDT) Received: from livre (livre.home [172.31.160.2]) by free.home (8.15.2/8.15.2) with ESMTPS id x5R7Y9sK528207 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 27 Jun 2019 04:34:09 -0300 From: Alexandre Oliva To: gcc-patches@gcc.gnu.org Subject: introduce EH_ELSE tree and gimplifier Date: Thu, 27 Jun 2019 04:34:09 -0300 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) MIME-Version: 1.0 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 tree, and logic to dump it and to gimplify it. Regstrapped on x86_64-linux-gnu. Ok to install? for gcc/ChangeLog * doc/generic.texi (Cleanups): Document EH_ELSE. * 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): Introduce. --- gcc/doc/generic.texi | 5 +++++ gcc/except.c | 12 ++++++------ gcc/expr.c | 1 + gcc/gimplify.c | 18 +++++++++++++++++- gcc/tree-dump.c | 1 + gcc/tree-pretty-print.c | 11 +++++++++++ gcc/tree.c | 3 +++ gcc/tree.def | 7 +++++++ 8 files changed, 51 insertions(+), 7 deletions(-) diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index 67f7ad53af6b..1d0e3cfec1d6 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} 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..76cd099749f3 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, 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 c78bc74c0d9f..70fb721a9621 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: /* Lowered by tree-eh.c. */ gcc_unreachable (); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 0b25e7100cde..de4cb66e2b65 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -13074,7 +13074,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) + { + 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)) { @@ -13632,6 +13647,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 && code != OACC_PARALLEL && code != OACC_KERNELS && code != OACC_DATA diff --git a/gcc/tree-dump.c b/gcc/tree-dump.c index 58cb1ee5a729..f7c89c3374ff 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: 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 329cc6fceeb2..663616d0a0f3 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -2823,6 +2823,17 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, is_expr = false; break; + case EH_ELSE: + pp_string (pp, "<>:"); + newline_and_indent (pp, spc+2); + dump_generic_node (pp, TREE_OPERAND (node, 0), spc+2, flags, true); + newline_and_indent (pp, spc); + pp_string (pp, "<>:"); + newline_and_indent (pp, spc+2); + dump_generic_node (pp, TREE_OPERAND (node, 1), spc+2, flags, true); + is_expr = false; + break; + case CATCH_EXPR: pp_string (pp, "catch ("); dump_generic_node (pp, CATCH_TYPES (node), spc+2, flags, false); diff --git a/gcc/tree.c b/gcc/tree.c index c97facd7ce50..8f6f6c43b6ce 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -13408,6 +13408,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: + 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..9cf53964f8eb 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -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) /* These types of expressions have no useful value, and always have side effects. */