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
This commit is contained in:
Mark Mitchell 1999-12-29 20:05:41 +00:00 committed by Mark Mitchell
parent 71e33c0d12
commit 80ec27c8f4
3 changed files with 91 additions and 24 deletions

View File

@ -1,3 +1,10 @@
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.

View File

@ -4136,7 +4136,22 @@ create_vtable_ptr (t, empty_p, has_virtual_p, max_has_virtual_p,
empty_p);
/* 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
function table pointers in this class. The

View File

@ -671,36 +671,81 @@ propagate_binfo_offsets (binfo, offset)
tree binfos = BINFO_BASETYPES (binfo);
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);
if (TREE_VIA_VIRTUAL (base_binfo))
i += 1;
else
for (i = 0; i < n_baselinks; ++i)
{
int j;
tree delta = NULL_TREE;
tree base_binfo;
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;
}
/* Figure out which base we're looking at. */
base_binfo = TREE_VEC_ELT (binfos, i);
BINFO_OFFSET (base_binfo) = offset;
/* Skip virtual bases. Their BINFO_OFFSET doesn't matter
since they are always reached by using offsets looked up
at run-time. */
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
/* 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
already at the indicated OFFSET. */
BINFO_OFFSET (base_binfo)
= size_binop (PLUS_EXPR, BINFO_OFFSET (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. */
i = j;
if (i < n_baselinks)
offset = size_binop (PLUS_EXPR, offset, delta);
if (TREE_VIA_VIRTUAL (base_binfo))
i += 1;
else
{
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);
}
}
}
}