OSDN Git Service

(tablejump_internal4+1): Fix typo in condition.
[pf3gnuchains/gcc-fork.git] / gcc / stor-layout.c
index 1f7d5ee..0a152d7 100644 (file)
@@ -1,5 +1,5 @@
 /* C-compiler utilities for types and variables storage layout
-   Copyright (C) 1987, 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,13 +15,15 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include "config.h"
 #include <stdio.h>
 
 #include "tree.h"
+#include "flags.h"
 #include "function.h"
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
@@ -44,7 +46,7 @@ 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;
 
@@ -79,7 +81,17 @@ get_pending_sizes ()
   return chain;
 }
 
-/* Given a size SIZE that isn't constant, return a SAVE_EXPR
+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.  */
 
 tree
@@ -89,7 +101,8 @@ variable_size (size)
   /* 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.  */
-  if (global_bindings_p () < 0 || contains_placeholder_p (size))
+  if (TREE_CONSTANT (size)
+      || global_bindings_p () < 0 || contains_placeholder_p (size))
     return size;
 
   size = save_expr (size);
@@ -220,13 +233,6 @@ layout_decl (decl, known_align)
 
   if (code == FIELD_DECL && DECL_BIT_FIELD (decl))
     {
-      /* This is a bit-field.  We don't know how to handle
-        them except for integral types, and front ends should
-        never generate them otherwise.  */
-
-      if (! INTEGRAL_TYPE_P (type))
-       abort ();
-
       if (spec_size == 0 && DECL_NAME (decl) != 0)
        abort ();
 
@@ -248,11 +254,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 (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);
@@ -269,6 +278,14 @@ 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_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));
@@ -344,6 +361,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
@@ -371,6 +391,8 @@ 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 (TYPE_PACKED (rec))
+               type_align = MIN (type_align, BITS_PER_UNIT);
 
              record_align = MAX (record_align, type_align);
            }
@@ -411,7 +433,6 @@ 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
          && !integer_zerop (DECL_SIZE (field)))
        {
@@ -426,7 +447,7 @@ layout_record (rec)
             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)
+             != (const_size + (field_size % type_align) - 1) / type_align)
            const_size = CEIL (const_size, type_align) * type_align;
        }
 #endif
@@ -447,6 +468,8 @@ layout_record (rec)
 
          if (maximum_field_alignment != 0)
            type_align = MIN (type_align, maximum_field_alignment);
+         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.
             Advance to next boundary if necessary.  */
@@ -669,11 +692,12 @@ layout_type (type)
     {
     case LANG_TYPE:
       /* This kind of type is the responsibility
-        of the languge-specific code.  */
+        of the language-specific code.  */
       abort ();
 
     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;
@@ -734,10 +758,37 @@ 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
+              if *either* bound is non-constant, but this is the best
+              compromise between C and Ada.  */
+           if (! TREE_UNSIGNED (sizetype)
+               && TREE_CODE (TYPE_MIN_VALUE (index)) != INTEGER_CST
+               && TREE_CODE (TYPE_MAX_VALUE (index)) != INTEGER_CST)
+             length = size_binop (MAX_EXPR, length, size_zero_node);
 
            TYPE_SIZE (type) = size_binop (MULT_EXPR, length,
                                           TYPE_SIZE (element));
@@ -893,13 +944,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)