OSDN Git Service

2002-04-02 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index 1cc1d16..6f1a0d6 100644 (file)
@@ -1352,7 +1352,7 @@ convert_modes (mode, oldmode, x, unsignedp)
              && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
            val |= (HOST_WIDE_INT) (-1) << width;
 
-         return GEN_INT (trunc_int_for_mode (val, mode));
+         return gen_int_mode (val, mode);
        }
 
       return gen_lowpart (mode, x);
@@ -2004,12 +2004,17 @@ emit_group_load (dst, orig_src, ssize)
        }
       else if (GET_CODE (src) == CONCAT)
        {
-         if (bytepos == 0
-             && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 0))))
-           tmps[i] = XEXP (src, 0);
-         else if (bytepos == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
-                  && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 1))))
-           tmps[i] = XEXP (src, 1);
+         if ((bytepos == 0
+              && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 0))))
+             || (bytepos == (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (XEXP (src, 0)))
+                 && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 1)))))
+           {
+             tmps[i] = XEXP (src, bytepos != 0);
+             if (! CONSTANT_P (tmps[i])
+                 && (GET_CODE (tmps[i]) != REG || GET_MODE (tmps[i]) != mode))
+               tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
+                                            0, 1, NULL_RTX, mode, mode, ssize);
+           }
          else if (bytepos == 0)
            {
              rtx mem = assign_stack_temp (GET_MODE (src),
@@ -2095,7 +2100,7 @@ emit_group_store (orig_dst, src, ssize)
       emit_group_load (dst, temp, ssize);
       return;
     }
-  else if (GET_CODE (dst) != MEM)
+  else if (GET_CODE (dst) != MEM && GET_CODE (dst) != CONCAT)
     {
       dst = gen_reg_rtx (GET_MODE (orig_dst));
       /* Make life a bit easier for combine.  */
@@ -2108,6 +2113,7 @@ emit_group_store (orig_dst, src, ssize)
       HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
       enum machine_mode mode = GET_MODE (tmps[i]);
       unsigned int bytelen = GET_MODE_SIZE (mode);
+      rtx dest = dst;
 
       /* Handle trailing fragments that run over the size of the struct.  */
       if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
@@ -2121,14 +2127,27 @@ emit_group_store (orig_dst, src, ssize)
          bytelen = ssize - bytepos;
        }
 
+      if (GET_CODE (dst) == CONCAT)
+       {
+         if (bytepos + bytelen <= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
+           dest = XEXP (dst, 0);
+         else if (bytepos >= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0))))
+           {
+             bytepos -= GET_MODE_SIZE (GET_MODE (XEXP (dst, 0)));
+             dest = XEXP (dst, 1);
+           }
+         else
+           abort ();
+       }
+
       /* Optimize the access just a bit.  */
-      if (GET_CODE (dst) == MEM
-         && MEM_ALIGN (dst) >= GET_MODE_ALIGNMENT (mode)
+      if (GET_CODE (dest) == MEM
+         && MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)
          && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
          && bytelen == GET_MODE_SIZE (mode))
-       emit_move_insn (adjust_address (dst, mode, bytepos), tmps[i]);
+       emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]);
       else
-       store_bit_field (dst, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
+       store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT,
                         mode, tmps[i], ssize);
     }
 
@@ -4002,14 +4021,13 @@ store_expr (exp, target, want_value)
        {
          if (TREE_UNSIGNED (TREE_TYPE (exp))
              != SUBREG_PROMOTED_UNSIGNED_P (target))
-           exp
-             = convert
-               (signed_or_unsigned_type (SUBREG_PROMOTED_UNSIGNED_P (target),
-                                         TREE_TYPE (exp)),
-                exp);
-
-         exp = convert (type_for_mode (GET_MODE (SUBREG_REG (target)),
-                                       SUBREG_PROMOTED_UNSIGNED_P (target)),
+           exp = convert
+             ((*lang_hooks.types.signed_or_unsigned_type)
+              (SUBREG_PROMOTED_UNSIGNED_P (target), TREE_TYPE (exp)), exp);
+
+         exp = convert ((*lang_hooks.types.type_for_mode)
+                        (GET_MODE (SUBREG_REG (target)),
+                         SUBREG_PROMOTED_UNSIGNED_P (target)),
                         exp);
 
          inner_target = SUBREG_REG (target);
@@ -4507,7 +4525,8 @@ store_constructor (exp, target, cleared, size)
 
              if (TYPE_PRECISION (type) < BITS_PER_WORD)
                {
-                 type = type_for_size (BITS_PER_WORD, TREE_UNSIGNED (type));
+                 type = (*lang_hooks.types.type_for_size)
+                   (BITS_PER_WORD, TREE_UNSIGNED (type));
                  value = convert (type, value);
                }
 
@@ -4936,7 +4955,8 @@ store_constructor (exp, target, cleared, size)
            {
              targetx
                = assign_temp
-                 ((build_qualified_type (type_for_mode (GET_MODE (target), 0),
+                 ((build_qualified_type ((*lang_hooks.types.type_for_mode)
+                                         (GET_MODE (target), 0),
                                          TYPE_QUAL_CONST)),
                   0, 1, 1);
              emit_move_insn (targetx, target);
@@ -5145,8 +5165,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, type,
 
              if (unsignedp)
                return expand_and (tmode, temp,
-                                  GEN_INT (trunc_int_for_mode (width_mask,
-                                                               tmode)),
+                                  gen_int_mode (width_mask, tmode),
                                   NULL_RTX);
 
              count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
@@ -5827,20 +5846,21 @@ highest_pow2_factor (exp)
   switch (TREE_CODE (exp))
     {
     case INTEGER_CST:
-      /* If the integer is expressable in a HOST_WIDE_INT, we can find the
-        lowest bit that's a one.  If the result is zero, return
-        BIGGEST_ALIGNMENT.  We need to handle this case since we can find it
-        in a COND_EXPR, a MIN_EXPR, or a MAX_EXPR.  If the constant overlows,
-        we have an erroneous program, so return BIGGEST_ALIGNMENT to avoid any
+      /* We can find the lowest bit that's a one.  If the low
+        HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT.
+        We need to handle this case since we can find it in a COND_EXPR,
+        a MIN_EXPR, or a MAX_EXPR.  If the constant overlows, we have an
+        erroneous program, so return BIGGEST_ALIGNMENT to avoid any
         later ICE.  */
-      if (TREE_CONSTANT_OVERFLOW (exp)
-         || integer_zerop (exp))
+      if (TREE_CONSTANT_OVERFLOW (exp))
        return BIGGEST_ALIGNMENT;
-      else if (host_integerp (exp, 0))
+      else
        {
-         c0 = tree_low_cst (exp, 0);
-         c0 = c0 < 0 ? - c0 : c0;
-         return c0 & -c0;
+         /* Note: tree_low_cst is intentionally not used here,
+            we don't care about the upper bits.  */
+         c0 = TREE_INT_CST_LOW (exp);
+         c0 &= -c0;
+         return c0 ? c0 : BIGGEST_ALIGNMENT;
        }
       break;
 
@@ -6227,7 +6247,7 @@ expand_expr (exp, target, tmode, modifier)
          DECL_NONLOCAL (exp) = 1;
          if (DECL_NO_STATIC_CHAIN (current_function_decl))
            abort ();
-         mark_addressable (exp);
+         (*lang_hooks.mark_addressable) (exp);
          if (GET_CODE (DECL_RTL (exp)) != MEM)
            abort ();
          addr = XEXP (DECL_RTL (exp), 0);
@@ -6284,7 +6304,8 @@ expand_expr (exp, target, tmode, modifier)
          /* Get the signedness used for this variable.  Ensure we get the
             same mode we got when the variable was declared.  */
          if (GET_MODE (DECL_RTL (exp))
-             != promote_mode (type, DECL_MODE (exp), &unsignedp, 0))
+             != promote_mode (type, DECL_MODE (exp), &unsignedp, 
+                              (TREE_CODE (exp) == RESULT_DECL ? 1 : 0)))
            abort ();
 
          temp = gen_lowpart_SUBREG (mode, DECL_RTL (exp));
@@ -6441,7 +6462,8 @@ expand_expr (exp, target, tmode, modifier)
       {
        rtx temp;
        temp = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-       TREE_OPERAND (exp, 0) = unsave_expr_now (TREE_OPERAND (exp, 0));
+       TREE_OPERAND (exp, 0)
+         = (*lang_hooks.unsave_expr_now) (TREE_OPERAND (exp, 0));
        return temp;
       }
 
@@ -6520,7 +6542,7 @@ expand_expr (exp, target, tmode, modifier)
        /* Mark the corresponding BLOCK for output in its proper place.  */
        if (TREE_OPERAND (exp, 2) != 0
            && ! TREE_USED (TREE_OPERAND (exp, 2)))
-         insert_block (TREE_OPERAND (exp, 2));
+         (*lang_hooks.decls.insert_block) (TREE_OPERAND (exp, 2));
 
        /* If VARS have not yet been expanded, expand them now.  */
        while (vars)
@@ -6625,8 +6647,8 @@ expand_expr (exp, target, tmode, modifier)
            && GET_MODE_CLASS (mode) == MODE_INT
            && GET_MODE_SIZE (mode) == 1
            && modifier != EXPAND_WRITE)
-         return
-           GEN_INT (TREE_STRING_POINTER (string)[TREE_INT_CST_LOW (index)]);
+         return gen_int_mode (TREE_STRING_POINTER (string)
+                              [TREE_INT_CST_LOW (index)], mode);
 
        op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
        op0 = memory_address (mode, op0);
@@ -6675,8 +6697,8 @@ expand_expr (exp, target, tmode, modifier)
            && compare_tree_int (index, TREE_STRING_LENGTH (array)) < 0
            && GET_MODE_CLASS (mode) == MODE_INT
            && GET_MODE_SIZE (mode) == 1)
-         return
-           GEN_INT (TREE_STRING_POINTER (array)[TREE_INT_CST_LOW (index)]);
+         return gen_int_mode (TREE_STRING_POINTER (array)
+                              [TREE_INT_CST_LOW (index)], mode);
 
        /* If this is a constant index into a constant array,
           just get the value from the array.  Handle both the cases when
@@ -6736,9 +6758,8 @@ expand_expr (exp, target, tmode, modifier)
 
                    if (GET_MODE_CLASS (mode) == MODE_INT
                        && GET_MODE_SIZE (mode) == 1)
-                     return (GEN_INT
-                             (TREE_STRING_POINTER
-                              (init)[TREE_INT_CST_LOW (index)]));
+                     return gen_int_mode (TREE_STRING_POINTER (init)
+                                          [TREE_INT_CST_LOW (index)], mode);
                  }
              }
          }
@@ -6995,7 +7016,8 @@ expand_expr (exp, target, tmode, modifier)
            if (mode == BLKmode)
              {
                rtx new = assign_temp (build_qualified_type
-                                      (type_for_mode (ext_mode, 0),
+                                      ((*lang_hooks.types.type_for_mode)
+                                       (ext_mode, 0),
                                        TYPE_QUAL_CONST), 0, 1, 1);
 
                emit_move_insn (new, op0);
@@ -7220,7 +7242,8 @@ expand_expr (exp, target, tmode, modifier)
         {
          if (DECL_BUILT_IN_CLASS (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
              == BUILT_IN_FRONTEND)
-           return (*lang_expand_expr) (exp, original_target, tmode, modifier);
+           return (*lang_hooks.expand_expr)
+             (exp, original_target, tmode, modifier);
          else
            return expand_builtin (exp, target, subtarget, tmode, ignore);
        }
@@ -7464,7 +7487,8 @@ expand_expr (exp, target, tmode, modifier)
              rtx constant_part;
 
              op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
-                                EXPAND_SUM);
+                                (modifier == EXPAND_INITIALIZER
+                                ? EXPAND_INITIALIZER : EXPAND_SUM));
              if (! CONSTANT_P (op0))
                {
                  op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
@@ -7733,6 +7757,7 @@ expand_expr (exp, target, tmode, modifier)
          expensive divide.  If not, combine will rebuild the original
          computation.  */
       if (flag_unsafe_math_optimizations && optimize && !optimize_size
+         && TREE_CODE (type) == REAL_TYPE
          && !real_onep (TREE_OPERAND (exp, 0)))
         return expand_expr (build (MULT_EXPR, type, TREE_OPERAND (exp, 0),
                                   build (RDIV_EXPR, type,
@@ -7942,8 +7967,25 @@ expand_expr (exp, target, tmode, modifier)
          temp = expand_expr (TREE_OPERAND (exp, 0), original_target,
                              VOIDmode, 0);
 
+         /* If temp is constant, we can just compute the result.  */
+         if (GET_CODE (temp) == CONST_INT)
+           {
+             if (INTVAL (temp) != 0)
+               emit_move_insn (target, const1_rtx);
+             else
+               emit_move_insn (target, const0_rtx);
+
+             return target;
+           }
+
          if (temp != original_target)
-           temp = copy_to_reg (temp);
+           {
+             enum machine_mode mode1 = GET_MODE (temp);
+             if (mode1 == VOIDmode)
+               mode1 = tmode != VOIDmode ? tmode : mode;
+             
+             temp = copy_to_mode_reg (mode1, temp);
+           }
 
          op1 = gen_label_rtx ();
          emit_cmp_and_jump_insns (temp, const0_rtx, EQ, NULL_RTX,
@@ -8341,7 +8383,8 @@ expand_expr (exp, target, tmode, modifier)
                   built here.  */
 
                if (TREE_OPERAND (exp, 2) == 0)
-                 TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot);
+                 TREE_OPERAND (exp, 2)
+                   = (*lang_hooks.maybe_build_cleanup) (slot);
                cleanups = TREE_OPERAND (exp, 2);
              }
          }
@@ -8761,7 +8804,7 @@ expand_expr (exp, target, tmode, modifier)
       abort ();
 
     default:
-      return (*lang_expand_expr) (exp, original_target, tmode, modifier);
+      return (*lang_hooks.expand_expr) (exp, original_target, tmode, modifier);
     }
 
   /* Here to do an ordinary binary operator, generating an instruction
@@ -9212,7 +9255,7 @@ do_jump (exp, if_false_label, if_true_label)
          && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
          && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
          && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
-         && (type = type_for_mode (mode, 1)) != 0
+         && (type = (*lang_hooks.types.type_for_mode) (mode, 1)) != 0
          && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
          && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
              != CODE_FOR_nothing))
@@ -9272,7 +9315,7 @@ do_jump (exp, if_false_label, if_true_label)
        get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
                             &unsignedp, &volatilep);
 
-       type = type_for_size (bitsize, unsignedp);
+       type = (*lang_hooks.types.type_for_size) (bitsize, unsignedp);
        if (! SLOW_BYTE_ACCESS
            && type != 0 && bitsize >= 0
            && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
@@ -10353,8 +10396,8 @@ try_casesi (index_type, index_expr, minval, range,
     {
       if (TYPE_MODE (index_type) != index_mode)
        {
-         index_expr = convert (type_for_size (index_bits, 0),
-                               index_expr);
+         index_expr = convert ((*lang_hooks.types.type_for_size)
+                               (index_bits, 0), index_expr);
          index_type = TREE_TYPE (index_expr);
        }