]> gcc.gnu.org Git - gcc.git/commitdiff
Implement empty base optimization.
authorJason Merrill <jason@yorick.cygnus.com>
Fri, 3 Apr 1998 14:13:24 +0000 (14:13 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 3 Apr 1998 14:13:24 +0000 (09:13 -0500)
* class.c (finish_struct_1): Add vbase fields earlier.  Set
CLASSTYPE_SIZE of an empty base to 0.  Types with bases can be empty.
* search.c (dfs_check_overlap, dfs_no_overlap_yet): New fns.
(types_overlap_p): New fn.
* tree.c (avoid_overlap): New fn.
(build_base_fields): Use it to avoid overlapping empty bases.
* cp-tree.h, decl2.c, lang-options.h: Add -fnew-abi.

From-SVN: r18978

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/lang-options.h
gcc/cp/search.c
gcc/cp/tree.c

index b02f2bb02b09e5281448b9a3f7e44d46db2fe1b9..99555d8bc4f9d1de5ba9a69d6168afdd2521cf56 100644 (file)
@@ -1,5 +1,14 @@
 Fri Apr  3 02:22:59 1998  Jason Merrill  <jason@yorick.cygnus.com>
 
+       Implement empty base optimization.
+       * class.c (finish_struct_1): Add vbase fields earlier.  Set 
+       CLASSTYPE_SIZE of an empty base to 0.  Types with bases can be empty.
+       * search.c (dfs_check_overlap, dfs_no_overlap_yet): New fns.
+       (types_overlap_p): New fn.
+       * tree.c (avoid_overlap): New fn.
+       (build_base_fields): Use it to avoid overlapping empty bases.
+       * cp-tree.h, decl2.c, lang-options.h: Add -fnew-abi.
+
        * decl.c (cplus_expand_expr_stmt): Strip unused INDIRECT_REFs.
 
        Re-implement allocation of base class subobjects.
index c39caac5b119db1e21d689e1f6c716f2aa157bc3..dc4cc313cf064d425f961158e78c14adbdc72eb8 100644 (file)
@@ -3131,7 +3131,6 @@ finish_struct_1 (t, warn_anon)
       cant_have_const_ctor = base_info.cant_have_const_ctor;
       no_const_asn_ref = base_info.no_const_asn_ref;
       aggregate = 0;
-      empty = 0;
     }
   else
     {
@@ -3209,6 +3208,9 @@ finish_struct_1 (t, warn_anon)
        }
     }
 
+  if (n_baseclasses)
+    fields = chainon (build_vbase_pointer_fields (t), fields);
+
   last_x = NULL_TREE;
   for (x = fields; x; x = TREE_CHAIN (x))
     {
@@ -3757,9 +3759,6 @@ finish_struct_1 (t, warn_anon)
     
   }
 
-  if (n_baseclasses)
-    fields = chainon (build_vbase_pointer_fields (t), fields);
-
   if (vfield == NULL_TREE && has_virtual)
     {
       /* We build this decl with ptr_type_node, and
@@ -3852,21 +3851,33 @@ finish_struct_1 (t, warn_anon)
   TYPE_FIELDS (t) = fields;
 
   if (n_baseclasses)
-    TYPE_FIELDS (t) = chainon (build_base_fields (t), fields);
-  else if (empty)
+    {
+      last_x = build_base_fields (t);
+
+      /* If all our bases are empty, we can be empty too.  */
+      for (x = last_x; empty && x; x = TREE_CHAIN (x))
+       if (DECL_SIZE (x) != integer_zero_node)
+         empty = 0;
+    }
+  if (empty)
     {
       /* C++: do not let empty structures exist.  */
       tree decl = build_lang_field_decl
        (FIELD_DECL, NULL_TREE, char_type_node);
-      TREE_CHAIN (decl) = TYPE_FIELDS (t);
+      TREE_CHAIN (decl) = fields;
       TYPE_FIELDS (t) = decl;
     }
+  if (n_baseclasses)
+    TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
 
   layout_type (t);
 
   /* Remember the size and alignment of the class before adding
      the virtual bases.  */
-  CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
+  if (empty && flag_new_abi)
+    CLASSTYPE_SIZE (t) = integer_zero_node;
+  else
+    CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
   CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
 
   finish_struct_anon (t);
index c62fe082a97b9f657d6c95108d2b555d066d3b8f..443c83edc4fed18382f8b5cc4519fedd650c1854 100644 (file)
@@ -1914,6 +1914,10 @@ extern int flag_implicit_templates;
 
 extern int flag_weak;
 
+/* Nonzero to enable experimental ABI changes.  */
+
+extern int flag_new_abi;
+
 /* Nonzero if we're done parsing and into end-of-file activities.  */
 
 extern int at_eof;
index 8340f095ba25b70996c78a3e1676c5dcb4ff909c..cf9b07680ce6357329a64bcabdf3c00f4b8314a6 100644 (file)
@@ -401,6 +401,8 @@ int flag_new_for_scope = 1;
 
 int flag_weak = 1;
 
+int flag_new_abi = 1;
+
 /* Maximum template instantiation depth. Must be at least 17 for ANSI
    compliance. */
 
@@ -467,7 +469,8 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"check-new", &flag_check_new, 1},
   {"repo", &flag_use_repository, 1},
   {"for-scope", &flag_new_for_scope, 2},
-  {"weak", &flag_weak, 1}
+  {"weak", &flag_weak, 1},
+  {"new-abi", &flag_new_abi, 1}
 };
 
 /* Decode the string P as a language-specific option.
index 51eee7c7f51706778a60d170a4580ef22753d17e..f4f262dc062c47d45c93f9903cc4579215c992fa 100644 (file)
@@ -67,6 +67,8 @@ Boston, MA 02111-1307, USA.  */
   "-fmemoize-lookups",
   "-fno-memoize-lookups",
   "-fname-mangling-version-",
+  "-fnew-abi",
+  "-fno-new-abi",
   "-fnonnull-objects",
   "-fno-nonnull-objects",
   "-foperator-names",
index 72108cd4768d4400b0153e9ce1c27553f03d85f5..488220adc2abffb4fe55be20e6d7a5f167f0250b 100644 (file)
@@ -3830,3 +3830,49 @@ get_template_base (template, binfo)
 
   return rval;
 }
+
+/* Check whether the empty class indicated by EMPTY_BINFO is also present
+   at offset 0 in COMPARE_TYPE, and set found_overlap if so.  */
+
+static tree compare_type;
+static int found_overlap;
+static void
+dfs_check_overlap (empty_binfo)
+     tree empty_binfo;
+{
+  tree binfo;
+  for (binfo = TYPE_BINFO (compare_type); ; binfo = BINFO_BASETYPE (binfo, 0))
+    {
+      if (BINFO_TYPE (binfo) == BINFO_TYPE (empty_binfo))
+       {
+         found_overlap = 1;
+         break;
+       }
+      else if (BINFO_BASETYPES (binfo) == NULL_TREE)
+       break;
+    }
+}
+
+/* Trivial function to stop base traversal when we find something.  */
+
+static int
+dfs_no_overlap_yet (t)
+     tree t;
+{
+  return found_overlap == 0;
+}
+
+/* Returns nonzero if EMPTY_TYPE or any of its bases can also be found at
+   offset 0 in NEXT_TYPE.  Used in laying out empty base class subobjects.  */
+
+int
+types_overlap_p (empty_type, next_type)
+     tree empty_type, next_type;
+{
+  if (! IS_AGGR_TYPE (next_type))
+    return 0;
+  compare_type = next_type;
+  found_overlap = 0;
+  dfs_walk (TYPE_BINFO (empty_type), dfs_check_overlap, dfs_no_overlap_yet);
+  return found_overlap;
+}
index 8f4d02d70ffa8cd1a3e6d4fdd3a107d41db70801..b314185605bf5b7d6a66938829e97d07bb0ad477 100644 (file)
@@ -750,6 +750,28 @@ layout_basetypes (rec, max)
   return max;
 }
 
+/* If the empty base field in DECL overlaps with a base of the same type in
+   NEWDECL, which is either another base field or the first data field of
+   the class, pad the base just before NEWDECL and return 1.  Otherwise,
+   return 0.  */
+
+static int
+avoid_overlap (decl, newdecl)
+     tree decl, newdecl;
+{
+  tree field;
+
+  if (newdecl == NULL_TREE
+      || ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
+    return 0;
+
+  for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
+       field = TREE_CHAIN (field))
+    ;
+
+  DECL_SIZE (field) = integer_one_node;
+}
+
 /* Returns a list of fields to stand in for the base class subobjects
    of REC.  These fields are later removed by layout_basetypes.  */
 
@@ -762,8 +784,8 @@ build_base_fields (rec)
   tree base_decls = NULL_TREE;
   tree binfos = TYPE_BINFO_BASETYPES (rec);
   int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-  tree decl;
-  int i;
+  tree decl, nextdecl;
+  int i, saw_empty = 0;
   unsigned int base_align = 0;
 
   for (i = 0; i < n_baseclasses; ++i)
@@ -787,18 +809,54 @@ build_base_fields (rec)
       TREE_CHAIN (decl) = base_decls;
       base_decls = decl;
 
-      /* Brain damage for backwards compatibility.  For no good reason, the
-        old layout_basetypes made every base at least as large as the
-        alignment for the bases up to that point, gratuitously wasting
-        space.  So we do the same thing here.  */
-      base_align = MAX (base_align, DECL_ALIGN (decl));
-      DECL_SIZE (decl) = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
-                                       base_align));
+      if (! flag_new_abi)
+       {
+         /* Brain damage for backwards compatibility.  For no good reason,
+            the old layout_basetypes made every base at least as large as
+            the alignment for the bases up to that point, gratuitously
+            wasting space.  So we do the same thing here.  */
+         base_align = MAX (base_align, DECL_ALIGN (decl));
+         DECL_SIZE (decl)
+           = size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
+                            base_align));
+       }
+      else if (DECL_SIZE (decl) == integer_zero_node)
+       saw_empty = 1;
     }
 
   /* Reverse the list of fields so we allocate the bases in the proper
      order.  */
-  return nreverse (base_decls);
+  base_decls = nreverse (base_decls);
+
+  /* In the presence of empty base classes, we run the risk of allocating
+     two objects of the same class on top of one another.  Avoid that.  */
+  if (flag_new_abi && saw_empty)
+    for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
+      {
+       if (DECL_SIZE (decl) == integer_zero_node)
+         {
+           /* First step through the following bases until we find
+              an overlap or a non-empty base.  */
+           for (nextdecl = TREE_CHAIN (decl); nextdecl;
+                nextdecl = TREE_CHAIN (nextdecl))
+             {
+               if (avoid_overlap (decl, nextdecl)
+                   || DECL_SIZE (nextdecl) != integer_zero_node)
+                 goto nextbase;
+             }
+
+           /* If we're still looking, also check against the first
+              field.  */
+           for (nextdecl = TYPE_FIELDS (rec);
+                nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
+                nextdecl = TREE_CHAIN (nextdecl))
+             /* keep looking */;
+           avoid_overlap (decl, nextdecl);
+         }
+      nextbase:;
+      }
+
+  return base_decls;
 }
 
 /* Returns list of virtual base class pointers in a FIELD_DECL chain.  */
This page took 0.09467 seconds and 5 git commands to generate.