OSDN Git Service

* init.c (build_new): Allow enumeration types for the array-bounds
[pf3gnuchains/gcc-fork.git] / gcc / expr.c
index fbe5fe5..f4ff9b2 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert tree expression to rtl instructions, for GNU compiler.
-   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
-   Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+   2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -39,7 +39,6 @@ Boston, MA 02111-1307, USA.  */
 #include "reload.h"
 #include "output.h"
 #include "typeclass.h"
-#include "defaults.h"
 #include "toplev.h"
 #include "ggc.h"
 #include "intl.h"
@@ -181,7 +180,6 @@ static tree save_noncopied_parts PARAMS ((tree, tree));
 static tree init_noncopied_parts PARAMS ((tree, tree));
 static int fixed_type_p                PARAMS ((tree));
 static rtx var_rtx             PARAMS ((tree));
-static int readonly_fields_p   PARAMS ((tree));
 static rtx expand_expr_unaligned PARAMS ((tree, unsigned int *));
 static rtx expand_increment    PARAMS ((tree, int, int));
 static void do_jump_by_parts_greater PARAMS ((tree, int, rtx, rtx));
@@ -213,7 +211,7 @@ static char direct_store[NUM_MACHINE_MODES];
    to perform a structure copy.  */
 #ifndef MOVE_BY_PIECES_P
 #define MOVE_BY_PIECES_P(SIZE, ALIGN) \
-  (move_by_pieces_ninsns (SIZE, ALIGN) < MOVE_RATIO)
+  (move_by_pieces_ninsns (SIZE, ALIGN) < (unsigned int) MOVE_RATIO)
 #endif
 
 /* This array records the insn_code of insns to perform block moves.  */
@@ -1759,7 +1757,7 @@ emit_block_move (x, y, size, align)
          DECL_EXTERNAL (fn) = 1;
          TREE_PUBLIC (fn) = 1;
          DECL_ARTIFICIAL (fn) = 1;
-         make_decl_rtl (fn, NULL_PTR, 1);
+         make_decl_rtl (fn, NULL_PTR);
          assemble_external (fn);
        }
 
@@ -1858,6 +1856,9 @@ move_block_from_reg (regno, x, nregs, size)
 #endif
   enum machine_mode mode;
 
+  if (nregs == 0)
+    return;
+
   /* If SIZE is that of a mode no bigger than a word, just use that
      mode's store operation.  */
   if (size <= UNITS_PER_WORD
@@ -1968,7 +1969,7 @@ emit_group_load (dst, orig_src, ssize, align)
       int shift = 0;
 
       /* Handle trailing fragments that run over the size of the struct.  */
-      if (ssize >= 0 && bytepos + bytelen > ssize)
+      if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
        {
          shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
          bytelen = ssize - bytepos;
@@ -1993,7 +1994,7 @@ emit_group_load (dst, orig_src, ssize, align)
          if (bytepos == 0
              && bytelen == GET_MODE_SIZE (GET_MODE (XEXP (src, 0))))
            tmps[i] = XEXP (src, 0);
-         else if (bytepos == GET_MODE_SIZE (GET_MODE (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);
          else
@@ -2091,7 +2092,7 @@ emit_group_store (orig_dst, src, ssize, align)
       unsigned int bytelen = GET_MODE_SIZE (mode);
 
       /* Handle trailing fragments that run over the size of the struct.  */
-      if (ssize >= 0 && bytepos + bytelen > ssize)
+      if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize)
        {
          if (BYTES_BIG_ENDIAN)
            {
@@ -2145,8 +2146,10 @@ copy_blkmode_from_reg (tgtblk, srcreg, type)
 
   if (tgtblk == 0)
     {
-      tgtblk = assign_stack_temp (BLKmode, bytes, 0);
-      MEM_SET_IN_STRUCT_P (tgtblk, AGGREGATE_TYPE_P (type));
+      tgtblk = assign_temp (build_qualified_type (type,
+                                                 (TYPE_QUALS (type)
+                                                  | TYPE_QUAL_CONST)),
+                           0, 1, 1);
       preserve_temp_slots (tgtblk);
     }
 
@@ -2538,7 +2541,7 @@ clear_storage (object, size, align)
      just move a zero.  Otherwise, do this a piece at a time.  */
   if (GET_MODE (object) != BLKmode
       && GET_CODE (size) == CONST_INT
-      && GET_MODE_SIZE (GET_MODE (object)) == INTVAL (size))
+      && GET_MODE_SIZE (GET_MODE (object)) == (unsigned int) INTVAL (size))
     emit_move_insn (object, CONST0_RTX (GET_MODE (object)));
   else
     {
@@ -2654,7 +2657,7 @@ clear_storage (object, size, align)
              DECL_EXTERNAL (fn) = 1;
              TREE_PUBLIC (fn) = 1;
              DECL_ARTIFICIAL (fn) = 1;
-             make_decl_rtl (fn, NULL_PTR, 1);
+             make_decl_rtl (fn, NULL_PTR);
              assemble_external (fn);
            }
 
@@ -2705,6 +2708,8 @@ emit_move_insn (x, y)
      rtx x, y;
 {
   enum machine_mode mode = GET_MODE (x);
+  rtx y_cst = NULL_RTX;
+  rtx last_insn;
 
   x = protect_from_queue (x, 1);
   y = protect_from_queue (y, 0);
@@ -2716,7 +2721,10 @@ emit_move_insn (x, y)
   if (GET_CODE (y) == CONSTANT_P_RTX)
     ;
   else if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
-    y = force_const_mem (mode, y);
+    {
+      y_cst = y;
+      y = force_const_mem (mode, y);
+    }
 
   /* If X or Y are memory references, verify that their addresses are valid
      for the machine.  */
@@ -2736,7 +2744,13 @@ emit_move_insn (x, y)
   if (mode == BLKmode)
     abort ();
 
-  return emit_move_insn_1 (x, y);
+  last_insn = emit_move_insn_1 (x, y);
+
+  if (y_cst && GET_CODE (x) == REG)
+    REG_NOTES (last_insn)
+      = gen_rtx_EXPR_LIST (REG_EQUAL, y_cst, REG_NOTES (last_insn));
+
+  return last_insn;
 }
 
 /* Low level part of emit_move_insn.
@@ -2822,17 +2836,17 @@ emit_move_insn_1 (x, y)
                  enum mode_class reg_class = ((class == MODE_COMPLEX_FLOAT)
                                               ? MODE_FLOAT : MODE_INT);
 
-                 enum machine_mode reg_mode =
-                   mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
+                 enum machine_mode reg_mode
+                   mode_for_size (GET_MODE_BITSIZE (mode), reg_class, 1);
 
                  if (reg_mode != BLKmode)
                    {
                      rtx mem = assign_stack_temp (reg_mode,
                                                   GET_MODE_SIZE (mode), 0);
-
                      rtx cmem = change_address (mem, mode, NULL_RTX);
 
-                     cfun->cannot_inline = N_("function using short complex types cannot be inline");
+                     cfun->cannot_inline
+                       = N_("function using short complex types cannot be inline");
 
                      if (packed_dest_p)
                        {
@@ -4150,9 +4164,10 @@ store_expr (exp, target, want_value)
                {
                  addr = plus_constant (addr, TREE_STRING_LENGTH (exp));
                  size = plus_constant (size, -TREE_STRING_LENGTH (exp));
-                 align = MIN (align, (BITS_PER_UNIT
-                                      * (INTVAL (copy_size_rtx)
-                                         & - INTVAL (copy_size_rtx))));
+                 align = MIN (align,
+                              (unsigned int) (BITS_PER_UNIT
+                                              * (INTVAL (copy_size_rtx)
+                                                 & - INTVAL (copy_size_rtx))));
                }
              else
                {
@@ -4338,8 +4353,14 @@ store_constructor_field (target, bitsize, bitpos,
                            plus_constant (XEXP (target, 0),
                                           bitpos / BITS_PER_UNIT));
 
+
+      /* Show the alignment may no longer be what it was and update the alias
+        set, if required.  */
+      if (bitpos != 0)
+       align = MIN (align, (unsigned int) bitpos & - bitpos);
       if (GET_CODE (target) == MEM)
        MEM_ALIAS_SET (target) = alias_set;
+
       store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
     }
   else
@@ -4422,7 +4443,7 @@ store_constructor (exp, target, align, cleared, size)
                    != fields_length (type))
                   || mostly_zeros_p (exp))
               && (GET_CODE (target) != REG
-                  || GET_MODE_SIZE (GET_MODE (target)) == size))
+                  || (HOST_WIDE_INT) GET_MODE_SIZE (GET_MODE (target)) == size))
        {
          if (! cleared)
            clear_storage (target, GEN_INT (size), align);
@@ -4777,6 +4798,7 @@ store_constructor (exp, target, align, cleared, size)
              store_constructor_field (target, bitsize, bitpos, mode, value,
                                       type, align, cleared,
                                       TYPE_NONALIASED_COMPONENT (type)
+                                      && GET_CODE (target) == MEM
                                       ? MEM_ALIAS_SET (target) :
                                       get_alias_set (elttype));
 
@@ -4921,9 +4943,11 @@ store_constructor (exp, target, align, cleared, size)
 
          if (REG_P (target))
            {
-             targetx = assign_stack_temp (GET_MODE (target),
-                                          GET_MODE_SIZE (GET_MODE (target)),
-                                          0);
+             targetx
+               = assign_temp
+                 ((build_qualified_type (type_for_mode (GET_MODE (target), 0),
+                                         TYPE_QUAL_CONST)),
+                  0, 1, 1);
              emit_move_insn (targetx, target);
            }
 
@@ -5022,15 +5046,16 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
   if (mode == BLKmode
       && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
     {
-      rtx object = assign_stack_temp (GET_MODE (target),
-                                     GET_MODE_SIZE (GET_MODE (target)), 0);
+      rtx object
+       = assign_temp
+         (build_qualified_type (type_for_mode (GET_MODE (target), 0),
+                                TYPE_QUAL_CONST),
+          0, 1, 1);
       rtx blk_object = copy_rtx (object);
 
-      MEM_SET_IN_STRUCT_P (object, 1);
-      MEM_SET_IN_STRUCT_P (blk_object, 1);
       PUT_MODE (blk_object, BLKmode);
 
-      if (bitsize != GET_MODE_BITSIZE (GET_MODE (target)))
+      if (bitsize != (HOST_WIDE_INT) GET_MODE_BITSIZE (GET_MODE (target)))
        emit_move_insn (object, target);
 
       store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0,
@@ -5394,10 +5419,10 @@ get_memory_usage_from_modifier (modifier)
     }
 }
 \f
-/* Given an rtx VALUE that may contain additions and multiplications,
-   return an equivalent value that just refers to a register or memory.
-   This is done by generating instructions to perform the arithmetic
-   and returning a pseudo-register containing the value.
+/* Given an rtx VALUE that may contain additions and multiplications, return
+   an equivalent value that just refers to a register, memory, or constant.
+   This is done by generating instructions to perform the arithmetic and
+   returning a pseudo-register containing the value.
 
    The returned value may be a REG, SUBREG, MEM or constant.  */
 
@@ -5506,7 +5531,12 @@ save_noncopied_parts (lhs, list)
        tree part = TREE_VALUE (tail);
        tree part_type = TREE_TYPE (part);
        tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part);
-       rtx target = assign_temp (part_type, 0, 1, 1);
+       rtx target
+         = assign_temp (build_qualified_type (part_type,
+                                              (TYPE_QUALS (part_type)
+                                               | TYPE_QUAL_CONST)),
+                        0, 1, 1);
+
        if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0)))
          target = change_address (target, TYPE_MODE (part_type), NULL_RTX);
        parts = tree_cons (to_be_saved,
@@ -5559,10 +5589,7 @@ safe_from_p (x, exp, top_p)
 {
   rtx exp_rtl = 0;
   int i, nops;
-  static int save_expr_count;
-  static int save_expr_size = 0;
-  static tree *save_expr_rewritten;
-  static tree save_expr_trees[256];
+  static tree save_expr_list;
 
   if (x == 0
       /* If EXP has varying size, we MUST use a target since we currently
@@ -5577,31 +5604,14 @@ safe_from_p (x, exp, top_p)
              || TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)) == NULL_TREE
              || TREE_CODE (TYPE_ARRAY_MAX_SIZE (TREE_TYPE (exp)))
              != INTEGER_CST)
-         && GET_MODE (x) == BLKmode))
+         && GET_MODE (x) == BLKmode)
+      /* If X is in the outgoing argument area, it is always safe.  */
+      || (GET_CODE (x) == MEM
+         && (XEXP (x, 0) == virtual_outgoing_args_rtx
+             || (GET_CODE (XEXP (x, 0)) == PLUS
+                 && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx))))
     return 1;
 
-  if (top_p && save_expr_size == 0)
-    {
-      int rtn;
-
-      save_expr_count = 0;
-      save_expr_size = ARRAY_SIZE (save_expr_trees);
-      save_expr_rewritten = &save_expr_trees[0];
-
-      rtn = safe_from_p (x, exp, 1);
-
-      for (i = 0; i < save_expr_count; ++i)
-       {
-         if (TREE_CODE (save_expr_trees[i]) != ERROR_MARK)
-           abort ();
-         TREE_SET_CODE (save_expr_trees[i], SAVE_EXPR);
-       }
-
-      save_expr_size = 0;
-
-      return rtn;
-    }
-
   /* If this is a subreg of a hard register, declare it unsafe, otherwise,
      find the underlying pseudo.  */
   if (GET_CODE (x) == SUBREG)
@@ -5611,13 +5621,31 @@ safe_from_p (x, exp, top_p)
        return 0;
     }
 
-  /* If X is a location in the outgoing argument area, it is always safe.  */
-  if (GET_CODE (x) == MEM
-      && (XEXP (x, 0) == virtual_outgoing_args_rtx
-         || (GET_CODE (XEXP (x, 0)) == PLUS
-             && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx)))
-    return 1;
+  /* A SAVE_EXPR might appear many times in the expression passed to the
+     top-level safe_from_p call, and if it has a complex subexpression,
+     examining it multiple times could result in a combinatorial explosion.
+     E.g. on an Alpha running at least 200MHz, a Fortran test case compiled
+     with optimization took about 28 minutes to compile -- even though it was
+     only a few lines long.  So we mark each SAVE_EXPR we see with TREE_PRIVATE
+     and turn that off when we are done.  We keep a list of the SAVE_EXPRs
+     we have processed.  Note that the only test of top_p was above.  */
+
+  if (top_p)
+    {
+      int rtn;
+      tree t;
+
+      save_expr_list = 0;
 
+      rtn = safe_from_p (x, exp, 0);
+
+      for (t = save_expr_list; t != 0; t = TREE_CHAIN (t))
+       TREE_PRIVATE (TREE_PURPOSE (t)) = 0;
+
+      return rtn;
+    }
+
+  /* Now look at our tree code and possibly recurse.  */
   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
     {
     case 'd':
@@ -5657,11 +5685,13 @@ safe_from_p (x, exp, top_p)
        {
        case ADDR_EXPR:
          return (staticp (TREE_OPERAND (exp, 0))
-                 || safe_from_p (x, TREE_OPERAND (exp, 0), 0)
-                 || TREE_STATIC (exp));
+                 || TREE_STATIC (exp)
+                 || safe_from_p (x, TREE_OPERAND (exp, 0), 0));
 
        case INDIRECT_REF:
-         if (GET_CODE (x) == MEM)
+         if (GET_CODE (x) == MEM
+             && alias_sets_conflict_p (MEM_ALIAS_SET (x),
+                                       get_alias_set (exp)))
            return 0;
          break;
 
@@ -5695,37 +5725,20 @@ safe_from_p (x, exp, top_p)
          if (exp_rtl)
            break;
 
-         /* This SAVE_EXPR might appear many times in the top-level
-            safe_from_p() expression, and if it has a complex
-            subexpression, examining it multiple times could result
-            in a combinatorial explosion.  E.g. on an Alpha
-            running at least 200MHz, a Fortran test case compiled with
-            optimization took about 28 minutes to compile -- even though
-            it was only a few lines long, and the complicated line causing
-            so much time to be spent in the earlier version of safe_from_p()
-            had only 293 or so unique nodes.
-
-            So, turn this SAVE_EXPR into an ERROR_MARK for now, but remember
-            where it is so we can turn it back in the top-level safe_from_p()
-            when we're done.  */
-
-         /* For now, don't bother re-sizing the array.  */
-         if (save_expr_count >= save_expr_size)
-           return 0;
-         save_expr_rewritten[save_expr_count++] = exp;
+         /* If we've already scanned this, don't do it again.  Otherwise,
+            show we've scanned it and record for clearing the flag if we're
+            going on.  */
+         if (TREE_PRIVATE (exp))
+           return 1;
 
-         nops = TREE_CODE_LENGTH (SAVE_EXPR);
-         for (i = 0; i < nops; i++)
+         TREE_PRIVATE (exp) = 1;
+         if (! safe_from_p (x, TREE_OPERAND (exp, 0), 0))
            {
-             tree operand = TREE_OPERAND (exp, i);
-             if (operand == NULL_TREE)
-               continue;
-             TREE_SET_CODE (exp, ERROR_MARK);
-             if (!safe_from_p (x, operand, 0))
-               return 0;
-             TREE_SET_CODE (exp, SAVE_EXPR);
+             TREE_PRIVATE (exp) = 0;
+             return 0;
            }
-         TREE_SET_CODE (exp, ERROR_MARK);
+
+         save_expr_list = tree_cons (exp, NULL_TREE, save_expr_list);
          return 1;
 
        case BIND_EXPR:
@@ -5772,10 +5785,11 @@ safe_from_p (x, exp, top_p)
        }
 
       /* If the rtl is X, then it is not safe.  Otherwise, it is unless both
-        are memory and EXP is not readonly.  */
+        are memory and they conflict.  */
       return ! (rtx_equal_p (x, exp_rtl)
                || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
-                   && ! TREE_READONLY (exp)));
+                   && true_dependence (exp_rtl, GET_MODE (x), x,
+                                       rtx_addr_varies_p)));
     }
 
   /* If we reach here, it is safe.  */
@@ -5817,6 +5831,7 @@ var_rtx (exp)
 }
 
 #ifdef MAX_INTEGER_COMPUTATION_MODE
+
 void
 check_max_integer_computation_mode (exp)
      tree exp;
@@ -5842,7 +5857,7 @@ check_max_integer_computation_mode (exp)
       mode = TYPE_MODE (TREE_TYPE (exp));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 
   /* Check operand of a unary op.  */
@@ -5851,7 +5866,7 @@ check_max_integer_computation_mode (exp)
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 
   /* Check operands of a binary/comparison op.  */
@@ -5860,36 +5875,16 @@ check_max_integer_computation_mode (exp)
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
 
       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 }
 #endif
 \f
-/* Utility function used by expand_expr to see if TYPE, a RECORD_TYPE,
-   has any readonly fields.  If any of the fields have types that
-   contain readonly fields, return true as well.  */
-
-static int
-readonly_fields_p (type)
-     tree type;
-{
-  tree field;
-
-  for (field = TYPE_FIELDS (type); field != 0; field = TREE_CHAIN (field))
-    if (TREE_CODE (field) == FIELD_DECL
-       && (TREE_READONLY (field)
-           || (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE
-               && readonly_fields_p (TREE_TYPE (field)))))
-      return 1;
-
-  return 0;
-}
-\f
 /* expand_expr: generate code for computing expression EXP.
    An rtx for the computed value is returned.  The value is never null.
    In the case of a void EXP, const0_rtx is returned.
@@ -6043,7 +6038,7 @@ expand_expr (exp, target, tmode, modifier)
 
       if (GET_MODE_CLASS (mode) == MODE_INT
          && mode > MAX_INTEGER_COMPUTATION_MODE)
-       fatal ("unsupported wide integer operation");
+       internal_error ("unsupported wide integer operation");
     }
 
   if (tmode != mode
@@ -6058,7 +6053,7 @@ expand_expr (exp, target, tmode, modifier)
       && TREE_CODE (exp) != RTL_EXPR
       && GET_MODE_CLASS (tmode) == MODE_INT
       && tmode > MAX_INTEGER_COMPUTATION_MODE)
-    fatal ("unsupported wide integer operation");
+    internal_error ("unsupported wide integer operation");
 
   check_max_integer_computation_mode (exp);
 #endif
@@ -6350,11 +6345,10 @@ expand_expr (exp, target, tmode, modifier)
          if (mode == VOIDmode)
            temp = const0_rtx;
          else
-           {
-             temp = assign_temp (type, 3, 0, 0);
-             if (GET_CODE (temp) == MEM)
-               RTX_UNCHANGING_P (temp) = 1;
-           }
+           temp = assign_temp (build_qualified_type (type,
+                                                     (TYPE_QUALS (type)
+                                                      | TYPE_QUAL_CONST)),
+                               3, 0, 0);
 
          SAVE_EXPR_RTL (exp) = temp;
          if (!optimize && GET_CODE (temp) == REG)
@@ -6606,27 +6600,18 @@ expand_expr (exp, target, tmode, modifier)
                                          XEXP (constructor, 0));
          return constructor;
        }
-
       else
        {
          /* Handle calls that pass values in multiple non-contiguous
             locations.  The Irix 6 ABI has examples of this.  */
          if (target == 0 || ! safe_from_p (target, exp, 1)
              || GET_CODE (target) == PARALLEL)
-           {
-             if (mode != BLKmode && ! TREE_ADDRESSABLE (exp))
-               target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-             else
-               target = assign_temp (type, 0, 1, 1);
-           }
-
-         if (TREE_READONLY (exp))
-           {
-             if (GET_CODE (target) == MEM)
-               target = copy_rtx (target);
-
-             RTX_UNCHANGING_P (target) = 1;
-           }
+           target
+             = assign_temp (build_qualified_type (type,
+                                                  (TYPE_QUALS (type)
+                                                   | (TREE_READONLY (exp)
+                                                      * TYPE_QUAL_CONST))),
+                            TREE_ADDRESSABLE (exp), 1, 1);
 
          store_constructor (exp, target, TYPE_ALIGN (TREE_TYPE (exp)), 0,
                             int_size_in_bytes (TREE_TYPE (exp)));
@@ -6685,8 +6670,7 @@ expand_expr (exp, target, tmode, modifier)
        /* If we are writing to this object and its type is a record with
           readonly fields, we must mark it as readonly so it will
           conflict with readonly references to those fields.  */
-       if (modifier == EXPAND_MEMORY_USE_WO
-           && TREE_CODE (type) == RECORD_TYPE && readonly_fields_p (type))
+       if (modifier == EXPAND_MEMORY_USE_WO && readonly_fields_p (type))
          RTX_UNCHANGING_P (temp) = 1;
 
        return temp;
@@ -6902,7 +6886,10 @@ expand_expr (exp, target, tmode, modifier)
            if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
                || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
              {
-               rtx memloc = assign_temp (TREE_TYPE (tem), 1, 1, 1);
+               tree nt = build_qualified_type (TREE_TYPE (tem),
+                                               (TYPE_QUALS (TREE_TYPE (tem))
+                                                | TYPE_QUAL_CONST));
+               rtx memloc = assign_temp (nt, 1, 1, 1);
 
                mark_temp_addr_taken (memloc);
                emit_move_insn (memloc, op0);
@@ -7077,13 +7064,13 @@ expand_expr (exp, target, tmode, modifier)
 
            if (mode == BLKmode)
              {
-               rtx new = assign_stack_temp (ext_mode,
-                                            bitsize / BITS_PER_UNIT, 0);
+               tree nt = build_qualified_type (type_for_mode (ext_mode, 0),
+                                               TYPE_QUAL_CONST);
+               rtx new = assign_temp (nt, 0, 1, 1);
 
                emit_move_insn (new, op0);
                op0 = copy_rtx (new);
                PUT_MODE (op0, BLKmode);
-               MEM_SET_IN_STRUCT_P (op0, 1);
              }
 
            return op0;
@@ -7303,12 +7290,7 @@ expand_expr (exp, target, tmode, modifier)
                                modifier);
 
          if (target == 0)
-           {
-             if (mode != BLKmode)
-               target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
-             else
-               target = assign_temp (type, 0, 1, 1);
-           }
+           target = assign_temp (type, 0, 1, 1);
 
          if (GET_CODE (target) == MEM)
            /* Store data into beginning of memory target.  */
@@ -7321,7 +7303,7 @@ expand_expr (exp, target, tmode, modifier)
                         MIN ((int_size_in_bytes (TREE_TYPE
                                                  (TREE_OPERAND (exp, 0)))
                               * BITS_PER_UNIT),
-                             GET_MODE_BITSIZE (mode)),
+                             (HOST_WIDE_INT) GET_MODE_BITSIZE (mode)),
                         0, TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
                         VOIDmode, 0, BITS_PER_UNIT,
                         int_size_in_bytes (type), 0);
@@ -8514,7 +8496,10 @@ expand_expr (exp, target, tmode, modifier)
              /* If this object is in a register, it must be not
                 be BLKmode.  */
              tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
-             rtx memloc = assign_temp (inner_type, 1, 1, 1);
+             tree nt = build_qualified_type (inner_type,
+                                             (TYPE_QUALS (inner_type)
+                                              | TYPE_QUAL_CONST));
+             rtx memloc = assign_temp (nt, 1, 1, 1);
 
              mark_temp_addr_taken (memloc);
              if (GET_CODE (op0) == PARALLEL)
@@ -8914,7 +8899,10 @@ expand_expr_unaligned (exp, palign)
            if (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG
                || GET_CODE (op0) == CONCAT || GET_CODE (op0) == ADDRESSOF)
              {
-               rtx memloc = assign_temp (TREE_TYPE (tem), 1, 1, 1);
+               tree nt = build_qualified_type (TREE_TYPE (tem),
+                                               (TYPE_QUALS (TREE_TYPE (tem))
+                                                | TYPE_QUAL_CONST));
+               rtx memloc = assign_temp (nt, 1, 1, 1);
 
                mark_temp_addr_taken (memloc);
                emit_move_insn (memloc, op0);
@@ -8996,8 +8984,9 @@ expand_expr_unaligned (exp, palign)
              }
            else
              {
-               rtx new = assign_stack_temp (ext_mode,
-                                            bitsize / BITS_PER_UNIT, 0);
+               tree nt = build_qualified_type (type_for_mode (ext_mode, 0),
+                                               TYPE_QUAL_CONST);
+               rtx new = assign_temp (nt, 0, 1, 1);
 
                op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
                                         unsignedp, NULL_RTX, ext_mode,
@@ -9797,7 +9786,9 @@ do_jump (exp, if_false_label, if_true_label)
       /* Do any postincrements in the expression that was tested.  */
       emit_queue ();
 
-      if (GET_CODE (temp) == CONST_INT || GET_CODE (temp) == LABEL_REF)
+      if (GET_CODE (temp) == CONST_INT 
+         || (GET_CODE (temp) == CONST_DOUBLE && GET_MODE (temp) == VOIDmode)
+         || GET_CODE (temp) == LABEL_REF)
        {
          rtx target = temp == const0_rtx ? if_false_label : if_true_label;
          if (target)