OSDN Git Service

* config/h8300/h8300.md (a peephole2): Remove useless code.
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index c03ccdd..6caaf5f 100644 (file)
@@ -1,27 +1,29 @@
 /* C-compiler utilities for types and variables storage layout
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1996, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC 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 version.
+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
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+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 GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "tree.h"
 #include "rtl.h"
 #include "tm_p.h"
@@ -30,6 +32,8 @@ Boston, MA 02111-1307, USA.  */
 #include "expr.h"
 #include "toplev.h"
 #include "ggc.h"
+#include "target.h"
+#include "langhooks.h"
 
 /* Set to one when set_sizetype has been called.  */
 static int sizetype_set;
@@ -46,24 +50,46 @@ tree sizetype_tab[(int) TYPE_KIND_LAST];
    The value is measured in bits.  */
 unsigned int maximum_field_alignment;
 
-/* If non-zero, the alignment of a bitstring or (power-)set value, in bits.
+/* If nonzero, the alignment of a bitstring or (power-)set value, in bits.
    May be overridden by front-ends.  */
 unsigned int set_alignment = 0;
 
+/* Nonzero if all REFERENCE_TYPEs are internal and hence should be
+   allocated in Pmode, not ptr_mode.   Set only by internal_reference_types
+   called only by a front end.  */
+static int reference_types_internal = 0;
+
 static void finalize_record_size       PARAMS ((record_layout_info));
 static void finalize_type_size         PARAMS ((tree));
 static void place_union_field          PARAMS ((record_layout_info, tree));
+#if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED)
+static int excess_unit_span            PARAMS ((HOST_WIDE_INT, HOST_WIDE_INT,
+                                               HOST_WIDE_INT, HOST_WIDE_INT,
+                                               tree));
+#endif
+static unsigned int update_alignment_for_field
+                                        PARAMS ((record_layout_info, tree, 
+                                                unsigned int));
 extern void debug_rli                  PARAMS ((record_layout_info));
 \f
 /* SAVE_EXPRs for sizes of types and decls, waiting to be expanded.  */
 
-static tree pending_sizes;
+static GTY(()) tree pending_sizes;
 
 /* Nonzero means cannot safely call expand_expr now,
    so put variable sizes onto `pending_sizes' instead.  */
 
 int immediate_size_expand;
 
+/* Show that REFERENCE_TYPES are internal and should be Pmode.  Called only
+   by front end.  */
+
+void
+internal_reference_types ()
+{
+  reference_types_internal = 1;
+}
+
 /* Get a list of all the objects put on the pending sizes list.  */
 
 tree
@@ -80,6 +106,37 @@ get_pending_sizes ()
   return chain;
 }
 
+/* Return nonzero if EXPR is present on the pending sizes list.  */
+
+int
+is_pending_size (expr)
+     tree expr;
+{
+  tree t;
+
+  for (t = pending_sizes; t; t = TREE_CHAIN (t))
+    if (TREE_VALUE (t) == expr)
+      return 1;
+  return 0;
+}
+
+/* Add EXPR to the pending sizes list.  */
+
+void
+put_pending_size (expr)
+     tree expr;
+{
+  /* Strip any simple arithmetic from EXPR to see if it has an underlying
+     SAVE_EXPR.  */
+  while (TREE_CODE_CLASS (TREE_CODE (expr)) == '1'
+        || (TREE_CODE_CLASS (TREE_CODE (expr)) == '2'
+           && TREE_CONSTANT (TREE_OPERAND (expr, 1))))
+    expr = TREE_OPERAND (expr, 0);
+
+  if (TREE_CODE (expr) == SAVE_EXPR)
+    pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes);
+}
+
 /* Put a chain of objects into the pending sizes list, which must be
    empty.  */
 
@@ -100,14 +157,23 @@ tree
 variable_size (size)
      tree size;
 {
+  tree save;
+
   /* If the language-processor is to take responsibility for variable-sized
      items (e.g., languages which have elaboration procedures like Ada),
-     just return SIZE unchanged.  Likewise for self-referential sizes.  */
+     just return SIZE unchanged.  Likewise for self-referential sizes and
+     constant sizes.  */
   if (TREE_CONSTANT (size)
-      || global_bindings_p () < 0 || contains_placeholder_p (size))
+      || (*lang_hooks.decls.global_bindings_p) () < 0
+      || contains_placeholder_p (size))
     return size;
 
-  size = save_expr (size);
+  if (TREE_CODE (size) == MINUS_EXPR && integer_onep (TREE_OPERAND (size, 1)))
+    /* If this is the upper bound of a C array, leave the minus 1 outside
+       the SAVE_EXPR so it can be folded away.  */
+    TREE_OPERAND (size, 0) = save = save_expr (TREE_OPERAND (size, 0));
+  else
+    size = save = save_expr (size);
 
   /* If an array with a variable number of elements is declared, and
      the elements require destruction, we will emit a cleanup for the
@@ -117,10 +183,10 @@ variable_size (size)
      `unsaved', i.e., all SAVE_EXPRs are recalculated.  However, we do
      not wish to do that here; the array-size is the same in both
      places.  */
-  if (TREE_CODE (size) == SAVE_EXPR)
-    SAVE_EXPR_PERSISTENT_P (size) = 1;
+  if (TREE_CODE (save) == SAVE_EXPR)
+    SAVE_EXPR_PERSISTENT_P (save) = 1;
 
-  if (global_bindings_p ())
+  if ((*lang_hooks.decls.global_bindings_p) ())
     {
       if (TREE_CONSTANT (size))
        error ("type size can't be explicitly evaluated");
@@ -131,16 +197,13 @@ variable_size (size)
     }
 
   if (immediate_size_expand)
-    /* NULL_RTX is not defined; neither is the rtx type. 
-       Also, we would like to pass const0_rtx here, but don't have it.  */
-    expand_expr (size, expand_expr (integer_zero_node, NULL_PTR, VOIDmode, 0),
-                VOIDmode, 0);
+    expand_expr (save, const0_rtx, VOIDmode, 0);
   else if (cfun != 0 && cfun->x_dont_save_pending_sizes_p)
     /* The front-end doesn't want us to keep a list of the expressions
        that determine sizes for variable size objects.  */
     ;
-  else if (TREE_CODE (size) == SAVE_EXPR)
-    pending_sizes = tree_cons (NULL_TREE, size, pending_sizes);
+  else
+    put_pending_size (save);
 
   return size;
 }
@@ -160,7 +223,7 @@ mode_for_size (size, class, limit)
      enum mode_class class;
      int limit;
 {
-  register enum machine_mode mode;
+  enum machine_mode mode;
 
   if (limit && size > MAX_FIXED_MODE_SIZE)
     return BLKmode;
@@ -200,7 +263,7 @@ smallest_mode_for_size (size, class)
      unsigned int size;
      enum mode_class class;
 {
-  register enum machine_mode mode;
+  enum machine_mode mode;
 
   /* Get the first mode which has at least this size, in the
      specified class.  */
@@ -227,14 +290,16 @@ int_mode_for_mode (mode)
     case MODE_COMPLEX_INT:
     case MODE_COMPLEX_FLOAT:
     case MODE_FLOAT:
+    case MODE_VECTOR_INT:
+    case MODE_VECTOR_FLOAT:
       mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
       break;
 
     case MODE_RANDOM:
       if (mode == BLKmode)
-        break;
+       break;
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case MODE_CC:
     default:
@@ -244,6 +309,29 @@ int_mode_for_mode (mode)
   return mode;
 }
 
+/* Return the alignment of MODE. This will be bounded by 1 and
+   BIGGEST_ALIGNMENT.  */
+
+unsigned int
+get_mode_alignment (mode)
+     enum machine_mode mode;
+{
+  unsigned int alignment;
+
+  if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+      || GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
+    alignment = GET_MODE_UNIT_SIZE (mode);
+  else
+    alignment = GET_MODE_SIZE (mode);
+
+  /* Extract the LSB of the size.  */
+  alignment = alignment & -alignment;
+  alignment *= BITS_PER_UNIT;
+
+  alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
+  return alignment;
+}
+
 /* Return the value of VALUE, rounded up to a multiple of DIVISOR.
    This can only be applied to objects of a sizetype.  */
 
@@ -287,8 +375,8 @@ layout_decl (decl, known_align)
      tree decl;
      unsigned int known_align;
 {
-  register tree type = TREE_TYPE (decl);
-  register enum tree_code code = TREE_CODE (decl);
+  tree type = TREE_TYPE (decl);
+  enum tree_code code = TREE_CODE (decl);
 
   if (code == CONST_DECL)
     return;
@@ -330,9 +418,9 @@ layout_decl (decl, known_align)
       && (DECL_ALIGN (decl) == 0
          || (! (code == FIELD_DECL && DECL_PACKED (decl))
              && TYPE_ALIGN (type) > DECL_ALIGN (decl))))
-    {        
+    {
       DECL_ALIGN (decl) = TYPE_ALIGN (type);
-      DECL_USER_ALIGN (decl) = TYPE_USER_ALIGN (type);
+      DECL_USER_ALIGN (decl) = 0;
     }
 
   /* For fields, set the bit field type and update the alignment.  */
@@ -341,14 +429,22 @@ layout_decl (decl, known_align)
       DECL_BIT_FIELD_TYPE (decl) = DECL_BIT_FIELD (decl) ? type : 0;
       if (maximum_field_alignment != 0)
        DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), maximum_field_alignment);
-      else if (DECL_PACKED (decl))
+
+      /* If the field is of variable size, we can't misalign it since we
+        have no way to make a temporary to align the result.  But this
+        isn't an issue if the decl is not addressable.  Likewise if it
+        is of unknown size.  */
+      else if (DECL_PACKED (decl)
+              && (DECL_NONADDRESSABLE_P (decl)
+                  || DECL_SIZE_UNIT (decl) == 0
+                  || TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST))
        {
          DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
          DECL_USER_ALIGN (decl) = 0;
        }
     }
 
-  /* See if we can use an ordinary integer mode for a bit-field. 
+  /* See if we can use an ordinary integer mode for a bit-field.
      Conditions are: a fixed size that is correct for another mode
      and occupying a complete byte or bytes on proper boundary.  */
   if (code == FIELD_DECL && DECL_BIT_FIELD (decl)
@@ -356,7 +452,7 @@ layout_decl (decl, known_align)
       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
       && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
     {
-      register enum machine_mode xmode
+      enum machine_mode xmode
        = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1);
 
       if (xmode != BLKmode && known_align >= GET_MODE_ALIGNMENT (xmode))
@@ -404,10 +500,22 @@ layout_decl (decl, known_align)
     }
 }
 \f
+/* Hook for a front-end function that can modify the record layout as needed
+   immediately before it is finalized.  */
+
+void (*lang_adjust_rli) PARAMS ((record_layout_info)) = 0;
+
+void
+set_lang_adjust_rli (f)
+     void (*f) PARAMS ((record_layout_info));
+{
+  lang_adjust_rli = f;
+}
+
 /* Begin laying out type T, which may be a RECORD_TYPE, UNION_TYPE, or
    QUAL_UNION_TYPE.  Return a pointer to a struct record_layout_info which
    is to be passed to all other layout functions for this record.  It is the
-   responsibility of the caller to call `free' for the storage returned. 
+   responsibility of the caller to call `free' for the storage returned.
    Note that garbage collection is not permitted until we finish laying
    out the record.  */
 
@@ -415,7 +523,7 @@ record_layout_info
 start_record_layout (t)
      tree t;
 {
-  record_layout_info rli 
+  record_layout_info rli
     = (record_layout_info) xmalloc (sizeof (struct record_layout_info_s));
 
   rli->t = t;
@@ -424,17 +532,18 @@ start_record_layout (t)
      declaration, for example) use it -- otherwise, start with a
      one-byte alignment.  */
   rli->record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (t));
-  rli->unpacked_align = rli->record_align;
+  rli->unpacked_align = rli->unpadded_align = rli->record_align;
   rli->offset_align = MAX (rli->record_align, BIGGEST_ALIGNMENT);
 
 #ifdef STRUCTURE_SIZE_BOUNDARY
   /* Packed structures don't need to have minimum size.  */
   if (! TYPE_PACKED (t))
-    rli->record_align = MAX (rli->record_align, STRUCTURE_SIZE_BOUNDARY);
+    rli->record_align = MAX (rli->record_align, (unsigned) STRUCTURE_SIZE_BOUNDARY);
 #endif
 
   rli->offset = size_zero_node;
   rli->bitpos = bitsize_zero_node;
+  rli->prev_field = 0;
   rli->pending_statics = 0;
   rli->packed_maybe_necessary = 0;
 
@@ -464,25 +573,6 @@ byte_from_pos (offset, bitpos)
 }
 
 void
-pos_from_byte (poffset, pbitpos, off_align, pos)
-     tree *poffset, *pbitpos;
-     unsigned int off_align;
-     tree pos;
-{
-  *poffset
-    = size_binop (MULT_EXPR,
-                 convert (sizetype,
-                          size_binop (FLOOR_DIV_EXPR, pos,
-                                      bitsize_int (off_align
-                                                   / BITS_PER_UNIT))),
-                 size_int (off_align / BITS_PER_UNIT));
-  *pbitpos = size_binop (MULT_EXPR,
-                        size_binop (FLOOR_MOD_EXPR, pos,
-                                    bitsize_int (off_align / BITS_PER_UNIT)),
-                        bitsize_unit_node);
-}
-
-void
 pos_from_bit (poffset, pbitpos, off_align, pos)
      tree *poffset, *pbitpos;
      unsigned int off_align;
@@ -515,7 +605,7 @@ normalize_offset (poffset, pbitpos, off_align)
        = size_binop (PLUS_EXPR, *poffset,
                      size_binop (MULT_EXPR, convert (sizetype, extra_aligns),
                                  size_int (off_align / BITS_PER_UNIT)));
-                               
+
       *pbitpos
        = size_binop (FLOOR_MOD_EXPR, *pbitpos, bitsize_int (off_align));
     }
@@ -531,8 +621,9 @@ debug_rli (rli)
   print_node_brief (stderr, "\noffset", rli->offset, 0);
   print_node_brief (stderr, " bitpos", rli->bitpos, 0);
 
-  fprintf (stderr, "\nrec_align = %u, unpack_align = %u, off_align = %u\n",
-          rli->record_align, rli->unpacked_align, rli->offset_align);
+  fprintf (stderr, "\naligns: rec = %u, unpack = %u, unpad = %u, off = %u\n",
+          rli->record_align, rli->unpacked_align, rli->unpadded_align,
+          rli->offset_align);
   if (rli->packed_maybe_necessary)
     fprintf (stderr, "packed may be necessary\n");
 
@@ -571,53 +662,184 @@ rli_size_so_far (rli)
   return bit_from_pos (rli->offset, rli->bitpos);
 }
 
-/* Called from place_field to handle unions.  */
+/* FIELD is about to be added to RLI->T.  The alignment (in bits) of
+   the next available location is given by KNOWN_ALIGN.  Update the
+   variable alignment fields in RLI, and return the alignment to give
+   the FIELD.  */
 
-static void
-place_union_field (rli, field)
+static unsigned int
+update_alignment_for_field (rli, field, known_align)
      record_layout_info rli;
      tree field;
+     unsigned int known_align;
 {
+  /* The alignment required for FIELD.  */
   unsigned int desired_align;
+  /* The type of this field.  */
+  tree type = TREE_TYPE (field);
+  /* True if the field was explicitly aligned by the user.  */
+  bool user_align;
 
-  layout_decl (field, 0);
-  
-  DECL_FIELD_OFFSET (field) = size_zero_node;
-  DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
-  SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
-
+  /* Lay out the field so we know what alignment it needs.  For a
+     packed field, use the alignment as specified, disregarding what
+     the type would want.  */
   desired_align = DECL_ALIGN (field);
+  user_align = DECL_USER_ALIGN (field);
+  layout_decl (field, known_align);
+  if (! DECL_PACKED (field))
+    {
+      desired_align = DECL_ALIGN (field);
+      user_align = DECL_USER_ALIGN (field);
+    }
 
-#ifdef BIGGEST_FIELD_ALIGNMENT
-  /* Some targets (i.e. i386) limit union field alignment
+  /* Some targets (i.e. i386, VMS) limit struct field alignment
      to a lower boundary than alignment of variables unless
      it was overridden by attribute aligned.  */
-  if (! DECL_USER_ALIGN (field))
-    desired_align =
-      MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
+#ifdef BIGGEST_FIELD_ALIGNMENT
+  if (!user_align)
+    desired_align
+      = MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
 #endif
 
-  /* Union must be at least as aligned as any field requires.  */
-  rli->record_align = MAX (rli->record_align, desired_align);
+#ifdef ADJUST_FIELD_ALIGN
+  if (!user_align)
+    desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
+#endif
 
+  /* Record must have at least as much alignment as any field.
+     Otherwise, the alignment of the field within the record is
+     meaningless.  */
+  if ((* targetm.ms_bitfield_layout_p) (rli->t)
+      && type != error_mark_node
+      && DECL_BIT_FIELD_TYPE (field)
+      && ! integer_zerop (TYPE_SIZE (type)))
+    {
+      /* Here, the alignment of the underlying type of a bitfield can
+        affect the alignment of a record; even a zero-sized field
+        can do this.  The alignment should be to the alignment of
+        the type, except that for zero-size bitfields this only
+        applies if there was an immediately prior, nonzero-size
+        bitfield.  (That's the way it is, experimentally.) */
+      if (! integer_zerop (DECL_SIZE (field))
+         ? ! DECL_PACKED (field)
+         : (rli->prev_field
+            && DECL_BIT_FIELD_TYPE (rli->prev_field)
+            && ! integer_zerop (DECL_SIZE (rli->prev_field))))
+       {
+         unsigned int type_align = TYPE_ALIGN (type);
+         type_align = MAX (type_align, desired_align);
+         if (maximum_field_alignment != 0)
+           type_align = MIN (type_align, maximum_field_alignment);
+         rli->record_align = MAX (rli->record_align, type_align);
+         rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+         rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+       }
+      else
+       desired_align = 1;
+    }
+  else
 #ifdef PCC_BITFIELD_TYPE_MATTERS
-  /* On the m88000, a bit field of declare type `int' forces the
-     entire union to have `int' alignment.  */
-  if (PCC_BITFIELD_TYPE_MATTERS && DECL_BIT_FIELD_TYPE (field))
-    rli->record_align = MAX (rli->record_align, 
-                            TYPE_ALIGN (TREE_TYPE (field)));
+  if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
+      && ! (* targetm.ms_bitfield_layout_p) (rli->t)
+      && DECL_BIT_FIELD_TYPE (field)
+      && ! integer_zerop (TYPE_SIZE (type)))
+    {
+      /* A zero-length bit-field affects the alignment of the next
+        field.  */
+      if (!DECL_PACKED (field) && integer_zerop (DECL_SIZE (field)))
+       {
+         desired_align = TYPE_ALIGN (type);
+#ifdef ADJUST_FIELD_ALIGN
+         desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
 #endif
+       }
+
+      /* Named bit-fields cause the entire structure to have the
+        alignment implied by their type.  */
+      if (DECL_NAME (field) != 0)
+       {
+         unsigned int type_align = TYPE_ALIGN (type);
+
+#ifdef ADJUST_FIELD_ALIGN
+         if (! TYPE_USER_ALIGN (type))
+           type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
+         if (maximum_field_alignment != 0)
+           type_align = MIN (type_align, maximum_field_alignment);
+         else if (DECL_PACKED (field))
+           type_align = MIN (type_align, BITS_PER_UNIT);
+
+         /* The alignment of the record is increased to the maximum
+            of the current alignment, the alignment indicated on the
+            field (i.e., the alignment specified by an __aligned__
+            attribute), and the alignment indicated by the type of
+            the field.  */
+         rli->record_align = MAX (rli->record_align, desired_align);
+         rli->record_align = MAX (rli->record_align, type_align);
+
+         rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+         if (warn_packed)
+           rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+         user_align |= TYPE_USER_ALIGN (type);
+       }
+    }
+  else
+#endif
+    {
+      rli->record_align = MAX (rli->record_align, desired_align);
+      rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
+      rli->unpadded_align = MAX (rli->unpadded_align, DECL_ALIGN (field));
+    }
+
+  TYPE_USER_ALIGN (rli->t) |= user_align;
+
+  return desired_align;
+}
+
+/* Called from place_field to handle unions.  */
+
+static void
+place_union_field (rli, field)
+     record_layout_info rli;
+     tree field;
+{
+  update_alignment_for_field (rli, field, /*known_align=*/0);
+
+  DECL_FIELD_OFFSET (field) = size_zero_node;
+  DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
+  SET_DECL_OFFSET_ALIGN (field, BIGGEST_ALIGNMENT);
 
   /* We assume the union's size will be a multiple of a byte so we don't
      bother with BITPOS.  */
   if (TREE_CODE (rli->t) == UNION_TYPE)
     rli->offset = size_binop (MAX_EXPR, rli->offset, DECL_SIZE_UNIT (field));
   else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
-    rli->offset = fold (build (COND_EXPR, sizetype, 
+    rli->offset = fold (build (COND_EXPR, sizetype,
                               DECL_QUALIFIER (field),
                               DECL_SIZE_UNIT (field), rli->offset));
 }
 
+#if defined (PCC_BITFIELD_TYPE_MATTERS) || defined (BITFIELD_NBYTES_LIMITED)
+/* A bitfield of SIZE with a required access alignment of ALIGN is allocated
+   at BYTE_OFFSET / BIT_OFFSET.  Return nonzero if the field would span more
+   units of alignment than the underlying TYPE.  */
+static int
+excess_unit_span (byte_offset, bit_offset, size, align, type)
+     HOST_WIDE_INT byte_offset, bit_offset, size, align;
+     tree type;
+{
+  /* Note that the calculation of OFFSET might overflow; we calculate it so
+     that we still get the right result as long as ALIGN is a power of two.  */
+  unsigned HOST_WIDE_INT offset = byte_offset * BITS_PER_UNIT + bit_offset;
+
+  offset = offset % align;
+  return ((offset + size + align - 1) / align
+         > ((unsigned HOST_WIDE_INT) tree_low_cst (TYPE_SIZE (type), 1)
+            / align));
+}
+#endif
+
 /* RLI contains information about the layout of a RECORD_TYPE.  FIELD
    is a FIELD_DECL to be added after those fields already present in
    T.  (FIELD is not actually added to the TYPE_FIELDS list here;
@@ -634,10 +856,9 @@ place_field (rli, field)
      record as it presently stands.  */
   unsigned int known_align;
   unsigned int actual_align;
-  unsigned int user_align;
   /* The type of this field.  */
   tree type = TREE_TYPE (field);
+
   if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
       return;
 
@@ -678,71 +899,8 @@ place_field (rli, field)
                      & - tree_low_cst (rli->offset, 1)));
   else
     known_align = rli->offset_align;
-
-  /* Lay out the field so we know what alignment it needs.  For a
-     packed field, use the alignment as specified, disregarding what
-     the type would want.  */
-  desired_align = DECL_ALIGN (field);
-  user_align = DECL_USER_ALIGN (field);
-  layout_decl (field, known_align);
-  if (! DECL_PACKED (field))
-    {
-      desired_align = DECL_ALIGN (field);
-      user_align = DECL_USER_ALIGN (field);
-    }
-
-#ifdef BIGGEST_FIELD_ALIGNMENT
-  /* Some targets (i.e. i386, VMS) limit struct field alignment
-     to a lower boundary than alignment of variables unless
-     it was overridden by attribute aligned.  */
-  if (! user_align)
-    desired_align =
-      MIN (desired_align, (unsigned) BIGGEST_FIELD_ALIGNMENT);
-#endif
-#ifdef ADJUST_FIELD_ALIGN
-  desired_align = ADJUST_FIELD_ALIGN (field, desired_align);
-#endif
-
-  /* Record must have at least as much alignment as any field.
-     Otherwise, the alignment of the field within the record is
-     meaningless.  */
-#ifdef PCC_BITFIELD_TYPE_MATTERS
-  if (PCC_BITFIELD_TYPE_MATTERS && type != error_mark_node
-      && DECL_BIT_FIELD_TYPE (field)
-      && ! integer_zerop (TYPE_SIZE (type)))
-    {
-      /* For these machines, a zero-length field does not
-        affect the alignment of the structure as a whole.
-        It does, however, affect the alignment of the next field
-        within the structure.  */
-      if (! integer_zerop (DECL_SIZE (field)))
-       rli->record_align = MAX (rli->record_align, desired_align);
-      else if (! DECL_PACKED (field))
-       desired_align = TYPE_ALIGN (type);
-
-      /* A named bit field of declared type `int'
-        forces the entire structure to have `int' alignment.  */
-      if (DECL_NAME (field) != 0)
-       {
-         unsigned int type_align = TYPE_ALIGN (type);
-
-         if (maximum_field_alignment != 0)
-           type_align = MIN (type_align, maximum_field_alignment);
-         else if (DECL_PACKED (field))
-           type_align = MIN (type_align, BITS_PER_UNIT);
-
-         rli->record_align = MAX (rli->record_align, type_align);
-         if (warn_packed)
-           rli->unpacked_align = MAX (rli->unpacked_align, 
-                                      TYPE_ALIGN (type));
-       }
-    }
-  else
-#endif
-    {
-      rli->record_align = MAX (rli->record_align, desired_align);
-      rli->unpacked_align = MAX (rli->unpacked_align, TYPE_ALIGN (type));
-    }
+  
+  desired_align = update_alignment_for_field (rli, field, known_align);
 
   if (warn_packed && DECL_PACKED (field))
     {
@@ -796,6 +954,7 @@ place_field (rli, field)
      variable-sized fields, we need not worry about compatibility.  */
 #ifdef PCC_BITFIELD_TYPE_MATTERS
   if (PCC_BITFIELD_TYPE_MATTERS
+      && ! (* targetm.ms_bitfield_layout_p) (rli->t)
       && TREE_CODE (field) == FIELD_DECL
       && type != error_mark_node
       && DECL_BIT_FIELD (field)
@@ -812,19 +971,23 @@ place_field (rli, field)
       HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
       HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
 
+#ifdef ADJUST_FIELD_ALIGN
+      if (! TYPE_USER_ALIGN (type))
+       type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
       /* A bit field may not span more units of alignment of its type
         than its type itself.  Advance to next boundary if necessary.  */
-      if ((((offset * BITS_PER_UNIT + bit_offset + field_size +
-            type_align - 1)
-           / type_align)
-          - (offset * BITS_PER_UNIT + bit_offset) / type_align)
-         > tree_low_cst (TYPE_SIZE (type), 1) / type_align)
+      if (excess_unit_span (offset, bit_offset, field_size, type_align, type))
        rli->bitpos = round_up (rli->bitpos, type_align);
+
+      TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
     }
 #endif
 
 #ifdef BITFIELD_NBYTES_LIMITED
   if (BITFIELD_NBYTES_LIMITED
+      && ! (* targetm.ms_bitfield_layout_p) (rli->t)
       && TREE_CODE (field) == FIELD_DECL
       && type != error_mark_node
       && DECL_BIT_FIELD_TYPE (field)
@@ -840,6 +1003,11 @@ place_field (rli, field)
       HOST_WIDE_INT offset = tree_low_cst (rli->offset, 0);
       HOST_WIDE_INT bit_offset = tree_low_cst (rli->bitpos, 0);
 
+#ifdef ADJUST_FIELD_ALIGN
+      if (! TYPE_USER_ALIGN (type))
+       type_align = ADJUST_FIELD_ALIGN (field, type_align);
+#endif
+
       if (maximum_field_alignment != 0)
        type_align = MIN (type_align, maximum_field_alignment);
       /* ??? This test is opposite the test in the containing if
@@ -849,15 +1017,158 @@ place_field (rli, field)
 
       /* A bit field may not span the unit of alignment of its type.
         Advance to next boundary if necessary.  */
-      /* ??? This code should match the code above for the
-        PCC_BITFIELD_TYPE_MATTERS case.  */
-      if ((offset * BITS_PER_UNIT + bit_offset) / type_align
-         != ((offset * BITS_PER_UNIT + bit_offset + field_size - 1)
-             / type_align))
+      if (excess_unit_span (offset, bit_offset, field_size, type_align, type))
        rli->bitpos = round_up (rli->bitpos, type_align);
+
+      TYPE_USER_ALIGN (rli->t) |= TYPE_USER_ALIGN (type);
     }
 #endif
 
+  /* See the docs for TARGET_MS_BITFIELD_LAYOUT_P for details.
+     A subtlety:
+       When a bit field is inserted into a packed record, the whole
+       size of the underlying type is used by one or more same-size
+       adjacent bitfields.  (That is, if its long:3, 32 bits is
+       used in the record, and any additional adjacent long bitfields are
+       packed into the same chunk of 32 bits. However, if the size
+       changes, a new field of that size is allocated.)  In an unpacked
+       record, this is the same as using alignment, but not equivalent
+       when packing.
+
+     Note: for compatibility, we use the type size, not the type alignment
+     to determine alignment, since that matches the documentation */
+
+  if ((* targetm.ms_bitfield_layout_p) (rli->t)
+       && ((DECL_BIT_FIELD_TYPE (field) && ! DECL_PACKED (field))
+         || (rli->prev_field && ! DECL_PACKED (rli->prev_field))))
+    {
+      /* At this point, either the prior or current are bitfields,
+        (possibly both), and we're dealing with MS packing.  */
+      tree prev_saved = rli->prev_field;
+
+      /* Is the prior field a bitfield?  If so, handle "runs" of same
+        type size fields.  */
+      if (rli->prev_field /* necessarily a bitfield if it exists.  */)
+       {
+         /* If both are bitfields, nonzero, and the same size, this is
+            the middle of a run.  Zero declared size fields are special
+            and handled as "end of run". (Note: it's nonzero declared
+            size, but equal type sizes!) (Since we know that both
+            the current and previous fields are bitfields by the
+            time we check it, DECL_SIZE must be present for both.) */
+         if (DECL_BIT_FIELD_TYPE (field)
+             && !integer_zerop (DECL_SIZE (field))
+             && !integer_zerop (DECL_SIZE (rli->prev_field))
+             && simple_cst_equal (TYPE_SIZE (type),
+                  TYPE_SIZE (TREE_TYPE (rli->prev_field))) )
+           {
+             /* We're in the middle of a run of equal type size fields; make
+                sure we realign if we run out of bits.  (Not decl size,
+                type size!) */
+             int bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
+             tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_field));
+
+             if (rli->remaining_in_alignment < bitsize)
+               {
+                 /* out of bits; bump up to next 'word'.  */
+                 rli->offset = DECL_FIELD_OFFSET (rli->prev_field);
+                 rli->bitpos = size_binop (PLUS_EXPR,
+                                     type_size,
+                                     DECL_FIELD_BIT_OFFSET(rli->prev_field));
+                 rli->prev_field = field;
+                 rli->remaining_in_alignment = TREE_INT_CST_LOW (type_size);
+               }
+             rli->remaining_in_alignment -= bitsize;
+           }
+         else
+           {
+             /* End of a run: if leaving a run of bitfields of the same type
+                size, we have to "use up" the rest of the bits of the type
+                size.
+
+                Compute the new position as the sum of the size for the prior
+                type and where we first started working on that type.
+                Note: since the beginning of the field was aligned then
+                of course the end will be too.  No round needed.  */
+
+             if (!integer_zerop (DECL_SIZE (rli->prev_field)))
+               {
+                 tree type_size = TYPE_SIZE(TREE_TYPE(rli->prev_field));
+                 rli->bitpos = size_binop (PLUS_EXPR,
+                                     type_size,
+                                     DECL_FIELD_BIT_OFFSET(rli->prev_field));
+               }
+             else
+               {
+                 /* We "use up" size zero fields; the code below should behave
+                    as if the prior field was not a bitfield.  */
+                 prev_saved = NULL;
+               }
+
+             /* Cause a new bitfield to be captured, either this time (if
+                currently a bitfield) or next time we see one.  */
+             if (!DECL_BIT_FIELD_TYPE(field)
+                || integer_zerop (DECL_SIZE (field)))
+               {
+                 rli->prev_field = NULL;
+               }
+           }
+         normalize_rli (rli);
+        }
+
+      /* If we're starting a new run of same size type bitfields
+        (or a run of non-bitfields), set up the "first of the run"
+        fields.
+
+        That is, if the current field is not a bitfield, or if there
+        was a prior bitfield the type sizes differ, or if there wasn't
+        a prior bitfield the size of the current field is nonzero.
+
+        Note: we must be sure to test ONLY the type size if there was
+        a prior bitfield and ONLY for the current field being zero if
+        there wasn't.  */
+
+      if (!DECL_BIT_FIELD_TYPE (field)
+         || ( prev_saved != NULL
+              ? !simple_cst_equal (TYPE_SIZE (type),
+                     TYPE_SIZE (TREE_TYPE (prev_saved)))
+              : !integer_zerop (DECL_SIZE (field)) ))
+       {
+         unsigned int type_align = 8;  /* Never below 8 for compatibility */
+
+         /* (When not a bitfield), we could be seeing a flex array (with
+            no DECL_SIZE).  Since we won't be using remaining_in_alignment
+            until we see a bitfield (and come by here again) we just skip
+            calculating it.  */
+
+         if (DECL_SIZE (field) != NULL)
+             rli->remaining_in_alignment
+                 = TREE_INT_CST_LOW (TYPE_SIZE(TREE_TYPE(field)))
+                   - TREE_INT_CST_LOW (DECL_SIZE (field));
+
+         /* Now align (conventionally) for the new type.  */
+         if (!DECL_PACKED(field))
+             type_align = MAX(TYPE_ALIGN (type), type_align);
+
+         if (prev_saved
+             && DECL_BIT_FIELD_TYPE (prev_saved)
+             /* If the previous bit-field is zero-sized, we've already
+                accounted for its alignment needs (or ignored it, if
+                appropriate) while placing it.  */
+             && ! integer_zerop (DECL_SIZE (prev_saved)))
+           type_align = MAX (type_align,
+                             TYPE_ALIGN (TREE_TYPE (prev_saved)));
+
+         if (maximum_field_alignment != 0)
+           type_align = MIN (type_align, maximum_field_alignment);
+
+         rli->bitpos = round_up (rli->bitpos, type_align);
+          /* If we really aligned, don't allow subsequent bitfields
+            to undo that.  */
+         rli->prev_field = NULL;
+       }
+    }
+
   /* Offset so far becomes the position of this field after normalizing.  */
   normalize_rli (rli);
   DECL_FIELD_OFFSET (field) = rli->offset;
@@ -882,6 +1193,10 @@ place_field (rli, field)
   if (known_align != actual_align)
     layout_decl (field, actual_align);
 
+  /* Only the MS bitfields use this.  */
+  if (rli->prev_field == NULL && DECL_BIT_FIELD_TYPE(field))
+      rli->prev_field = field;
+
   /* Now add size of this field to the size of the record.  If the size is
      not constant, treat the field as being a multiple of bytes and just
      adjust the offset, resetting the bit position.  Otherwise, apportion the
@@ -891,7 +1206,8 @@ place_field (rli, field)
      is printed in finish_struct.  */
   if (DECL_SIZE (field) == 0)
     /* Do nothing.  */;
-  else if (! TREE_CONSTANT (DECL_SIZE_UNIT (field)))
+  else if (TREE_CODE (DECL_SIZE_UNIT (field)) != INTEGER_CST
+          || TREE_CONSTANT_OVERFLOW (DECL_SIZE_UNIT (field)))
     {
       rli->offset
        = size_binop (PLUS_EXPR, rli->offset,
@@ -912,7 +1228,7 @@ place_field (rli, field)
 
 /* Assuming that all the fields have been laid out, this function uses
    RLI to compute the final TYPE_SIZE, TYPE_ALIGN, etc. for the type
-   inidicated by RLI.  */
+   indicated by RLI.  */
 
 static void
 finalize_record_size (rli)
@@ -932,7 +1248,6 @@ finalize_record_size (rli)
 #else
   TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
 #endif
-  TYPE_USER_ALIGN (rli->t) = 1;
 
   /* Compute the size so far.  Be sure to allow for extra bits in the
      size in bytes.  We have guaranteed above that it will be no more
@@ -943,15 +1258,7 @@ finalize_record_size (rli)
     unpadded_size_unit
       = size_binop (PLUS_EXPR, unpadded_size_unit, size_one_node);
 
-  /* Record the un-rounded size in the binfo node.  But first we check
-     the size of TYPE_BINFO to make sure that BINFO_SIZE is available.  */
-  if (TYPE_BINFO (rli->t) && TREE_VEC_LENGTH (TYPE_BINFO (rli->t)) > 6)
-    {
-      TYPE_BINFO_SIZE (rli->t) = unpadded_size;
-      TYPE_BINFO_SIZE_UNIT (rli->t) = unpadded_size_unit;
-    }
-
-    /* Round the size up to be a multiple of the required alignment */
+  /* Round the size up to be a multiple of the required alignment */
 #ifdef ROUND_TYPE_SIZE
   TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, unpadded_size,
                                        TYPE_ALIGN (rli->t));
@@ -967,7 +1274,7 @@ finalize_record_size (rli)
   if (warn_padded && TREE_CONSTANT (unpadded_size)
       && simple_cst_equal (unpadded_size, TYPE_SIZE (rli->t)) == 0)
     warning ("padding struct size to alignment boundary");
-  
+
   if (warn_packed && TREE_CODE (rli->t) == RECORD_TYPE
       && TYPE_PACKED (rli->t) && ! rli->packed_maybe_necessary
       && TREE_CONSTANT (unpadded_size))
@@ -1049,11 +1356,12 @@ compute_record_mode (type)
          || (TYPE_MODE (TREE_TYPE (field)) == BLKmode
              && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
          || ! host_integerp (bit_position (field), 1)
+         || DECL_SIZE (field) == 0
          || ! host_integerp (DECL_SIZE (field), 1))
        return;
 
       bitpos = int_bit_position (field);
-         
+
       /* Must be BLKmode if any field crosses a word boundary,
         since extract_bit_field can't handle that in registers.  */
       if (bitpos / BITS_PER_WORD
@@ -1069,12 +1377,13 @@ compute_record_mode (type)
       if (simple_cst_equal (TYPE_SIZE (type), DECL_SIZE (field)))
        mode = DECL_MODE (field);
 
-#ifdef STRUCT_FORCE_BLK
+#ifdef MEMBER_TYPE_FORCES_BLK
       /* With some targets, eg. c4x, it is sub-optimal
         to access an aligned BLKmode structure as a scalar.  */
-      if (mode == VOIDmode && STRUCT_FORCE_BLK (field))
+
+      if (MEMBER_TYPE_FORCES_BLK (field, mode))
        return;
-#endif /* STRUCT_FORCE_BLK  */
+#endif /* MEMBER_TYPE_FORCES_BLK  */
     }
 
   /* If we only have one real field; use its mode.  This only applies to
@@ -1187,11 +1496,14 @@ finalize_type_size (type)
 
 /* Do all of the work required to layout the type indicated by RLI,
    once the fields have been laid out.  This function will call `free'
-   for RLI.  */
+   for RLI, unless FREE_P is false.  Passing a value other than false
+   for FREE_P is bad practice; this option only exists to support the
+   G++ 3.2 ABI.  */
 
 void
-finish_record_layout (rli)
+finish_record_layout (rli, free_p)
      record_layout_info rli;
+     int free_p;
 {
   /* Compute the final size.  */
   finalize_record_size (rli);
@@ -1211,9 +1523,50 @@ finish_record_layout (rli)
     }
 
   /* Clean up.  */
-  free (rli);
+  if (free_p)
+    free (rli);
 }
 \f
+
+/* Finish processing a builtin RECORD_TYPE type TYPE.  It's name is
+   NAME, its fields are chained in reverse on FIELDS.
+
+   If ALIGN_TYPE is non-null, it is given the same alignment as
+   ALIGN_TYPE.  */
+
+void
+finish_builtin_struct (type, name, fields, align_type)
+     tree type;
+     const char *name;
+     tree fields;
+     tree align_type;
+{
+  tree tail, next;
+
+  for (tail = NULL_TREE; fields; tail = fields, fields = next)
+    {
+      DECL_FIELD_CONTEXT (fields) = type;
+      next = TREE_CHAIN (fields);
+      TREE_CHAIN (fields) = tail;
+    }
+  TYPE_FIELDS (type) = tail;
+
+  if (align_type)
+    {
+      TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
+      TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);
+    }
+
+  layout_type (type);
+#if 0 /* not yet, should get fixed properly later */
+  TYPE_NAME (type) = make_type_decl (get_identifier (name), type);
+#else
+  TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);
+#endif
+  TYPE_STUB_DECL (type) = TYPE_NAME (type);
+  layout_decl (TYPE_NAME (type), 0);
+}
+
 /* Calculate the mode, size, and alignment for TYPE.
    For an array type, calculate the element separation as well.
    Record TYPE on the chain of permanent or temporary types
@@ -1242,11 +1595,11 @@ layout_type (type)
         of the language-specific code.  */
       abort ();
 
-    case BOOLEAN_TYPE:  /* Used for Java, Pascal, and Chill. */
+    case BOOLEAN_TYPE:  /* Used for Java, Pascal, and Chill.  */
       if (TYPE_PRECISION (type) == 0)
-       TYPE_PRECISION (type) = 1; /* default to one byte/boolean. */
+       TYPE_PRECISION (type) = 1; /* default to one byte/boolean.  */
 
-      /* ... fall through ... */
+      /* ... fall through ...  */
 
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
@@ -1299,7 +1652,9 @@ layout_type (type)
     case OFFSET_TYPE:
       TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
       TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
-      TYPE_MODE (type) = ptr_mode;
+      /* A pointer might be MODE_PARTIAL_INT,
+        but ptrdiff_t must be integral.  */
+      TYPE_MODE (type) = mode_for_size (POINTER_SIZE, MODE_INT, 0);
       break;
 
     case FUNCTION_TYPE:
@@ -1311,17 +1666,25 @@ layout_type (type)
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
-      TYPE_MODE (type) = ptr_mode;
-      TYPE_SIZE (type) = bitsize_int (POINTER_SIZE);
-      TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
-      TREE_UNSIGNED (type) = 1;
-      TYPE_PRECISION (type) = POINTER_SIZE;
+      {
+
+       enum machine_mode mode = ((TREE_CODE (type) == REFERENCE_TYPE
+                                  && reference_types_internal)
+                                 ? Pmode : TYPE_MODE (type));
+
+       int nbits = GET_MODE_BITSIZE (mode);
+
+       TYPE_SIZE (type) = bitsize_int (nbits);
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (mode));
+       TREE_UNSIGNED (type) = 1;
+       TYPE_PRECISION (type) = nbits;
+      }
       break;
 
     case ARRAY_TYPE:
       {
-       register tree index = TYPE_DOMAIN (type);
-       register tree element = TREE_TYPE (type);
+       tree index = TYPE_DOMAIN (type);
+       tree element = TREE_TYPE (type);
 
        build_pointer_type (element);
 
@@ -1384,6 +1747,7 @@ layout_type (type)
 #else
        TYPE_ALIGN (type) = MAX (TYPE_ALIGN (element), BITS_PER_UNIT);
 #endif
+       TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (element);
 
 #ifdef ROUND_TYPE_SIZE
        if (TYPE_SIZE (type) != 0)
@@ -1402,13 +1766,21 @@ layout_type (type)
 
        TYPE_MODE (type) = BLKmode;
        if (TYPE_SIZE (type) != 0
+#ifdef MEMBER_TYPE_FORCES_BLK
+           && ! MEMBER_TYPE_FORCES_BLK (type, VOIDmode)
+#endif
            /* BLKmode elements force BLKmode aggregate;
               else extract/store fields may lose.  */
            && (TYPE_MODE (TREE_TYPE (type)) != BLKmode
                || TYPE_NO_FORCE_BLK (TREE_TYPE (type))))
          {
-           TYPE_MODE (type)
-             = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
+           /* One-element arrays get the component type's mode.  */
+           if (simple_cst_equal (TYPE_SIZE (type),
+                                 TYPE_SIZE (TREE_TYPE (type))))
+             TYPE_MODE (type) = TYPE_MODE (TREE_TYPE (type));
+           else
+             TYPE_MODE (type)
+               = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
 
            if (TYPE_MODE (type) != BLKmode
                && STRICT_ALIGNMENT && TYPE_ALIGN (type) < BIGGEST_ALIGNMENT
@@ -1445,15 +1817,18 @@ layout_type (type)
        if (TREE_CODE (type) == QUAL_UNION_TYPE)
          TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
 
+       if (lang_adjust_rli)
+         (*lang_adjust_rli) (rli);
+
        /* Finish laying out the record.  */
-       finish_record_layout (rli);
+       finish_record_layout (rli, /*free_p=*/true);
       }
       break;
 
-    case SET_TYPE:  /* Used by Chill and Pascal. */
+    case SET_TYPE:  /* Used by Chill and Pascal.  */
       if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
          || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)
-       abort();
+       abort ();
       else
        {
 #ifndef SET_WORD_SIZE
@@ -1495,7 +1870,7 @@ layout_type (type)
   /* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE.  For
      records and unions, finish_record_layout already called this
      function.  */
-  if (TREE_CODE (type) != RECORD_TYPE 
+  if (TREE_CODE (type) != RECORD_TYPE
       && TREE_CODE (type) != UNION_TYPE
       && TREE_CODE (type) != QUAL_UNION_TYPE)
     finalize_type_size (type);
@@ -1520,7 +1895,7 @@ tree
 make_signed_type (precision)
      int precision;
 {
-  register tree type = make_node (INTEGER_TYPE);
+  tree type = make_node (INTEGER_TYPE);
 
   TYPE_PRECISION (type) = precision;
 
@@ -1534,7 +1909,7 @@ tree
 make_unsigned_type (precision)
      int precision;
 {
-  register tree type = make_node (INTEGER_TYPE);
+  tree type = make_node (INTEGER_TYPE);
 
   TYPE_PRECISION (type) = precision;
 
@@ -1638,9 +2013,6 @@ set_sizetype (type)
       TYPE_REFERENCE_TO (sizetype_tab[i]) = 0;
     }
 
-  ggc_add_tree_root ((tree *) &sizetype_tab,
-                    sizeof sizetype_tab / sizeof (tree));
-
   /* Go down each of the types we already made and set the proper type
      for the sizes in them.  */
   for (t = early_type_list; t != 0; t = TREE_CHAIN (t))
@@ -1665,7 +2037,13 @@ void
 fixup_signed_type (type)
      tree type;
 {
-  register int precision = TYPE_PRECISION (type);
+  int precision = TYPE_PRECISION (type);
+
+  /* We can not represent properly constants greater then
+     2 * HOST_BITS_PER_WIDE_INT, still we need the types
+     as they are used by i386 vector extensions and friends.  */
+  if (precision > HOST_BITS_PER_WIDE_INT * 2)
+    precision = HOST_BITS_PER_WIDE_INT * 2;
 
   TYPE_MIN_VALUE (type)
     = build_int_2 ((precision - HOST_BITS_PER_WIDE_INT > 0
@@ -1697,7 +2075,13 @@ void
 fixup_unsigned_type (type)
      tree type;
 {
-  register int precision = TYPE_PRECISION (type);
+  int precision = TYPE_PRECISION (type);
+
+  /* We can not represent properly constants greater then
+     2 * HOST_BITS_PER_WIDE_INT, still we need the types
+     as they are used by i386 vector extensions and friends.  */
+  if (precision > HOST_BITS_PER_WIDE_INT * 2)
+    precision = HOST_BITS_PER_WIDE_INT * 2;
 
   TYPE_MIN_VALUE (type) = build_int_2 (0, 0);
   TYPE_MAX_VALUE (type)
@@ -1784,26 +2168,4 @@ get_best_mode (bitsize, bitpos, align, largest_mode, volatilep)
   return mode;
 }
 
-/* Return the alignment of MODE. This will be bounded by 1 and
-   BIGGEST_ALIGNMENT.  */
-
-unsigned int
-get_mode_alignment (mode)
-     enum machine_mode mode;
-{
-  unsigned int alignment = GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT;
-  
-  /* Extract the LSB of the size.  */
-  alignment = alignment & -alignment;
-
-  alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment));
-  return alignment;
-}
-
-/* This function is run once to initialize stor-layout.c.  */
-
-void
-init_stor_layout_once ()
-{
-  ggc_add_tree_root (&pending_sizes, 1);
-}
+#include "gt-stor-layout.h"