X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fstmt.c;h=f1be5e01aff30f9611dd640cea656e2b1b44525b;hb=f5ef996258725dd451733c21e2bba88c87019646;hp=be3e876f589b6cad79f03b152973157e2b5204b4;hpb=1edb3690ac67a2f68d5b7a1507d3d2159b9ae219;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/stmt.c b/gcc/stmt.c index be3e876f589..f1be5e01aff 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1,13 +1,13 @@ /* 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 @@ -16,9 +16,8 @@ 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, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* 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. @@ -50,6 +49,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "optabs.h" #include "target.h" #include "regs.h" +#include "alloc-pool.h" /* Functions and data structures for expanding case statements. */ @@ -80,7 +80,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 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 */ @@ -122,7 +122,7 @@ static int node_has_high_bound (case_node_ptr, tree); 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); /* Return the rtx-label that corresponds to a LABEL_DECL, @@ -260,15 +260,16 @@ n_occurrences (int c, const char *s) 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; @@ -574,14 +575,9 @@ decl_overlaps_hard_reg_set_p (tree *declp, int *walk_subtrees ATTRIBUTE_UNUSED, && 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; } @@ -693,7 +689,11 @@ expand_asm_operands (tree string, tree outputs, tree inputs, CLEAR_HARD_REG_SET (clobbered_regs); for (tail = clobbers; tail; tail = TREE_CHAIN (tail)) { - const char *regname = TREE_STRING_POINTER (TREE_VALUE (tail)); + const char *regname; + + if (TREE_VALUE (tail) == error_mark_node) + return; + regname = TREE_STRING_POINTER (TREE_VALUE (tail)); i = decode_reg_name (regname); if (i >= 0 || i == -4) @@ -881,9 +881,13 @@ expand_asm_operands (tree string, tree outputs, tree inputs, val = TREE_VALUE (tail); type = TREE_TYPE (val); + /* EXPAND_INITIALIZER will not generate code for valid initializer + constants, but will still generate code for other types of operand. + This is the behavior we want for constant constraints. */ op = expand_expr (val, NULL_RTX, VOIDmode, - (allows_mem && !allows_reg - ? EXPAND_MEMORY : EXPAND_NORMAL)); + allows_reg ? EXPAND_NORMAL + : allows_mem ? EXPAND_MEMORY + : EXPAND_INITIALIZER); /* Never pass a CONCAT to an ASM. */ if (GET_CODE (op) == CONCAT) @@ -1074,6 +1078,7 @@ expand_asm_operands (tree string, tree outputs, tree inputs, if (real_output_rtx[i]) emit_move_insn (real_output_rtx[i], output_rtx[i]); + cfun->has_asm_statement = 1; free_temp_slots (); } @@ -1086,7 +1091,7 @@ expand_asm_expr (tree exp) 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; } @@ -1110,7 +1115,7 @@ expand_asm_expr (tree exp) { 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 @@ -1353,7 +1358,10 @@ expand_expr_stmt (tree exp) 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 type = TREE_TYPE (exp); /* If all we do is reference a volatile value in memory, @@ -1385,7 +1393,7 @@ expand_expr_stmt (tree exp) (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)) @@ -1407,12 +1415,14 @@ warn_if_unused_value (tree exp, location_t locus) case PREDECREMENT_EXPR: case POSTDECREMENT_EXPR: case MODIFY_EXPR: + case GIMPLE_MODIFY_STMT: case INIT_EXPR: case TARGET_EXPR: case CALL_EXPR: case TRY_CATCH_EXPR: case WITH_CLEANUP_EXPR: case EXIT_EXPR: + case VA_ARG_EXPR: return 0; case BIND_EXPR: @@ -1465,11 +1475,11 @@ warn_if_unused_value (tree exp, location_t locus) /* If this is an expression which has no operands, there is no value to be unused. There are no such language-independent codes, but front ends may define such. */ - if (EXPRESSION_CLASS_P (exp) && TREE_CODE_LENGTH (TREE_CODE (exp)) == 0) + if (EXPRESSION_CLASS_P (exp) && TREE_OPERAND_LENGTH (exp) == 0) return 0; warn: - warning (0, "%Hvalue computed is not used", &locus); + warning (OPT_Wunused_value, "%Hvalue computed is not used", &locus); return 1; } } @@ -1574,10 +1584,10 @@ expand_return (tree retval) expand_null_return (); return; } - else if ((TREE_CODE (retval) == MODIFY_EXPR + else if ((TREE_CODE (retval) == GIMPLE_MODIFY_STMT || TREE_CODE (retval) == INIT_EXPR) - && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL) - retval_rhs = TREE_OPERAND (retval, 1); + && TREE_CODE (GENERIC_TREE_OPERAND (retval, 0)) == RESULT_DECL) + retval_rhs = GENERIC_TREE_OPERAND (retval, 1); else retval_rhs = retval; @@ -1596,7 +1606,7 @@ expand_return (tree retval) (and in expand_call). */ else if (retval_rhs != 0 - && TYPE_MODE (TREE_TYPE (retval_rhs)) == BLKmode + && TYPE_MODE (GENERIC_TREE_TYPE (retval_rhs)) == BLKmode && REG_P (result_rtl)) { int i; @@ -1714,7 +1724,7 @@ expand_return (tree retval) 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); @@ -1722,7 +1732,7 @@ expand_return (tree retval) 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); } } @@ -1738,7 +1748,7 @@ expand_return (tree retval) *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; @@ -1821,12 +1831,10 @@ expand_nl_goto_receiver (void) 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 ()); } /* Generate RTL for the automatic variable declaration DECL. @@ -1891,19 +1899,11 @@ expand_decl (tree 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 @@ -2068,7 +2068,7 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED, 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; @@ -2120,7 +2120,7 @@ add_case_node (struct case_node *head, tree type, tree low, tree high, /* 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), @@ -2136,7 +2136,7 @@ add_case_node (struct case_node *head, tree type, tree low, tree 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 @@ -2303,7 +2303,7 @@ expand_case (tree exp) rtx table_label; int ncases; rtx *labelvec; - int i, fail; + int i; rtx before_case, end, lab; tree vec = SWITCH_LABELS (exp); @@ -2323,6 +2323,10 @@ expand_case (tree 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)); @@ -2360,7 +2364,7 @@ expand_case (tree exp) continue; case_list = add_case_node (case_list, index_type, low, high, - CASE_LABEL (elt)); + CASE_LABEL (elt), case_node_pool); } @@ -2411,6 +2415,7 @@ expand_case (tree exp) if (count == 0) { emit_jump (default_label); + free_alloc_pool (case_node_pool); return; } @@ -2577,12 +2582,11 @@ expand_case (tree exp) 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. */