This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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)));
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]