/* Expands front end tree to back end RTL for GCC
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
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
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
/* This file handles the generation of rtl code from tree structure
above the level of expressions, using subroutines in exp*.c and emit-rtl.c.
#include "optabs.h"
#include "target.h"
#include "regs.h"
+#include "alloc-pool.h"
\f
/* Functions and data structures for expanding case statements. */
For very small, suitable switch statements, we can generate a series
of simple bit test and branches instead. */
-struct case_node GTY(())
+struct case_node
{
struct case_node *left; /* Left son in binary tree */
struct case_node *right; /* Right son in binary tree; also node chain */
static int node_is_bounded (case_node_ptr, tree);
static void emit_case_nodes (rtx, case_node_ptr, rtx, tree);
static struct case_node *add_case_node (struct case_node *, tree,
- tree, tree, tree);
+ tree, tree, tree, alloc_pool);
\f
/* Return the rtx-label that corresponds to a LABEL_DECL,
insn is volatile; don't optimize it. */
static void
-expand_asm (tree string, int vol)
+expand_asm_loc (tree string, int vol, location_t locus)
{
rtx body;
if (TREE_CODE (string) == ADDR_EXPR)
string = TREE_OPERAND (string, 0);
- body = gen_rtx_ASM_INPUT (VOIDmode,
- ggc_strdup (TREE_STRING_POINTER (string)));
+ body = gen_rtx_ASM_INPUT_loc (VOIDmode,
+ ggc_strdup (TREE_STRING_POINTER (string)),
+ locus);
MEM_VOLATILE_P (body) = vol;
&& REGNO (DECL_RTL (decl)) < FIRST_PSEUDO_REGISTER)
{
rtx reg = DECL_RTL (decl);
- unsigned int regno;
-
- for (regno = REGNO (reg);
- regno < (REGNO (reg)
- + hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]);
- regno++)
- if (TEST_HARD_REG_BIT (*regs, regno))
- return decl;
+
+ if (overlaps_hard_reg_set_p (*regs, GET_MODE (reg), REGNO (reg)))
+ return decl;
}
walk_subtrees = 0;
}
if (real_output_rtx[i])
emit_move_insn (real_output_rtx[i], output_rtx[i]);
+ cfun->has_asm_statement = 1;
free_temp_slots ();
}
if (ASM_INPUT_P (exp))
{
- expand_asm (ASM_STRING (exp), ASM_VOLATILE_P (exp));
+ expand_asm_loc (ASM_STRING (exp), ASM_VOLATILE_P (exp), input_location);
return;
}
{
if (o[i] != TREE_VALUE (tail))
{
- expand_assignment (o[i], TREE_VALUE (tail));
+ expand_assignment (o[i], TREE_VALUE (tail), false);
free_temp_slots ();
/* Restore the original value so that it's correct the next
rtx value;
tree type;
- value = expand_expr (exp, const0_rtx, VOIDmode, 0);
+ value = expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
if (GIMPLE_TUPLE_P (exp))
type = void_type_node;
else
(potential) location of the expression. */
int
-warn_if_unused_value (tree exp, location_t locus)
+warn_if_unused_value (const_tree exp, location_t locus)
{
restart:
if (TREE_USED (exp) || TREE_NO_WARNING (exp))
return 0;
warn:
- warning (0, "%Hvalue computed is not used", &locus);
+ warning (OPT_Wunused_value, "%Hvalue computed is not used", &locus);
return 1;
}
}
tree nt = build_qualified_type (ot, TYPE_QUALS (ot) | TYPE_QUAL_CONST);
val = assign_temp (nt, 0, 0, 1);
- val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
+ val = expand_expr (retval_rhs, val, GET_MODE (val), EXPAND_NORMAL);
val = force_not_mem (val);
/* Return the calculated value. */
expand_value_return (val);
else
{
/* No hard reg used; calculate value into hard return reg. */
- expand_expr (retval, const0_rtx, VOIDmode, 0);
+ expand_expr (retval, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_value_return (result_rtl);
}
}
*that* node in turn will point to the relevant FUNCTION_DECL node. */
int
-is_body_block (tree stmt)
+is_body_block (const_tree stmt)
{
if (lang_hooks.no_body_blocks)
return 0;
emit_insn (gen_nonlocal_goto_receiver ());
#endif
- /* @@@ This is a kludge. Not all machine descriptions define a blockage
- insn, but we must not allow the code we just generated to be reordered
- by scheduling. Specifically, the update of the frame pointer must
- happen immediately, not later. So emit an ASM_INPUT to act as blockage
- insn. */
- emit_insn (gen_rtx_ASM_INPUT (VOIDmode, ""));
+ /* We must not allow the code we just generated to be reordered by
+ scheduling. Specifically, the update of the frame pointer must
+ happen immediately, not later. */
+ emit_insn (gen_blockage ());
}
\f
/* Generate RTL for the automatic variable declaration DECL.
/* Note if the object is a user variable. */
if (!DECL_ARTIFICIAL (decl))
- {
mark_user_reg (DECL_RTL (decl));
- /* Trust user variables which have a pointer type to really
- be pointers. Do not trust compiler generated temporaries
- as our type system is totally busted as it relates to
- pointer arithmetic which translates into lots of compiler
- generated objects with pointer types, but which are not really
- pointers. */
- if (POINTER_TYPE_P (type))
- mark_reg_pointer (DECL_RTL (decl),
- TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
- }
+ if (POINTER_TYPE_P (type))
+ mark_reg_pointer (DECL_RTL (decl),
+ TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
}
else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
void
expand_stack_restore (tree var)
{
- rtx sa = DECL_RTL (var);
+ rtx sa = expand_normal (var);
emit_stack_restore (SAVE_BLOCK, sa, NULL_RTX);
}
static struct case_node *
add_case_node (struct case_node *head, tree type, tree low, tree high,
- tree label)
+ tree label, alloc_pool case_node_pool)
{
tree min_value, max_value;
struct case_node *r;
/* Add this label to the chain. Make sure to drop overflow flags. */
- r = ggc_alloc (sizeof (struct case_node));
+ r = (struct case_node *) pool_alloc (case_node_pool);
r->low = build_int_cst_wide (TREE_TYPE (low), TREE_INT_CST_LOW (low),
TREE_INT_CST_HIGH (low));
r->high = build_int_cst_wide (TREE_TYPE (high), TREE_INT_CST_LOW (high),
/* By default, enable case bit tests on targets with ashlsi3. */
#ifndef CASE_USE_BIT_TESTS
-#define CASE_USE_BIT_TESTS (ashl_optab->handlers[word_mode].insn_code \
+#define CASE_USE_BIT_TESTS (optab_handler (ashl_optab, word_mode)->insn_code \
!= CODE_FOR_nothing)
#endif
rtx table_label;
int ncases;
rtx *labelvec;
- int i, fail;
+ int i;
rtx before_case, end, lab;
tree vec = SWITCH_LABELS (exp);
/* Label to jump to if no case matches. */
tree default_label_decl;
+ alloc_pool case_node_pool = create_alloc_pool ("struct case_node pool",
+ sizeof (struct case_node),
+ 100);
+
/* The switch body is lowered in gimplify.c, we should never have
switches with a non-NULL SWITCH_BODY here. */
gcc_assert (!SWITCH_BODY (exp));
high = CASE_HIGH (elt);
/* Discard empty ranges. */
- if (high && INT_CST_LT (high, low))
+ if (high && tree_int_cst_lt (high, low))
continue;
case_list = add_case_node (case_list, index_type, low, high,
- CASE_LABEL (elt));
+ CASE_LABEL (elt), case_node_pool);
}
}
else
{
- if (INT_CST_LT (n->low, minval))
+ if (tree_int_cst_lt (n->low, minval))
minval = n->low;
- if (INT_CST_LT (maxval, n->high))
+ if (tree_int_cst_lt (maxval, n->high))
maxval = n->high;
}
/* A range counts double, since it requires two compares. */
if (count == 0)
{
emit_jump (default_label);
+ free_alloc_pool (case_node_pool);
return;
}
before_case = NEXT_INSN (before_case);
end = get_last_insn ();
- fail = squeeze_notes (&before_case, &end);
- gcc_assert (!fail);
reorder_insns (before_case, end, start);
}
free_temp_slots ();
+ free_alloc_pool (case_node_pool);
}
/* Generate code to jump to LABEL if OP0 and OP1 are equal in mode MODE. */
for (n = node; n; n = n->right)
{
- if ((INT_CST_LT (n->low, min_ascii)) || INT_CST_LT (max_ascii, n->high))
+ if (tree_int_cst_lt (n->low, min_ascii)
+ || tree_int_cst_lt (max_ascii, n->high))
return 0;
for (i = (HOST_WIDE_INT) TREE_INT_CST_LOW (n->low);