Commit c20118a8 by Mark Mitchell Committed by Mark Mitchell

class.c (subobject_offset_fn): New type.

	* class.c (subobject_offset_fn): New type.
	(dfs_record_base_offsets): Remove.
	(record_base_offsets): Likewise.
	(dfs_search_base_offsets): Likewise.
	(record_subobject_offset): New function.
	(check_subobject_offset): Likewise.
	(walk_subobject_offsets): Likewise.
	(record_subobject_offsets): Likewise.
	(layout_conflict_p): Reimplement.
	(layout_nonempty_base_or_field): Correct handling of type
	conflicts during layout.
	(layout_empty_base): Likewise.
	(build_base_field): Adjust to handle new representation of empty
	base offset table.
	(build_base_fields): Likewise.
	(layout_virtual_bases): Likewise.
	(splay_tree_compare_integer_csts): New function.
	(layout_class_type): Use a splay_tree, rather than a varray, to
	represent the offsets of empty bases.

From-SVN: r36958
parent bf6d9fd7
2000-10-19 Mark Mitchell <mark@codesourcery.com> 2000-10-19 Mark Mitchell <mark@codesourcery.com>
* class.c (subobject_offset_fn): New type.
(dfs_record_base_offsets): Remove.
(record_base_offsets): Likewise.
(dfs_search_base_offsets): Likewise.
(record_subobject_offset): New function.
(check_subobject_offset): Likewise.
(walk_subobject_offsets): Likewise.
(record_subobject_offsets): Likewise.
(layout_conflict_p): Reimplement.
(layout_nonempty_base_or_field): Correct handling of type
conflicts during layout.
(layout_empty_base): Likewise.
(build_base_field): Adjust to handle new representation of empty
base offset table.
(build_base_fields): Likewise.
(layout_virtual_bases): Likewise.
(splay_tree_compare_integer_csts): New function.
(layout_class_type): Use a splay_tree, rather than a varray, to
represent the offsets of empty bases.
* cp-tree.h (DECL_ANTICIPATED): Don't require a FUNCTION_DECL. * cp-tree.h (DECL_ANTICIPATED): Don't require a FUNCTION_DECL.
* decl.c (select_decl): Don't return declarations that are * decl.c (select_decl): Don't return declarations that are
DECL_ANTICIPATED. DECL_ANTICIPATED.
......
...@@ -89,6 +89,9 @@ typedef struct vtbl_init_data_s ...@@ -89,6 +89,9 @@ typedef struct vtbl_init_data_s
int ctor_vtbl_p; int ctor_vtbl_p;
} vtbl_init_data; } vtbl_init_data;
/* The type of a function passed to walk_subobject_offsets. */
typedef int (*subobject_offset_fn) PARAMS ((tree, tree, splay_tree));
/* The stack itself. This is an dynamically resized array. The /* The stack itself. This is an dynamically resized array. The
number of elements allocated is CURRENT_CLASS_STACK_SIZE. */ number of elements allocated is CURRENT_CLASS_STACK_SIZE. */
static int current_class_stack_size; static int current_class_stack_size;
...@@ -142,8 +145,9 @@ static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *)); ...@@ -142,8 +145,9 @@ static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *, static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *)); int *));
static void build_base_field PARAMS ((record_layout_info, tree, int *, static void build_base_field PARAMS ((record_layout_info, tree, int *,
unsigned int *, varray_type *)); unsigned int *, splay_tree));
static varray_type build_base_fields PARAMS ((record_layout_info, int *)); static void build_base_fields PARAMS ((record_layout_info, int *,
splay_tree));
static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *)); static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree, static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
int *)); int *));
...@@ -157,7 +161,7 @@ static void fixup_pending_inline PARAMS ((tree)); ...@@ -157,7 +161,7 @@ static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree)); static void fixup_inline_methods PARAMS ((tree));
static void set_primary_base PARAMS ((tree, tree, int *)); static void set_primary_base PARAMS ((tree, tree, int *));
static void propagate_binfo_offsets PARAMS ((tree, tree)); static void propagate_binfo_offsets PARAMS ((tree, tree));
static void layout_virtual_bases PARAMS ((tree, varray_type *)); static void layout_virtual_bases PARAMS ((tree, splay_tree));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *)); static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *)); static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *)); static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
...@@ -174,13 +178,9 @@ static void initialize_vtable PARAMS ((tree, tree)); ...@@ -174,13 +178,9 @@ static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree)); static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info, static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
tree, tree, tree, tree,
varray_type)); splay_tree));
static tree dfs_record_base_offsets PARAMS ((tree, void *));
static void record_base_offsets PARAMS ((tree, varray_type *));
static tree dfs_search_base_offsets PARAMS ((tree, void *));
static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int)); static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type)); static void layout_empty_base PARAMS ((tree, tree, splay_tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree)); static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static void set_vindex PARAMS ((tree, tree, int *)); static void set_vindex PARAMS ((tree, tree, int *));
static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *)); static void build_rtti_vtbl_entries PARAMS ((tree, tree, vtbl_init_data *));
...@@ -199,6 +199,14 @@ static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *)); ...@@ -199,6 +199,14 @@ static tree dfs_build_secondary_vptr_vtt_inits PARAMS ((tree, void *));
static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *)); static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
static tree get_matching_base PARAMS ((tree, tree)); static tree get_matching_base PARAMS ((tree, tree));
static tree dfs_get_primary_binfo PARAMS ((tree, void*)); static tree dfs_get_primary_binfo PARAMS ((tree, void*));
static int record_subobject_offset PARAMS ((tree, tree, splay_tree));
static int check_subobject_offset PARAMS ((tree, tree, splay_tree));
static int walk_subobject_offsets PARAMS ((tree, subobject_offset_fn,
tree, splay_tree, int));
static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
/* Variables shared between class.c and call.c. */ /* Variables shared between class.c and call.c. */
...@@ -3694,116 +3702,208 @@ build_vtbl_or_vbase_field (name, assembler_name, type, class_type, fcontext, ...@@ -3694,116 +3702,208 @@ build_vtbl_or_vbase_field (name, assembler_name, type, class_type, fcontext,
return field; return field;
} }
/* Record the type of BINFO in the slot in DATA (which is really a /* If TYPE is an empty class type, records its OFFSET in the table of
`varray_type *') corresponding to the BINFO_OFFSET. */ OFFSETS. */
static tree static int
dfs_record_base_offsets (binfo, data) record_subobject_offset (type, offset, offsets)
tree binfo; tree type;
void *data; tree offset;
splay_tree offsets;
{ {
varray_type *v; splay_tree_node n;
unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
v = (varray_type *) data; if (!is_empty_class (type))
while (VARRAY_SIZE (*v) <= offset) return 0;
VARRAY_GROW (*v, 2 * VARRAY_SIZE (*v));
VARRAY_TREE (*v, offset) = tree_cons (NULL_TREE,
BINFO_TYPE (binfo),
VARRAY_TREE (*v, offset));
return NULL_TREE; /* Record the location of this empty object in OFFSETS. */
n = splay_tree_lookup (offsets, (splay_tree_key) offset);
if (!n)
n = splay_tree_insert (offsets,
(splay_tree_key) offset,
(splay_tree_value) NULL_TREE);
n->value = ((splay_tree_value)
tree_cons (NULL_TREE,
type,
(tree) n->value));
return 0;
} }
/* Add the offset of BINFO and its bases to BASE_OFFSETS. */ /* Returns non-zero if TYPE is an empty class type and there is
already an entry in OFFSETS for the same TYPE as the same OFFSET. */
static void static int
record_base_offsets (binfo, base_offsets) check_subobject_offset (type, offset, offsets)
tree binfo; tree type;
varray_type *base_offsets; tree offset;
splay_tree offsets;
{ {
dfs_walk (binfo, splay_tree_node n;
dfs_record_base_offsets, tree t;
dfs_skip_vbases,
base_offsets); if (!is_empty_class (type))
return 0;
/* Record the location of this empty object in OFFSETS. */
n = splay_tree_lookup (offsets, (splay_tree_key) offset);
if (!n)
return 0;
for (t = (tree) n->value; t; t = TREE_CHAIN (t))
if (same_type_p (TREE_VALUE (t), type))
return 1;
return 0;
} }
/* Returns non-NULL if there is already an entry in DATA (which is /* Walk through all the subobjects of TYPE (located at OFFSET). Call
really a `varray_type') indicating that an object with the same F for every subobject, passing it the type, offset, and table of
type of BINFO is already at the BINFO_OFFSET for BINFO. */ OFFSETS. If VBASES_P is non-zero, then even non-virtual primary
bases should be traversed; otherwise, they are ignored. If F
returns a non-zero value, the traversal ceases, and that value is
returned. Otherwise, returns zero. */
static tree static int
dfs_search_base_offsets (binfo, data) walk_subobject_offsets (type, f, offset, offsets, vbases_p)
tree binfo; tree type;
void *data; subobject_offset_fn f;
tree offset;
splay_tree offsets;
int vbases_p;
{ {
if (is_empty_class (BINFO_TYPE (binfo))) int r = 0;
if (CLASS_TYPE_P (type))
{ {
varray_type v = (varray_type) data; tree field;
/* Find the offset for this BINFO. */ int i;
unsigned HOST_WIDE_INT offset = tree_low_cst (BINFO_OFFSET (binfo), 1);
tree t;
/* If we haven't yet encountered any objects at offsets that /* Record the location of TYPE. */
big, then there's no conflict. */ r = (*f) (type, offset, offsets);
if (VARRAY_SIZE (v) <= offset) if (r)
return NULL_TREE; return r;
/* Otherwise, go through the objects already allocated at this
offset. */ /* Iterate through the direct base classes of TYPE. */
for (t = VARRAY_TREE (v, offset); t; t = TREE_CHAIN (t)) for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
if (same_type_p (TREE_VALUE (t), BINFO_TYPE (binfo))) {
return binfo; tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
&& !BINFO_PRIMARY_MARKED_P (binfo))
continue;
r = walk_subobject_offsets (BINFO_TYPE (binfo),
f,
size_binop (PLUS_EXPR,
offset,
BINFO_OFFSET (binfo)),
offsets,
vbases_p);
if (r)
return r;
} }
return NULL_TREE; /* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
r = walk_subobject_offsets (TREE_TYPE (field),
f,
size_binop (PLUS_EXPR,
offset,
DECL_FIELD_OFFSET (field)),
offsets,
/*vbases_p=*/1);
if (r)
return r;
}
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
tree domain = TYPE_DOMAIN (type);
tree index;
/* Step through each of the elements in the array. */
for (index = size_zero_node;
INT_CST_LT (index, TYPE_MAX_VALUE (domain));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
f,
offset,
offsets,
/*vbases_p=*/1);
if (r)
return r;
offset = size_binop (PLUS_EXPR, offset,
TYPE_SIZE_UNIT (TREE_TYPE (type)));
}
}
return 0;
} }
/* Returns non-zero if there's a conflict between BINFO and a base /* Record all of the empty subobjects of TYPE (located at OFFSET) in
already mentioned in BASE_OFFSETS if BINFO is placed at its current OFFSETS. If VBASES_P is non-zero, virtual bases of TYPE are
BINFO_OFFSET. */ examined. */
static void
record_subobject_offsets (type, offset, offsets, vbases_p)
tree type;
tree offset;
splay_tree offsets;
int vbases_p;
{
walk_subobject_offsets (type, record_subobject_offset, offset,
offsets, vbases_p);
}
/* Returns non-zero if any of the empty subobjects of TYPE (located at
OFFSET) conflict with entries in OFFSETS. If VBASES_P is non-zero,
virtual bases of TYPE are examined. */
static int static int
layout_conflict_p (binfo, base_offsets) layout_conflict_p (type, offset, offsets, vbases_p)
tree binfo; tree type;
varray_type base_offsets; tree offset;
splay_tree offsets;
int vbases_p;
{ {
return dfs_walk (binfo, dfs_search_base_offsets, dfs_skip_vbases, return walk_subobject_offsets (type, check_subobject_offset, offset,
base_offsets) != NULL_TREE; offsets, vbases_p);
} }
/* DECL is a FIELD_DECL corresponding either to a base subobject of a /* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the non-static data member of the type indicated by RLI. BINFO is the
binfo corresponding to the base subobject, or, if this is a binfo corresponding to the base subobject, OFFSETS maps offsets to
non-static data-member, a dummy BINFO for the type of the data types already located at those offsets. This function determines
member. BINFO may be NULL if checks to see if the field overlaps the position of the DECL. */
an existing field with the same type are not required. V maps
offsets to types already located at those offsets. This function
determines the position of the DECL. */
static void static void
layout_nonempty_base_or_field (rli, decl, binfo, v) layout_nonempty_base_or_field (rli, decl, binfo, offsets)
record_layout_info rli; record_layout_info rli;
tree decl; tree decl;
tree binfo; tree binfo;
varray_type v; splay_tree offsets;
{ {
tree offset = NULL_TREE;
tree type = TREE_TYPE (decl);
/* If we are laying out a base class, rather than a field, then
DECL_ARTIFICIAL will be set on the FIELD_DECL. */
int field_p = !DECL_ARTIFICIAL (decl);
/* Try to place the field. It may take more than one try if we have /* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the a hard time placing the field without putting two objects of the
same type at the same address. */ same type at the same address. */
while (1) while (1)
{ {
tree offset;
struct record_layout_info_s old_rli = *rli; struct record_layout_info_s old_rli = *rli;
/* Place this field. */ /* Place this field. */
place_field (rli, decl); place_field (rli, decl);
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
offset = byte_position (decl); offset = byte_position (decl);
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
propagate_binfo_offsets (binfo,
convert (ssizetype, offset));
/* We have to check to see whether or not there is already /* We have to check to see whether or not there is already
something of the same type at the offset we're about to use. something of the same type at the offset we're about to use.
...@@ -3820,40 +3920,46 @@ layout_nonempty_base_or_field (rli, decl, binfo, v) ...@@ -3820,40 +3920,46 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
empty class, have non-zero size, any overlap can happen only empty class, have non-zero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with with a direct or indirect base-class -- it can't happen with
a data member. */ a data member. */
if (binfo && flag_new_abi && layout_conflict_p (binfo, v)) if (flag_new_abi && layout_conflict_p (TREE_TYPE (decl),
offset,
offsets,
field_p))
{ {
/* Undo the propagate_binfo_offsets call. */
offset = size_diffop (size_zero_node, offset);
propagate_binfo_offsets (binfo, convert (ssizetype, offset));
/* Strip off the size allocated to this field. That puts us /* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with at the first place we could have put the field with
proper alignment. */ proper alignment. */
*rli = old_rli; *rli = old_rli;
/* Bump up by the alignment required for the type, without /* Bump up by the alignment required for the type. */
virtual base classes. */
rli->bitpos rli->bitpos
= size_binop (PLUS_EXPR, rli->bitpos, = size_binop (PLUS_EXPR, rli->bitpos,
bitsize_int (CLASSTYPE_ALIGN (BINFO_TYPE (binfo)))); bitsize_int (binfo
? CLASSTYPE_ALIGN (type)
: TYPE_ALIGN (type)));
normalize_rli (rli); normalize_rli (rli);
} }
else else
/* There was no conflict. We're done laying out this field. */ /* There was no conflict. We're done laying out this field. */
break; break;
} }
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
propagate_binfo_offsets (binfo,
convert (ssizetype, offset));
} }
/* Layout the empty base BINFO. EOC indicates the byte currently just /* Layout the empty base BINFO. EOC indicates the byte currently just
past the end of the class, and should be correctly aligned for a past the end of the class, and should be correctly aligned for a
class of the type indicated by BINFO; BINFO_OFFSETS gives the class of the type indicated by BINFO; OFFSETS gives the offsets of
offsets of the other bases allocated so far. */ the empty bases allocated so far. */
static void static void
layout_empty_base (binfo, eoc, binfo_offsets) layout_empty_base (binfo, eoc, offsets)
tree binfo; tree binfo;
tree eoc; tree eoc;
varray_type binfo_offsets; splay_tree offsets;
{ {
tree alignment; tree alignment;
tree basetype = BINFO_TYPE (binfo); tree basetype = BINFO_TYPE (binfo);
...@@ -3864,14 +3970,20 @@ layout_empty_base (binfo, eoc, binfo_offsets) ...@@ -3864,14 +3970,20 @@ layout_empty_base (binfo, eoc, binfo_offsets)
/* This is an empty base class. We first try to put it at offset /* This is an empty base class. We first try to put it at offset
zero. */ zero. */
if (layout_conflict_p (binfo, binfo_offsets)) if (layout_conflict_p (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
{ {
/* That didn't work. Now, we move forward from the next /* That didn't work. Now, we move forward from the next
available spot in the class. */ available spot in the class. */
propagate_binfo_offsets (binfo, convert (ssizetype, eoc)); propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
while (1) while (1)
{ {
if (!layout_conflict_p (binfo, binfo_offsets)) if (!layout_conflict_p (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0))
/* We finally found a spot where there's no overlap. */ /* We finally found a spot where there's no overlap. */
break; break;
...@@ -3884,15 +3996,15 @@ layout_empty_base (binfo, eoc, binfo_offsets) ...@@ -3884,15 +3996,15 @@ layout_empty_base (binfo, eoc, binfo_offsets)
/* Build a FIELD_DECL for the base given by BINFO in the class /* Build a FIELD_DECL for the base given by BINFO in the class
indicated by RLI. If the new object is non-empty, clear *EMPTY_P. indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
*BASE_ALIGN is a running maximum of the alignments of any base *BASE_ALIGN is a running maximum of the alignments of any base
class. */ class. OFFSETS gives the location of empty base subobjects. */
static void static void
build_base_field (rli, binfo, empty_p, base_align, v) build_base_field (rli, binfo, empty_p, base_align, offsets)
record_layout_info rli; record_layout_info rli;
tree binfo; tree binfo;
int *empty_p; int *empty_p;
unsigned int *base_align; unsigned int *base_align;
varray_type *v; splay_tree offsets;
{ {
tree basetype = BINFO_TYPE (binfo); tree basetype = BINFO_TYPE (binfo);
tree decl; tree decl;
...@@ -3933,7 +4045,7 @@ build_base_field (rli, binfo, empty_p, base_align, v) ...@@ -3933,7 +4045,7 @@ build_base_field (rli, binfo, empty_p, base_align, v)
/* Try to place the field. It may take more than one try if we /* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two have a hard time placing the field without putting two
objects of the same type at the same address. */ objects of the same type at the same address. */
layout_nonempty_base_or_field (rli, decl, binfo, *v); layout_nonempty_base_or_field (rli, decl, binfo, offsets);
} }
else else
{ {
...@@ -3942,8 +4054,8 @@ build_base_field (rli, binfo, empty_p, base_align, v) ...@@ -3942,8 +4054,8 @@ build_base_field (rli, binfo, empty_p, base_align, v)
/* On some platforms (ARM), even empty classes will not be /* On some platforms (ARM), even empty classes will not be
byte-aligned. */ byte-aligned. */
eoc = tree_low_cst (rli_size_unit_so_far (rli), 0); eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
eoc = CEIL (eoc, DECL_ALIGN (decl)) * DECL_ALIGN (decl); eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
layout_empty_base (binfo, size_int (eoc), *v); layout_empty_base (binfo, size_int (eoc), offsets);
} }
/* Check for inaccessible base classes. If the same base class /* Check for inaccessible base classes. If the same base class
...@@ -3954,33 +4066,33 @@ build_base_field (rli, binfo, empty_p, base_align, v) ...@@ -3954,33 +4066,33 @@ build_base_field (rli, binfo, empty_p, base_align, v)
basetype, rli->t); basetype, rli->t);
/* Record the offsets of BINFO and its base subobjects. */ /* Record the offsets of BINFO and its base subobjects. */
record_base_offsets (binfo, v); record_subobject_offsets (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
} }
/* Layout all of the non-virtual base classes. Returns a map from /* Layout all of the non-virtual base classes. Record empty
offsets to types present at those offsets. */ subobjects in OFFSETS. */
static varray_type static void
build_base_fields (rli, empty_p) build_base_fields (rli, empty_p, offsets)
record_layout_info rli; record_layout_info rli;
int *empty_p; int *empty_p;
splay_tree offsets;
{ {
/* Chain to hold all the new FIELD_DECLs which stand in for base class /* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */ subobjects. */
tree rec = rli->t; tree rec = rli->t;
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec); int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
int i; int i;
varray_type v;
unsigned int base_align = 0; unsigned int base_align = 0;
/* Create the table mapping offsets to empty base classes. */
VARRAY_TREE_INIT (v, 32, "v");
/* Under the new ABI, the primary base class is always allocated /* Under the new ABI, the primary base class is always allocated
first. */ first. */
if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec)) if (flag_new_abi && CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec), build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
empty_p, &base_align, &v); empty_p, &base_align, offsets);
/* Now allocate the rest of the bases. */ /* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i) for (i = 0; i < n_baseclasses; ++i)
...@@ -4001,10 +4113,8 @@ build_base_fields (rli, empty_p) ...@@ -4001,10 +4113,8 @@ build_base_fields (rli, empty_p)
&& !BINFO_PRIMARY_MARKED_P (base_binfo)) && !BINFO_PRIMARY_MARKED_P (base_binfo))
continue; continue;
build_base_field (rli, base_binfo, empty_p, &base_align, &v); build_base_field (rli, base_binfo, empty_p, &base_align, offsets);
} }
return v;
} }
/* Go through the TYPE_METHODS of T issuing any appropriate /* Go through the TYPE_METHODS of T issuing any appropriate
...@@ -4573,13 +4683,13 @@ dfs_set_offset_for_unshared_vbases (binfo, data) ...@@ -4573,13 +4683,13 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
} }
/* Set BINFO_OFFSET for all of the virtual bases for T. Update /* Set BINFO_OFFSET for all of the virtual bases for T. Update
TYPE_ALIGN and TYPE_SIZE for T. BASE_OFFSETS is a varray mapping TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
offsets to the types at those offsets. */ empty subobjects of T. */
static void static void
layout_virtual_bases (t, base_offsets) layout_virtual_bases (t, offsets)
tree t; tree t;
varray_type *base_offsets; splay_tree offsets;
{ {
tree vbases; tree vbases;
unsigned HOST_WIDE_INT dsize; unsigned HOST_WIDE_INT dsize;
...@@ -4649,7 +4759,7 @@ layout_virtual_bases (t, base_offsets) ...@@ -4649,7 +4759,7 @@ layout_virtual_bases (t, base_offsets)
if (flag_new_abi && is_empty_class (basetype)) if (flag_new_abi && is_empty_class (basetype))
layout_empty_base (vbase, layout_empty_base (vbase,
size_int (CEIL (dsize, BITS_PER_UNIT)), size_int (CEIL (dsize, BITS_PER_UNIT)),
*base_offsets); offsets);
else else
{ {
tree offset; tree offset;
...@@ -4669,7 +4779,10 @@ layout_virtual_bases (t, base_offsets) ...@@ -4669,7 +4779,10 @@ layout_virtual_bases (t, base_offsets)
} }
/* Keep track of the offsets assigned to this virtual base. */ /* Keep track of the offsets assigned to this virtual base. */
record_base_offsets (vbase, base_offsets); record_subobject_offsets (BINFO_TYPE (vbase),
BINFO_OFFSET (vbase),
offsets,
/*vbases_p=*/0);
} }
} }
...@@ -4744,6 +4857,16 @@ end_of_class (t, include_virtuals_p) ...@@ -4744,6 +4857,16 @@ end_of_class (t, include_virtuals_p)
return result; return result;
} }
/* Compare two INTEGER_CSTs K1 and K2. */
static int
splay_tree_compare_integer_csts (k1, k2)
splay_tree_key k1;
splay_tree_key k2;
{
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate /* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable BINFO_OFFSETs for all of the base-classes. Position the vtable
pointer. */ pointer. */
...@@ -4761,8 +4884,10 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -4761,8 +4884,10 @@ layout_class_type (t, empty_p, vfuns_p,
tree field; tree field;
tree vptr; tree vptr;
record_layout_info rli; record_layout_info rli;
varray_type v;
unsigned HOST_WIDE_INT eoc; unsigned HOST_WIDE_INT eoc;
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
/* Keep track of the first non-static data member. */ /* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t); non_static_data_members = TYPE_FIELDS (t);
...@@ -4787,7 +4912,9 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -4787,7 +4912,9 @@ layout_class_type (t, empty_p, vfuns_p,
} }
/* Build FIELD_DECLs for all of the non-virtual base-types. */ /* Build FIELD_DECLs for all of the non-virtual base-types. */
v = build_base_fields (rli, empty_p); empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
build_base_fields (rli, empty_p, empty_base_offsets);
/* Add pointers to all of our virtual base-classes. */ /* Add pointers to all of our virtual base-classes. */
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p), TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
TYPE_FIELDS (t)); TYPE_FIELDS (t));
...@@ -4800,7 +4927,6 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -4800,7 +4927,6 @@ layout_class_type (t, empty_p, vfuns_p,
/* Layout the non-static data members. */ /* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field)) for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{ {
tree binfo;
tree type; tree type;
tree padding; tree padding;
...@@ -4852,10 +4978,8 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -4852,10 +4978,8 @@ layout_class_type (t, empty_p, vfuns_p,
else else
padding = NULL_TREE; padding = NULL_TREE;
/* Create a dummy BINFO corresponding to this field. */ layout_nonempty_base_or_field (rli, field, NULL_TREE,
binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE); empty_base_offsets);
unshare_base_binfos (binfo);
layout_nonempty_base_or_field (rli, field, binfo, v);
/* If we needed additional padding after this field, add it /* If we needed additional padding after this field, add it
now. */ now. */
...@@ -4870,7 +4994,9 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -4870,7 +4994,9 @@ layout_class_type (t, empty_p, vfuns_p,
DECL_SIZE (padding_field) = padding; DECL_SIZE (padding_field) = padding;
DECL_ALIGN (padding_field) = 1; DECL_ALIGN (padding_field) = 1;
DECL_USER_ALIGN (padding_field) = 0; DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, v); layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
empty_base_offsets);
} }
} }
...@@ -4956,10 +5082,10 @@ layout_class_type (t, empty_p, vfuns_p, ...@@ -4956,10 +5082,10 @@ layout_class_type (t, empty_p, vfuns_p,
around. We must get these done before we try to lay out the around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the virtual function table. As a side-effect, this will remove the
base subobject fields. */ base subobject fields. */
layout_virtual_bases (t, &v); layout_virtual_bases (t, empty_base_offsets);
/* Clean up. */ /* Clean up. */
VARRAY_FREE (v); splay_tree_delete (empty_base_offsets);
} }
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment