Commit 80ec27c8 by Mark Mitchell Committed by Mark Mitchell

class.c (create_vtable_ptr): Put the vtable at the beginning of the class, not…

class.c (create_vtable_ptr): Put the vtable at the beginning of the class, not the end, in the new ABI.

	* class.c (create_vtable_ptr): Put the vtable at the beginning of
	the class, not the end, in the new ABI.
	* tree.c (propagate_binfo_offsets): Do the right thing for the new
	ABI.

From-SVN: r31120
parent 71e33c0d
1999-12-29 Mark Mitchell <mark@codesourcery.com> 1999-12-29 Mark Mitchell <mark@codesourcery.com>
* class.c (create_vtable_ptr): Put the vtable at the beginning of
the class, not the end, in the new ABI.
* tree.c (propagate_binfo_offsets): Do the right thing for the new
ABI.
1999-12-29 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (lang_type): Add nearly_empty_p. Adjust dummy. * cp-tree.h (lang_type): Add nearly_empty_p. Adjust dummy.
(CLASSTYPE_NEARLY_EMPTY_P): New macro. (CLASSTYPE_NEARLY_EMPTY_P): New macro.
* class.c (check_bases): Update CLASSTYPE_NEARLY_EMPTY_P. * class.c (check_bases): Update CLASSTYPE_NEARLY_EMPTY_P.
......
...@@ -4136,7 +4136,22 @@ create_vtable_ptr (t, empty_p, has_virtual_p, max_has_virtual_p, ...@@ -4136,7 +4136,22 @@ create_vtable_ptr (t, empty_p, has_virtual_p, max_has_virtual_p,
empty_p); empty_p);
/* Add the new field to the list of fields in this class. */ /* Add the new field to the list of fields in this class. */
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t)); if (!flag_new_abi)
/* In the old ABI, the vtable pointer goes at the end of the
class. */
TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), TYPE_VFIELD (t));
else
{
/* But in the new ABI, the vtable pointer is the first thing
in the class. */
TYPE_FIELDS (t) = chainon (TYPE_VFIELD (t), TYPE_FIELDS (t));
/* If there were any baseclasses, they can't possibly be at
offset zero any more, because that's where the vtable
pointer is. So, converting to a base class is going to
take work. */
if (CLASSTYPE_N_BASECLASSES (t))
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (t) = 1;
}
/* We can't yet add this new field to the list of all virtual /* We can't yet add this new field to the list of all virtual
function table pointers in this class. The function table pointers in this class. The
......
...@@ -671,36 +671,81 @@ propagate_binfo_offsets (binfo, offset) ...@@ -671,36 +671,81 @@ propagate_binfo_offsets (binfo, offset)
tree binfos = BINFO_BASETYPES (binfo); tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = 0; i < n_baselinks; /* note increment is done in the loop. */) if (flag_new_abi)
{ {
tree base_binfo = TREE_VEC_ELT (binfos, i); for (i = 0; i < n_baselinks; ++i)
if (TREE_VIA_VIRTUAL (base_binfo))
i += 1;
else
{ {
int j; tree base_binfo;
tree delta = NULL_TREE;
/* Figure out which base we're looking at. */
for (j = i+1; j < n_baselinks; j++) base_binfo = TREE_VEC_ELT (binfos, i);
if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
{ /* Skip virtual bases. Their BINFO_OFFSET doesn't matter
/* The next basetype offset must take into account the space since they are always reached by using offsets looked up
between the classes, not just the size of each class. */ at run-time. */
delta = size_binop (MINUS_EXPR, if (TREE_VIA_VIRTUAL (base_binfo))
BINFO_OFFSET (TREE_VEC_ELT (binfos, j)), continue;
BINFO_OFFSET (base_binfo));
break; /* Whatever offset this class used to have in its immediate
} derived class, it is now at OFFSET more bytes in its
final derived class, since the immediate derived class is
BINFO_OFFSET (base_binfo) = offset; already at the indicated OFFSET. */
BINFO_OFFSET (base_binfo)
= size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), offset);
propagate_binfo_offsets (base_binfo, offset); propagate_binfo_offsets (base_binfo, offset);
}
}
else
{
/* This algorithm, used for the old ABI, is neither simple, nor
general. For example, it mishandles the case of:
struct A;
struct B : public A;
struct C : public B;
if B is at offset zero in C, but A is not in offset zero in
B. In that case, it sets the BINFO_OFFSET for A to zero.
(This sitution arises in the new ABI if B has virtual
functions, but A does not.) Rather than change this
algorithm, and risking breaking the old ABI, it is preserved
here. */
for (i = 0; i < n_baselinks; /* note increment is done in the
loop. */)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
/* Go to our next class that counts for offset propagation. */ if (TREE_VIA_VIRTUAL (base_binfo))
i = j; i += 1;
if (i < n_baselinks) else
offset = size_binop (PLUS_EXPR, offset, delta); {
int j;
tree delta = NULL_TREE;
for (j = i+1; j < n_baselinks; j++)
if (! TREE_VIA_VIRTUAL (TREE_VEC_ELT (binfos, j)))
{
/* The next basetype offset must take into account
the space between the classes, not just the
size of each class. */
delta = size_binop (MINUS_EXPR,
BINFO_OFFSET (TREE_VEC_ELT (binfos,
j)),
BINFO_OFFSET (base_binfo));
break;
}
BINFO_OFFSET (base_binfo) = offset;
propagate_binfo_offsets (base_binfo, offset);
/* Go to our next class that counts for offset
propagation. */
i = j;
if (i < n_baselinks)
offset = size_binop (PLUS_EXPR, offset, delta);
}
} }
} }
} }
......
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