This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [tree-ssa] COND_EXPR lowering preview
Hello,
here is the separate COND_EXPR lowering pass (it requieres
http://gcc.gnu.org/ml/gcc-patches/2003-08/msg01855.html to work).
Zdenek
/* Tree lowering pass. Lowers GIMPLE into unstructured form.
Copyright (C) 2003 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "errors.h"
#include "varray.h"
#include "tree-simple.h"
#include "tree-inline.h"
#include "diagnostic.h"
#include "langhooks.h"
#include "langhooks-def.h"
#include "tree-flow.h"
#include "timevar.h"
#include "except.h"
#include "hashtab.h"
#include "flags.h"
#include "real.h"
static void lower_stmt (tree_stmt_iterator *);
static void lower_bind_expr (tree_stmt_iterator *);
static void lower_loop_expr (tree_stmt_iterator *);
static void lower_cond_expr (tree_stmt_iterator *);
static void lower_switch_expr (tree_stmt_iterator *);
static void lower_try_finally_expr (tree_stmt_iterator *);
static void lower_try_catch_expr (tree_stmt_iterator *);
static void lower_eh_filter_expr (tree_stmt_iterator *);
static void lower_catch_expr (tree_stmt_iterator *);
/* Lowers the EXPR. Unlike gimplification the statements are not relowered
when they are changed -- if this has to be done, the lowering routine must
do it explicitly. */
void
lower_expr (tree *expr)
{
tree_stmt_iterator tsi;
for (tsi = tsi_start (expr); !tsi_end_p (tsi); tsi_next (&tsi))
lower_stmt (&tsi);
}
/* Lowers statement TSI. */
static void
lower_stmt (tree_stmt_iterator *tsi)
{
switch (TREE_CODE (tsi_stmt (*tsi)))
{
case BIND_EXPR:
lower_bind_expr (tsi);
break;
case COMPOUND_EXPR:
abort ();
case NOP_EXPR:
case ASM_EXPR:
case RETURN_EXPR:
case MODIFY_EXPR:
case CALL_EXPR:
case GOTO_EXPR:
case LABEL_EXPR:
case CASE_LABEL_EXPR:
case VA_ARG_EXPR:
break;
case LOOP_EXPR:
lower_loop_expr (tsi);
break;
case COND_EXPR:
lower_cond_expr (tsi);
break;
case SWITCH_EXPR:
lower_switch_expr (tsi);
break;
case TRY_FINALLY_EXPR:
lower_try_finally_expr (tsi);
break;
case TRY_CATCH_EXPR:
lower_try_catch_expr (tsi);
break;
case EH_FILTER_EXPR:
lower_eh_filter_expr (tsi);
break;
case CATCH_EXPR:
lower_catch_expr (tsi);
break;
default:
print_node_brief (stderr, "", tsi_stmt (*tsi), 0);
abort ();
}
}
/* Lowers a bind_expr TSI. */
static void
lower_bind_expr (tree_stmt_iterator *tsi)
{
lower_expr (&BIND_EXPR_BODY (tsi_stmt (*tsi)));
}
/* Lowers a loop_expr TSI. */
static void
lower_loop_expr (tree_stmt_iterator *tsi)
{
lower_expr (&LOOP_EXPR_BODY (tsi_stmt (*tsi)));
}
/* Lowers a cond_expr TSI. */
static void
lower_cond_expr (tree_stmt_iterator *tsi)
{
tree stmt = tsi_stmt (*tsi);
bool then_is_goto, else_is_goto;
tree then_branch, else_branch, then_label, else_label, end_label;
lower_expr (&COND_EXPR_THEN (stmt));
lower_expr (&COND_EXPR_ELSE (stmt));
/* Find out whether the branches are ordinary local gotos. */
then_branch = COND_EXPR_THEN (stmt);
else_branch = COND_EXPR_ELSE (stmt);
then_is_goto = (TREE_CODE (then_branch) == GOTO_EXPR
&& TREE_CODE (GOTO_DESTINATION (then_branch)) == LABEL_DECL
&& ! NONLOCAL_LABEL (GOTO_DESTINATION (then_branch))
&& (decl_function_context (GOTO_DESTINATION (then_branch))
== current_function_decl));
else_is_goto = (TREE_CODE (else_branch) == GOTO_EXPR
&& TREE_CODE (GOTO_DESTINATION (else_branch)) == LABEL_DECL
&& ! NONLOCAL_LABEL (GOTO_DESTINATION (else_branch))
&& (decl_function_context (GOTO_DESTINATION (else_branch))
== current_function_decl));
if (then_is_goto && else_is_goto)
return;
/* Replace the cond_expr with explicit gotos. */
if (!then_is_goto)
{
then_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
COND_EXPR_THEN (stmt) = build_and_jump (&LABEL_EXPR_LABEL (then_label));
}
else
then_label = NULL_TREE;
if (!else_is_goto)
{
else_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
COND_EXPR_ELSE (stmt) = build_and_jump (&LABEL_EXPR_LABEL (else_label));
}
else
else_label = NULL_TREE;
end_label = NULL_TREE;
if (then_label)
{
tsi_link_after (tsi, then_label, TSI_CHAIN_END);
tsi_link_after (tsi, then_branch, TSI_CHAIN_END);
if (else_label)
{
end_label = build1 (LABEL_EXPR, void_type_node, NULL_TREE);
tsi_link_after (tsi, build_and_jump (&LABEL_EXPR_LABEL (end_label)),
TSI_CHAIN_END);
}
}
if (else_label)
{
tsi_link_after (tsi, else_label, TSI_CHAIN_END);
tsi_link_after (tsi, else_branch, TSI_CHAIN_END);
}
if (end_label)
tsi_link_after (tsi, end_label, TSI_CHAIN_END);
}
/* Lowers a switch_expr TSI. */
static void
lower_switch_expr (tree_stmt_iterator *tsi)
{
lower_expr (&SWITCH_BODY (tsi_stmt (*tsi)));
}
/* Lowers a try_finally_expr TSI. */
static void
lower_try_finally_expr (tree_stmt_iterator *tsi)
{
lower_expr (&TREE_OPERAND (tsi_stmt (*tsi), 0));
lower_expr (&TREE_OPERAND (tsi_stmt (*tsi), 1));
}
/* Lowers a try_catch_expr TSI. */
static void
lower_try_catch_expr (tree_stmt_iterator *tsi)
{
lower_expr (&TREE_OPERAND (tsi_stmt (*tsi), 0));
lower_expr (&TREE_OPERAND (tsi_stmt (*tsi), 1));
}
/* Lowers an eh_filter_expr TSI. */
static void
lower_eh_filter_expr (tree_stmt_iterator *tsi)
{
lower_expr (&EH_FILTER_FAILURE (tsi_stmt (*tsi)));
}
static void
lower_catch_expr (tree_stmt_iterator *tsi)
{
lower_expr (&CATCH_BODY (tsi_stmt (*tsi)));
}