summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1998-04-03 14:13:24 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>1998-04-03 14:13:24 +0000
commitd729e3b1a1d95cebc497ccff79fb8c934760b59f (patch)
tree78b6049387f4015025e8331467e00ee2485df68d
parent1cd80523a7f9b340b7cecbe9d66cd2707d1f0988 (diff)
downloadgcc-d729e3b1a1d95cebc497ccff79fb8c934760b59f.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18978 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/class.c27
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/cp/lang-options.h2
-rw-r--r--gcc/cp/search.c46
-rw-r--r--gcc/cp/tree.c78
7 files changed, 152 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b02f2bb02b0..99555d8bc4f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index c39caac5b11..dc4cc313cf0 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c62fe082a97..443c83edc4f 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8340f095ba2..cf9b07680ce 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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.
diff --git a/gcc/cp/lang-options.h b/gcc/cp/lang-options.h
index 51eee7c7f51..f4f262dc062 100644
--- a/gcc/cp/lang-options.h
+++ b/gcc/cp/lang-options.h
@@ -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",
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 72108cd4768..488220adc2a 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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;
+}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8f4d02d70ff..b314185605b 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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. */