diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-04-03 14:13:24 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-04-03 14:13:24 +0000 |
commit | d729e3b1a1d95cebc497ccff79fb8c934760b59f (patch) | |
tree | 78b6049387f4015025e8331467e00ee2485df68d | |
parent | 1cd80523a7f9b340b7cecbe9d66cd2707d1f0988 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/class.c | 27 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 5 | ||||
-rw-r--r-- | gcc/cp/lang-options.h | 2 | ||||
-rw-r--r-- | gcc/cp/search.c | 46 | ||||
-rw-r--r-- | gcc/cp/tree.c | 78 |
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. */ |