OSDN Git Service

x
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index 75d2611..e55961a 100644 (file)
@@ -1,5 +1,5 @@
 /* C-compiler utilities for types and variables storage layout
-   Copyright (C) 1987, 88, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-96, 1997 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA.  */
 
 #include "tree.h"
 #include "flags.h"
+#include "except.h"
 #include "function.h"
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
@@ -46,14 +47,10 @@ tree size_one_node;
    The value is measured in bits.  */
 int maximum_field_alignment;
 
-/* If non-zero, the alignment of a bitsting or (power-)set value, in bits.
+/* If non-zero, the alignment of a bitstring or (power-)set value, in bits.
    May be overridden by front-ends.  */
 int set_alignment = 0;
 
-#define GET_MODE_ALIGNMENT(MODE)   \
-  MIN (BIGGEST_ALIGNMENT,         \
-       MAX (1, (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)))
-
 static enum machine_mode smallest_mode_for_size  PROTO((unsigned int,
                                                        enum mode_class));
 static tree layout_record      PROTO((tree));
@@ -81,6 +78,16 @@ get_pending_sizes ()
   return chain;
 }
 
+void
+put_pending_sizes (chain)
+     tree chain;
+{
+  if (pending_sizes)
+    abort ();
+
+  pending_sizes = chain;
+}
+
 /* Given a size SIZE that may not be a constant, return a SAVE_EXPR
    to serve as the actual size-expression for a type or decl.  */
 
@@ -244,13 +251,14 @@ 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 (flag_pack_struct)
+      else if (DECL_PACKED (decl))
        DECL_ALIGN (decl) = MIN (DECL_ALIGN (decl), BITS_PER_UNIT);
     }
 
   if (DECL_BIT_FIELD (decl)
       && TYPE_SIZE (type) != 0
-      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)
+      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
+      && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT)
     {
       register enum machine_mode xmode
        = mode_for_size (TREE_INT_CST_LOW (DECL_SIZE (decl)), MODE_INT, 1);
@@ -267,6 +275,15 @@ layout_decl (decl, known_align)
        }
     }
 
+  /* Turn off DECL_BIT_FIELD if we won't need it set.  */
+  if (DECL_BIT_FIELD (decl) && TYPE_MODE (type) == BLKmode
+      && known_align % TYPE_ALIGN (type) == 0
+      && DECL_SIZE (decl) != 0
+      && (TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST
+         || (TREE_INT_CST_LOW (DECL_SIZE (decl)) % BITS_PER_UNIT) == 0)
+      && DECL_ALIGN (decl) >= TYPE_ALIGN (type))
+    DECL_BIT_FIELD (decl) = 0;
+
   /* Evaluate nonconstant size only once, either now or as soon as safe.  */
   if (DECL_SIZE (decl) != 0 && TREE_CODE (DECL_SIZE (decl)) != INTEGER_CST)
     DECL_SIZE (decl) = variable_size (DECL_SIZE (decl));
@@ -301,7 +318,7 @@ layout_record (rec)
      and VAR_SIZE is a tree expression.
      If VAR_SIZE is null, the size is just CONST_SIZE.
      Naturally we try to avoid using VAR_SIZE.  */
 register int const_size = 0;
register HOST_WIDE_INT const_size = 0;
   register tree var_size = 0;
   /* Once we start using VAR_SIZE, this is the maximum alignment
      that we know VAR_SIZE has.  */
@@ -319,7 +336,7 @@ layout_record (rec)
         In both cases, all we do is lay out the decl,
         and we do it *after* the record is laid out.  */
 
-      if (TREE_STATIC (field))
+      if (TREE_CODE (field) == VAR_DECL)
        {
          pending_statics = tree_cons (NULL_TREE, field, pending_statics);
          continue;
@@ -342,6 +359,9 @@ layout_record (rec)
 #ifdef BIGGEST_FIELD_ALIGNMENT
       desired_align = MIN (desired_align, 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
@@ -369,7 +389,7 @@ layout_record (rec)
              int type_align = TYPE_ALIGN (TREE_TYPE (field));
              if (maximum_field_alignment != 0)
                type_align = MIN (type_align, maximum_field_alignment);
-             else if (flag_pack_struct)
+             else if (TYPE_PACKED (rec))
                type_align = MIN (type_align, BITS_PER_UNIT);
 
              record_align = MAX (record_align, type_align);
@@ -411,23 +431,17 @@ layout_record (rec)
          && TREE_TYPE (field) != error_mark_node
          && DECL_BIT_FIELD_TYPE (field)
          && !DECL_PACKED (field)
-         /* If #pragma pack is in effect, turn off this feature.  */
          && maximum_field_alignment == 0
-         && !flag_pack_struct
          && !integer_zerop (DECL_SIZE (field)))
        {
          int type_align = TYPE_ALIGN (TREE_TYPE (field));
          register tree dsize = DECL_SIZE (field);
          int field_size = TREE_INT_CST_LOW (dsize);
 
-         /* A bit field may not span the unit of alignment of its type.
-            Advance to next boundary if necessary.  */
-         /* ??? There is some uncertainty here as to what
-            should be done if type_align is less than the width of the type.
-            That can happen because the width exceeds BIGGEST_ALIGNMENT
-            or because it exceeds maximum_field_alignment.  */
-         if (const_size / type_align
-             != (const_size + field_size - 1) / type_align)
+         /* A bit field may not span more units of alignment of its type
+            than its type itself.  Advance to next boundary if necessary.  */
+         if (((const_size + field_size) / type_align - const_size / type_align)
+             > TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (field))) / type_align)
            const_size = CEIL (const_size, type_align) * type_align;
        }
 #endif
@@ -448,7 +462,7 @@ layout_record (rec)
 
          if (maximum_field_alignment != 0)
            type_align = MIN (type_align, maximum_field_alignment);
-         else if (flag_pack_struct)
+         else if (TYPE_PACKED (rec))
            type_align = MIN (type_align, BITS_PER_UNIT);
 
          /* A bit field may not span the unit of alignment of its type.
@@ -489,8 +503,9 @@ layout_record (rec)
        if (dsize == 0)
          /* Do nothing.  */;
        else if (TREE_CODE (dsize) == INTEGER_CST
+                && ! TREE_CONSTANT_OVERFLOW (dsize)
                 && TREE_INT_CST_HIGH (dsize) == 0
-                && TREE_INT_CST_LOW (dsize) + const_size > const_size)
+                && TREE_INT_CST_LOW (dsize) + const_size >= const_size)
          /* Use const_size if there's no overflow.  */
          const_size += TREE_INT_CST_LOW (dsize);
        else
@@ -677,6 +692,7 @@ layout_type (type)
 
     case INTEGER_TYPE:
     case ENUMERAL_TYPE:
+    case CHAR_TYPE:
       if (TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
          && tree_int_cst_sgn (TYPE_MIN_VALUE (type)) >= 0)
        TREE_UNSIGNED (type) = 1;
@@ -737,10 +753,28 @@ layout_type (type)
        if (index && TYPE_MAX_VALUE (index) && TYPE_MIN_VALUE (index)
            && TYPE_SIZE (element))
          {
-           tree length
-             = size_binop (PLUS_EXPR, size_one_node,
-                           size_binop (MINUS_EXPR, TYPE_MAX_VALUE (index),
-                                       TYPE_MIN_VALUE (index)));
+           tree ub = TYPE_MAX_VALUE (index);
+           tree lb = TYPE_MIN_VALUE (index);
+           tree length;
+
+           /* If UB is max (lb - 1, x), remove the MAX_EXPR since the
+              test for negative below covers it.  */
+           if (TREE_CODE (ub) == MAX_EXPR
+               && TREE_CODE (TREE_OPERAND (ub, 0)) == MINUS_EXPR
+               && integer_onep (TREE_OPERAND (TREE_OPERAND (ub, 0), 1))
+               && operand_equal_p (TREE_OPERAND (TREE_OPERAND (ub, 0), 0),
+                                   lb, 0))
+             ub = TREE_OPERAND (ub, 1);
+           else if (TREE_CODE (ub) == MAX_EXPR
+                    && TREE_CODE (TREE_OPERAND (ub, 1)) == MINUS_EXPR
+                    && integer_onep (TREE_OPERAND (TREE_OPERAND (ub, 1), 1))
+                    && operand_equal_p (TREE_OPERAND (TREE_OPERAND (ub, 1),
+                                                      0),
+                                        lb, 0))
+             ub = TREE_OPERAND (ub, 0);
+
+           length = size_binop (PLUS_EXPR, size_one_node,
+                                size_binop (MINUS_EXPR, ub, lb));
 
            /* If neither bound is a constant and sizetype is signed, make
               sure the size is never negative.  We should really do this
@@ -895,7 +929,7 @@ layout_type (type)
       break;
 
     /* Pascal and Chill types */
-    case BOOLEAN_TYPE:          /* store one byte/boolean for now. */
+    case BOOLEAN_TYPE:          /* store one byte/boolean for now.  */
       TYPE_MODE (type) = QImode;
       TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
       TYPE_PRECISION (type) = 1;
@@ -905,13 +939,6 @@ layout_type (type)
        TREE_UNSIGNED (type) = 1;
       break;
 
-    case CHAR_TYPE:
-      TYPE_MODE (type) = QImode;
-      TYPE_SIZE (type) = size_int (GET_MODE_BITSIZE (TYPE_MODE (type)));
-      TYPE_PRECISION (type) = GET_MODE_BITSIZE (TYPE_MODE (type));
-      TYPE_ALIGN (type) = GET_MODE_ALIGNMENT (TYPE_MODE (type));
-      break;
-
     case SET_TYPE:
       if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
          || TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST)