stor-layout.c (layout_union): Remove.
authorMark Mitchell <mark@codesourcery.com>
Wed, 15 Mar 2000 00:12:37 +0000 (00:12 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Wed, 15 Mar 2000 00:12:37 +0000 (00:12 +0000)
* stor-layout.c (layout_union): Remove.
(layout_union_field): New function, split out from layout_union.
(finish_union_layout): Likewise.
(layout_field): Handle unions by calling layout_union_field.
(finish_record_layout): Handle unions.
(layout_type): Combine RECORD_TYPE, UNION_TYPE, and
QUAL_UNION_TYPE handling.

From-SVN: r32548

gcc/ChangeLog
gcc/stor-layout.c

index d82cb85da1198f0d2943deb341183969b7c2f61a..fc74992ecad9018a73e1dd3b426cf58f4c862933 100644 (file)
@@ -1,3 +1,13 @@
+2000-03-14  Mark Mitchell  <mark@codesourcery.com>
+
+       * stor-layout.c (layout_union): Remove.
+       (layout_union_field): New function, split out from layout_union.
+       (finish_union_layout): Likewise.
+       (layout_field): Handle unions by calling layout_union_field.
+       (finish_record_layout): Handle unions.
+       (layout_type): Combine RECORD_TYPE, UNION_TYPE, and
+       QUAL_UNION_TYPE handling.
+
 Wed Feb 23 13:00:06 CET 2000  Jan Hubicka  <jh@suse.cz>
         * flow.c (fixup_reorder_chain): Avoid double labels in the basic block;
         end of basic block is jump_insn, not barrier; use create_basic_block
index 8e8a2e89f755c7b487910bd53a04d81dbcd0c37d..62363cbbde0bcf5c8bf4ae3274c4f9b73152582f 100644 (file)
@@ -50,10 +50,11 @@ unsigned int maximum_field_alignment;
    May be overridden by front-ends.  */
 unsigned int set_alignment = 0;
 
-static void layout_union       PARAMS ((tree));
 static void finalize_record_size PARAMS ((record_layout_info));
 static void compute_record_mode PARAMS ((tree));
 static void finalize_type_size PARAMS ((tree));
+static void layout_union_field PARAMS ((record_layout_info, tree));
+static void finish_union_layout PARAMS ((record_layout_info));
 \f
 /* SAVE_EXPRs for sizes of types and decls, waiting to be expanded.  */
 
@@ -402,9 +403,9 @@ layout_decl (decl, known_align)
     }
 }
 \f
-/* Create a new record_layout_info for the RECORD_TYPE T.  It is the
-   responsibility of the caller to call `free' for the storage the
-   returned.  */
+/* Create a new record_layout_info for T, which may be a RECORD_TYPE,
+   UNION_TYPE, or QUAL_UNION_TYPE.  It is the responsibility of the
+   caller to call `free' for the storage the returned.  */
 
 record_layout_info
 new_record_layout_info (t)
@@ -429,6 +430,65 @@ new_record_layout_info (t)
   return rli;
 }
 
+/* Like layout_field, but for unions.  */
+
+static void
+layout_union_field (rli, field)
+     record_layout_info rli;
+     tree field;
+{
+  tree dsize;
+      
+  /* This function should only be used for unions; use layout_field
+     for RECORD_TYPEs.  */
+  if (TREE_CODE (rli->t) != UNION_TYPE
+      && TREE_CODE (rli->t) != QUAL_UNION_TYPE)
+    abort ();
+
+  /* By now, we should only be seeing FIELD_DECLs.  */
+  if (TREE_CODE (field) != FIELD_DECL)
+    abort ();
+
+  layout_decl (field, 0);
+  DECL_FIELD_BITPOS (field) = bitsize_int (0);
+
+  /* Union must be at least as aligned as any field requires.  */
+  rli->record_align = MAX (rli->record_align, DECL_ALIGN (field));
+
+#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)));
+#endif
+
+  dsize = DECL_SIZE (field);
+  if (TREE_CODE (rli->t) == UNION_TYPE)
+    {
+      /* Set union_size to max (decl_size, union_size).  There are
+        more and less general ways to do this.  Use only CONST_SIZE
+        unless forced to use VAR_SIZE.  */
+
+      if (TREE_CODE (dsize) == INTEGER_CST
+         && ! TREE_CONSTANT_OVERFLOW (dsize)
+         && TREE_INT_CST_HIGH (dsize) == 0)
+       rli->const_size
+         = MAX (rli->const_size, TREE_INT_CST_LOW (dsize));
+      else if (rli->var_size == 0)
+       rli->var_size = dsize;
+      else
+       rli->var_size = size_binop (MAX_EXPR, rli->var_size, dsize);
+    }
+  else if (TREE_CODE (rli->t) == QUAL_UNION_TYPE)
+    rli->var_size = fold (build (COND_EXPR, bitsizetype, 
+                                DECL_QUALIFIER (field),
+                                DECL_SIZE (field),
+                                (rli->var_size
+                                 ? rli->var_size 
+                                 : bitsize_int (0))));
+}
+
 /* 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;
@@ -463,6 +523,13 @@ layout_field (rli, field)
      be laid out.  Likewise for initialized constant fields.  */
   else if (TREE_CODE (field) != FIELD_DECL)
     return;
+  /* This function should only be used for records; use
+     layout_union_field for unions.  */
+  else if (TREE_CODE (rli->t) != RECORD_TYPE)
+    {
+      layout_union_field (rli, field);
+      return;
+    }
 
   /* Work out the known alignment so far.  */
   known_align = rli->var_size ? rli->var_align : rli->const_size;
@@ -931,10 +998,17 @@ void
 finish_record_layout (rli)
      record_layout_info rli;
 {
-  /* Compute the final size.  */
-  finalize_record_size (rli);
-  /* Compute the TYPE_MODE for the record.  */
-  compute_record_mode (rli->t);
+  /* Use finish_union_layout for unions.  */
+  if (TREE_CODE (rli->t) != RECORD_TYPE)
+    finish_union_layout (rli);
+  else
+    {
+      /* Compute the final size.  */
+      finalize_record_size (rli);
+      /* Compute the TYPE_MODE for the record.  */
+      compute_record_mode (rli->t);
+    }
+
   /* Lay out any static members.  This is done now because their type
      may use the record's type.  */
   while (rli->pending_statics)
@@ -942,118 +1016,86 @@ finish_record_layout (rli)
       layout_decl (TREE_VALUE (rli->pending_statics), 0);
       rli->pending_statics = TREE_CHAIN (rli->pending_statics);
     }
+
   /* Perform any last tweaks to the TYPE_SIZE, etc.  */
   finalize_type_size (rli->t);
   /* Clean up.  */
   free (rli);
 }
 
-\f
-/* Lay out a UNION_TYPE or QUAL_UNION_TYPE type.
-   Lay out all the fields, set their positions to zero,
-   and compute the size and alignment of the union (maximum of any field).
-   Note that if you set the TYPE_ALIGN before calling this
-   then the union align is aligned to at least that boundary.  */
+/* Like finish_record_layout, but for unions.  */
 
 static void
-layout_union (rec)
-     tree rec;
+finish_union_layout (rli)
+     record_layout_info rli;
 {
-  register tree field;
-  unsigned int union_align = BITS_PER_UNIT;
-
-  /* The size of the union, based on the fields scanned so far,
-     is max (CONST_SIZE, VAR_SIZE).
-     VAR_SIZE may be null; then CONST_SIZE by itself is the size.  */
-  unsigned HOST_WIDE_INT const_size = 0;
-  register tree var_size = 0;
-
-#ifdef STRUCTURE_SIZE_BOUNDARY
-  /* Packed structures don't need to have minimum size.  */
-  if (! TYPE_PACKED (rec))
-    union_align = STRUCTURE_SIZE_BOUNDARY;
-#endif
-
-  /* If this is a QUAL_UNION_TYPE, we want to process the fields in
-     the reverse order in building the COND_EXPR that denotes its
-     size.  We reverse them again later.  */
-  if (TREE_CODE (rec) == QUAL_UNION_TYPE)
-    TYPE_FIELDS (rec) = nreverse (TYPE_FIELDS (rec));
-
-  for (field = TYPE_FIELDS (rec); field; field = TREE_CHAIN (field))
-    {
-      tree dsize;
-      
-      /* Enums which are local to this class need not be laid out.  */
-      if (TREE_CODE (field) == CONST_DECL || TREE_CODE (field) == TYPE_DECL)
-       continue;
-
-      layout_decl (field, 0);
-      DECL_FIELD_BITPOS (field) = bitsize_int (0);
-
-      /* Union must be at least as aligned as any field requires.  */
-
-      union_align = MAX (union_align, DECL_ALIGN (field));
-
-#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))
-       union_align = MAX (union_align, TYPE_ALIGN (TREE_TYPE (field)));
-#endif
-
-      dsize = DECL_SIZE (field);
-      if (TREE_CODE (rec) == UNION_TYPE)
-       {
-         /* Set union_size to max (decl_size, union_size).
-            There are more and less general ways to do this.
-            Use only CONST_SIZE unless forced to use VAR_SIZE.  */
-
-         if (TREE_CODE (dsize) == INTEGER_CST
-              && ! TREE_CONSTANT_OVERFLOW (dsize)
-              && TREE_INT_CST_HIGH (dsize) == 0)
-           const_size
-             = MAX (const_size, TREE_INT_CST_LOW (dsize));
-         else if (var_size == 0)
-           var_size = dsize;
-         else
-           var_size = size_binop (MAX_EXPR, var_size, dsize);
-       }
-      else if (TREE_CODE (rec) == QUAL_UNION_TYPE)
-       var_size = fold (build (COND_EXPR, bitsizetype, DECL_QUALIFIER (field),
-                               DECL_SIZE (field),
-                               var_size ? var_size : bitsize_int (0)));
-      }
-
-  if (TREE_CODE (rec) == QUAL_UNION_TYPE)
-    TYPE_FIELDS (rec) = nreverse (TYPE_FIELDS (rec));
+  /* This function should only be used for unions; use
+     finish_record_layout for RECORD_TYPEs.  */
+  if (TREE_CODE (rli->t) != UNION_TYPE
+      && TREE_CODE (rli->t) != QUAL_UNION_TYPE)
+    abort ();
 
   /* Determine the ultimate size of the union (in bytes).  */
-  if (NULL == var_size)
-    TYPE_SIZE (rec)
-      = bitsize_int (CEIL (const_size, BITS_PER_UNIT) * BITS_PER_UNIT);
+  if (NULL == rli->var_size)
+    TYPE_SIZE (rli->t)
+      = bitsize_int (CEIL (rli->const_size, BITS_PER_UNIT) * BITS_PER_UNIT);
 
-  else if (const_size == 0)
-    TYPE_SIZE (rec) = var_size;
+  else if (rli->const_size == 0)
+    TYPE_SIZE (rli->t) = rli->var_size;
   else
-    TYPE_SIZE (rec) = size_binop (MAX_EXPR, var_size,
-                                 round_up (bitsize_int (const_size),
-                                           BITS_PER_UNIT));
+    TYPE_SIZE (rli->t) = size_binop (MAX_EXPR, rli->var_size,
+                                    round_up (bitsize_int (rli->const_size),
+                                              BITS_PER_UNIT));
 
   /* Determine the desired alignment.  */
 #ifdef ROUND_TYPE_ALIGN
-  TYPE_ALIGN (rec) = ROUND_TYPE_ALIGN (rec, TYPE_ALIGN (rec), union_align);
+  TYPE_ALIGN (rli->t) = ROUND_TYPE_ALIGN (rli->t, TYPE_ALIGN (rli->t), 
+                                         rli->record_align);
 #else
-  TYPE_ALIGN (rec) = MAX (TYPE_ALIGN (rec), union_align);
+  TYPE_ALIGN (rli->t) = MAX (TYPE_ALIGN (rli->t), rli->record_align);
 #endif
 
 #ifdef ROUND_TYPE_SIZE
-  TYPE_SIZE (rec) = ROUND_TYPE_SIZE (rec, TYPE_SIZE (rec), TYPE_ALIGN (rec));
+  TYPE_SIZE (rli->t) = ROUND_TYPE_SIZE (rli->t, TYPE_SIZE (rli->t), 
+                                       TYPE_ALIGN (rli->t));
 #else
   /* Round the size up to be a multiple of the required alignment */
-  TYPE_SIZE (rec) = round_up (TYPE_SIZE (rec), TYPE_ALIGN (rec));
+  TYPE_SIZE (rli->t) = round_up (TYPE_SIZE (rli->t), 
+                                TYPE_ALIGN (rli->t));
 #endif
+
+  TYPE_MODE (rli->t) = BLKmode;
+  if (TREE_CODE (TYPE_SIZE (rli->t)) == INTEGER_CST
+      /* If structure's known alignment is less than
+        what the scalar mode would need, and it matters,
+        then stick with BLKmode.  */
+      && (! STRICT_ALIGNMENT
+         || TYPE_ALIGN (rli->t) >= BIGGEST_ALIGNMENT
+         || compare_tree_int (TYPE_SIZE (rli->t), 
+                              TYPE_ALIGN (rli->t)) <= 0))
+    {
+      tree field;
+
+      /* A union which has any BLKmode members must itself be BLKmode;
+        it can't go in a register.
+        Unless the member is BLKmode only because it isn't aligned.  */
+      for (field = TYPE_FIELDS (rli->t); 
+          field; 
+          field = TREE_CHAIN (field))
+       {
+         if (TREE_CODE (field) != FIELD_DECL)
+           continue;
+
+         if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
+             && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
+           return;
+       }
+
+      TYPE_MODE (rli->t) 
+       = mode_for_size_tree (TYPE_SIZE (rli->t), MODE_INT, 1);
+    }
 }
+
 \f
 /* Calculate the mode, size, and alignment for TYPE.
    For an array type, calculate the element separation as well.
@@ -1287,54 +1329,29 @@ layout_type (type)
       }
 
     case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
       {
        tree field;
        record_layout_info rli;
 
        /* Initialize the layout information.  */
        rli = new_record_layout_info (type);
+       /* If this is a QUAL_UNION_TYPE, we want to process the fields
+          in the reverse order in building the COND_EXPR that denotes
+          its size.  We reverse them again later.  */
+       if (TREE_CODE (type) == QUAL_UNION_TYPE)
+         TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
        /* Layout all the fields.  */
        for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
          layout_field (rli, field);
+       if (TREE_CODE (type) == QUAL_UNION_TYPE)
+         TYPE_FIELDS (type) = nreverse (TYPE_FIELDS (type));
        /* Finish laying out the record.  */
        finish_record_layout (rli);
       }
       break;
 
-    case UNION_TYPE:
-    case QUAL_UNION_TYPE:
-      layout_union (type);
-      TYPE_MODE (type) = BLKmode;
-      if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
-         /* If structure's known alignment is less than
-            what the scalar mode would need, and it matters,
-            then stick with BLKmode.  */
-         && (! STRICT_ALIGNMENT
-             || TYPE_ALIGN (type) >= BIGGEST_ALIGNMENT
-             || compare_tree_int (TYPE_SIZE (type), TYPE_ALIGN (type)) <= 0))
-       {
-         tree field;
-
-         /* A union which has any BLKmode members must itself be BLKmode;
-            it can't go in a register.
-            Unless the member is BLKmode only because it isn't aligned.  */
-         for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
-           {
-             if (TREE_CODE (field) != FIELD_DECL)
-               continue;
-
-             if (TYPE_MODE (TREE_TYPE (field)) == BLKmode
-                 && ! TYPE_NO_FORCE_BLK (TREE_TYPE (field)))
-               goto union_lose;
-           }
-
-         TYPE_MODE (type)
-           = mode_for_size_tree (TYPE_SIZE (type), MODE_INT, 1);
-
-       union_lose: ;
-       }
-      break;
-
     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)
@@ -1376,8 +1393,11 @@ layout_type (type)
     }
 
   /* Compute the final TYPE_SIZE, TYPE_ALIGN, etc. for TYPE.  For
-     RECORD_TYPEs, finish_record_layout already called this function.  */
-  if (TREE_CODE (type) != RECORD_TYPE)
+     records and unions, finish_record_layout already called this
+     function.  */
+  if (TREE_CODE (type) != RECORD_TYPE 
+      && TREE_CODE (type) != UNION_TYPE
+      && TREE_CODE (type) != QUAL_UNION_TYPE)
     finalize_type_size (type);
 
   pop_obstacks ();