X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fexpr.c;h=7ecbccf633cac8484952a9148d3efb882a730d66;hb=7433d1d602d195414fa7c4766b953d05ac8cf371;hp=afd01acb4aa569f5140cd3fa5d8b75bc15d4f632;hpb=10fc867f364ae606d1373d9290cdaf2278011643;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/expr.c b/gcc/expr.c index afd01acb4aa..7ecbccf633c 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "timevar.h" #include "df.h" +#include "diagnostic.h" /* Decide whether a function's arguments should be processed from first to last or from last to first. @@ -343,7 +344,7 @@ init_expr_target (void) void init_expr (void) { - cfun->expr = ggc_alloc_cleared (sizeof (struct expr_status)); + memset (&rtl.expr, 0, sizeof (rtl.expr)); } /* Copy data from FROM to TO, where the machine modes are not the same. @@ -551,15 +552,15 @@ convert_move (rtx to, rtx from, int unsignedp) && ((code = can_extend_p (to_mode, word_mode, unsignedp)) != CODE_FOR_nothing)) { + rtx word_to = gen_reg_rtx (word_mode); if (REG_P (to)) { if (reg_overlap_mentioned_p (to, from)) from = force_reg (from_mode, from); emit_insn (gen_rtx_CLOBBER (VOIDmode, to)); } - convert_move (gen_lowpart (word_mode, to), from, unsignedp); - emit_unop_insn (code, to, - gen_lowpart (word_mode, to), equiv_code); + convert_move (word_to, from, unsignedp); + emit_unop_insn (code, to, word_to, equiv_code); return; } @@ -1776,8 +1777,25 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize) else if (CONSTANT_P (src) && GET_MODE (dst) != BLKmode && XVECLEN (dst, 0) > 1) tmps[i] = simplify_gen_subreg (mode, src, GET_MODE(dst), bytepos); - else if (CONSTANT_P (src) - || (REG_P (src) && GET_MODE (src) == mode)) + else if (CONSTANT_P (src)) + { + HOST_WIDE_INT len = (HOST_WIDE_INT) bytelen; + + if (len == ssize) + tmps[i] = src; + else + { + rtx first, second; + + gcc_assert (2 * len == ssize); + split_double (src, &first, &second); + if (i) + tmps[i] = second; + else + tmps[i] = first; + } + } + else if (REG_P (src) && GET_MODE (src) == mode) tmps[i] = src; else tmps[i] = extract_bit_field (src, bytelen * BITS_PER_UNIT, @@ -2098,6 +2116,7 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type) rtx src = NULL, dst = NULL; unsigned HOST_WIDE_INT bitsize = MIN (TYPE_ALIGN (type), BITS_PER_WORD); unsigned HOST_WIDE_INT bitpos, xbitpos, padding_correction = 0; + enum machine_mode copy_mode; if (tgtblk == 0) { @@ -2131,11 +2150,23 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type) padding_correction = (BITS_PER_WORD - ((bytes % UNITS_PER_WORD) * BITS_PER_UNIT)); - /* Copy the structure BITSIZE bites at a time. + /* Copy the structure BITSIZE bits at a time. If the target lives in + memory, take care of not reading/writing past its end by selecting + a copy mode suited to BITSIZE. This should always be possible given + how it is computed. We could probably emit more efficient code for machines which do not use strict alignment, but it doesn't seem worth the effort at the current time. */ + + copy_mode = word_mode; + if (MEM_P (tgtblk)) + { + enum machine_mode mem_mode = mode_for_size (bitsize, MODE_INT, 1); + if (mem_mode != BLKmode) + copy_mode = mem_mode; + } + for (bitpos = 0, xbitpos = padding_correction; bitpos < bytes * BITS_PER_UNIT; bitpos += bitsize, xbitpos += bitsize) @@ -2154,11 +2185,11 @@ copy_blkmode_from_reg (rtx tgtblk, rtx srcreg, tree type) dst = operand_subword (tgtblk, bitpos / BITS_PER_WORD, 1, BLKmode); /* Use xbitpos for the source extraction (right justified) and - xbitpos for the destination store (left justified). */ - store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, word_mode, + bitpos for the destination store (left justified). */ + store_bit_field (dst, bitsize, bitpos % BITS_PER_WORD, copy_mode, extract_bit_field (src, bitsize, xbitpos % BITS_PER_WORD, 1, - NULL_RTX, word_mode, word_mode)); + NULL_RTX, copy_mode, copy_mode)); } return tgtblk; @@ -3373,16 +3404,12 @@ emit_move_insn (rtx x, rtx y) /* If X or Y are memory references, verify that their addresses are valid for the machine. */ if (MEM_P (x) - && ((! memory_address_p (GET_MODE (x), XEXP (x, 0)) - && ! push_operand (x, GET_MODE (x))) - || (flag_force_addr - && CONSTANT_ADDRESS_P (XEXP (x, 0))))) + && (! memory_address_p (GET_MODE (x), XEXP (x, 0)) + && ! push_operand (x, GET_MODE (x)))) x = validize_mem (x); if (MEM_P (y) - && (! memory_address_p (GET_MODE (y), XEXP (y, 0)) - || (flag_force_addr - && CONSTANT_ADDRESS_P (XEXP (y, 0))))) + && ! memory_address_p (GET_MODE (y), XEXP (y, 0))) y = validize_mem (y); gcc_assert (mode != BLKmode); @@ -4457,9 +4484,8 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal) converting modes. */ if (INTEGRAL_TYPE_P (TREE_TYPE (exp)) && TREE_TYPE (TREE_TYPE (exp)) == 0 - && (!lang_hooks.reduce_bit_field_operations - || (GET_MODE_PRECISION (GET_MODE (target)) - == TYPE_PRECISION (TREE_TYPE (exp))))) + && GET_MODE_PRECISION (GET_MODE (target)) + == TYPE_PRECISION (TREE_TYPE (exp))) { if (TYPE_UNSIGNED (TREE_TYPE (exp)) != SUBREG_PROMOTED_UNSIGNED_P (target)) @@ -4627,7 +4653,8 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal) temp = convert_to_mode (GET_MODE (target), temp, unsignedp); emit_move_insn (target, temp); } - else if (GET_MODE (target) == BLKmode) + else if (GET_MODE (target) == BLKmode + || GET_MODE (temp) == BLKmode) emit_block_move (target, temp, expr_size (exp), (call_param_p ? BLOCK_OP_CALL_PARM @@ -4948,14 +4975,7 @@ count_type_elements (const_tree type, bool allow_flexarr) case UNION_TYPE: case QUAL_UNION_TYPE: - { - /* Ho hum. How in the world do we guess here? Clearly it isn't - right to count the fields. Guess based on the number of words. */ - HOST_WIDE_INT n = int_size_in_bytes (type); - if (n < 0) - return -1; - return n / UNITS_PER_WORD; - } + return -1; case COMPLEX_TYPE: return 2; @@ -5873,7 +5893,8 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, else if (TREE_CODE (exp) == BIT_FIELD_REF) { size_tree = TREE_OPERAND (exp, 1); - *punsignedp = BIT_FIELD_REF_UNSIGNED (exp); + *punsignedp = (! INTEGRAL_TYPE_P (TREE_TYPE (exp)) + || TYPE_UNSIGNED (TREE_TYPE (exp))); /* For vector types, with the correct size of access, use the mode of inner type. */ @@ -6723,8 +6744,7 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode, /* ??? This should be considered a front-end bug. We should not be generating ADDR_EXPR of something that isn't an LVALUE. The only exception here is STRING_CST. */ - if (TREE_CODE (exp) == CONSTRUCTOR - || CONSTANT_CLASS_P (exp)) + if (CONSTANT_CLASS_P (exp)) return XEXP (expand_expr_constant (exp, 0, modifier), 0); /* Everything must be something allowed by is_gimple_addressable. */ @@ -6771,9 +6791,12 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode, default: /* If the object is a DECL, then expand it for its rtl. Don't bypass expand_expr, as that can have various side effects; LABEL_DECLs for - example, may not have their DECL_RTL set yet. Assume language - specific tree nodes can be expanded in some interesting way. */ + example, may not have their DECL_RTL set yet. Expand the rtl of + CONSTRUCTORs too, which should yield a memory reference for the + constructor's contents. Assume language specific tree nodes can + be expanded in some interesting way. */ if (DECL_P (exp) + || TREE_CODE (exp) == CONSTRUCTOR || TREE_CODE (exp) >= LAST_AND_UNUSED_TREE_CODE) { result = expand_expr (exp, target, tmode, @@ -7031,6 +7054,7 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, /* Handle ERROR_MARK before anybody tries to access its type. */ if (TREE_CODE (exp) == ERROR_MARK + || TREE_CODE (exp) == PREDICT_EXPR || (!GIMPLE_TUPLE_P (exp) && TREE_CODE (TREE_TYPE (exp)) == ERROR_MARK)) { ret = CONST0_RTX (tmode); @@ -7109,8 +7133,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, rtx subtarget, original_target; int ignore; tree context, subexp0, subexp1; - bool reduce_bit_field = false; -#define REDUCE_BIT_FIELD(expr) (reduce_bit_field && !ignore \ + bool reduce_bit_field; +#define REDUCE_BIT_FIELD(expr) (reduce_bit_field \ ? reduce_to_bit_field_precision ((expr), \ target, \ type) \ @@ -7128,27 +7152,20 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, mode = TYPE_MODE (type); unsignedp = TYPE_UNSIGNED (type); } - if (lang_hooks.reduce_bit_field_operations - && TREE_CODE (type) == INTEGER_TYPE - && GET_MODE_PRECISION (mode) > TYPE_PRECISION (type)) - { - /* An operation in what may be a bit-field type needs the - result to be reduced to the precision of the bit-field type, - which is narrower than that of the type's mode. */ - reduce_bit_field = true; - if (modifier == EXPAND_STACK_PARM) - target = 0; - } - /* Use subtarget as the target for operand 0 of a binary operation. */ - subtarget = get_subtarget (target); - original_target = target; ignore = (target == const0_rtx || ((code == NON_LVALUE_EXPR || code == NOP_EXPR || code == CONVERT_EXPR || code == COND_EXPR || code == VIEW_CONVERT_EXPR) && TREE_CODE (type) == VOID_TYPE)); + /* An operation in what may be a bit-field type needs the + result to be reduced to the precision of the bit-field type, + which is narrower than that of the type's mode. */ + reduce_bit_field = (!ignore + && TREE_CODE (type) == INTEGER_TYPE + && GET_MODE_PRECISION (mode) > TYPE_PRECISION (type)); + /* If we are going to ignore this result, we need only do something if there is a side-effect somewhere in the expression. If there is, short-circuit the most common cases here. Note that we must @@ -7197,6 +7214,12 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, target = 0; } + if (reduce_bit_field && modifier == EXPAND_STACK_PARM) + target = 0; + + /* Use subtarget as the target for operand 0 of a binary operation. */ + subtarget = get_subtarget (target); + original_target = target; switch (code) { @@ -7274,9 +7297,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, if (MEM_P (decl_rtl) && REG_P (XEXP (decl_rtl, 0))) temp = validize_mem (decl_rtl); - /* If DECL_RTL is memory, we are in the normal case and either - the address is not valid or it is not a register and -fforce-addr - is specified, get the address into a register. */ + /* If DECL_RTL is memory, we are in the normal case and the + address is not valid, get the address into a register. */ else if (MEM_P (decl_rtl) && modifier != EXPAND_INITIALIZER) { @@ -7285,8 +7307,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, decl_rtl = use_anchored_address (decl_rtl); if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_SUM - && (!memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0)) - || (flag_force_addr && !REG_P (XEXP (decl_rtl, 0))))) + && !memory_address_p (DECL_MODE (exp), XEXP (decl_rtl, 0))) temp = replace_equiv_address (decl_rtl, copy_rtx (XEXP (decl_rtl, 0))); } @@ -7408,8 +7429,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, if (modifier != EXPAND_CONST_ADDRESS && modifier != EXPAND_INITIALIZER && modifier != EXPAND_SUM - && (! memory_address_p (mode, XEXP (temp, 0)) - || flag_force_addr)) + && ! memory_address_p (mode, XEXP (temp, 0))) return replace_equiv_address (temp, copy_rtx (XEXP (temp, 0))); return temp; @@ -8001,21 +8021,21 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* All valid uses of __builtin_va_arg_pack () are removed during inlining. */ if (CALL_EXPR_VA_ARG_PACK (exp)) - error ("invalid use of %<__builtin_va_arg_pack ()%>"); + error ("%Kinvalid use of %<__builtin_va_arg_pack ()%>", exp); { tree fndecl = get_callee_fndecl (exp), attr; if (fndecl && (attr = lookup_attribute ("error", DECL_ATTRIBUTES (fndecl))) != NULL) - error ("call to %qs declared with attribute error: %s", - lang_hooks.decl_printable_name (fndecl, 1), + error ("%Kcall to %qs declared with attribute error: %s", + exp, lang_hooks.decl_printable_name (fndecl, 1), TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); if (fndecl && (attr = lookup_attribute ("warning", DECL_ATTRIBUTES (fndecl))) != NULL) - warning (0, "call to %qs declared with attribute warning: %s", - lang_hooks.decl_printable_name (fndecl, 1), + warning (0, "%Kcall to %qs declared with attribute warning: %s", + exp, lang_hooks.decl_printable_name (fndecl, 1), TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr)))); /* Check for a built-in function. */ @@ -8030,6 +8050,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, } return expand_call (exp, target, ignore); + case PAREN_EXPR: case NON_LVALUE_EXPR: case NOP_EXPR: case CONVERT_EXPR: @@ -8878,10 +8899,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, case BIT_XOR_EXPR: goto binop; - case LSHIFT_EXPR: - case RSHIFT_EXPR: case LROTATE_EXPR: case RROTATE_EXPR: + /* The expansion code only handles expansion of mode precision + rotates. */ + gcc_assert (GET_MODE_PRECISION (TYPE_MODE (type)) + == TYPE_PRECISION (type)); + + /* Falltrough. */ + case LSHIFT_EXPR: + case RSHIFT_EXPR: /* If this is a fixed-point operation, then we cannot use the code below because "expand_shift" doesn't support sat/no-sat fixed-point shifts. */ @@ -8894,8 +8921,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, target = 0; op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_NORMAL); - return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target, + temp = expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target, unsignedp); + if (code == LSHIFT_EXPR) + temp = REDUCE_BIT_FIELD (temp); + return temp; /* Could determine the answer when only additive constants differ. Also, the addition of one can be handled by changing the condition. */ @@ -9341,6 +9371,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, goto binop; } + case OMP_ATOMIC_LOAD: + case OMP_ATOMIC_STORE: + /* OMP expansion is not run when there were errors, so these codes + can get here. */ + gcc_assert (errorcount != 0); + return NULL_RTX; + default: return lang_hooks.expand_expr (exp, original_target, tmode, modifier, alt_rtl); @@ -9943,10 +9980,6 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label, index = copy_to_mode_reg (Pmode, index); #endif - /* If flag_force_addr were to affect this address - it could interfere with the tricky assumptions made - about addresses that contain label-refs, - which may be valid only very near the tablejump itself. */ /* ??? The only correct use of CASE_VECTOR_MODE is the one inside the GET_MODE_SIZE, because this indicates how large insns are. The other uses should all be Pmode, because they are addresses. This code @@ -9960,7 +9993,7 @@ do_tablejump (rtx index, enum machine_mode mode, rtx range, rtx table_label, index = PIC_CASE_VECTOR_ADDRESS (index); else #endif - index = memory_address_noforce (CASE_VECTOR_MODE, index); + index = memory_address (CASE_VECTOR_MODE, index); temp = gen_reg_rtx (CASE_VECTOR_MODE); vector = gen_const_mem (CASE_VECTOR_MODE, index); convert_move (temp, vector, 0);