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. From-SVN: r18978
This commit is contained in:
parent
e9eaed43b9
commit
732dcb6f2a
7 changed files with 152 additions and 19 deletions
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue