Put RTTI entries at negative offsets in new ABI.

* class.c (dfs_build_vbase_offset_vtbl_entries): Put the first
	vbase offset at index -3, not -1.
	(build_vtabe_offset_vtbl_entries): Use unmarked_vtable_pathp, not
	dfs_vtable_path_unmarked_real_bases_queue_p to walk bases.
	(dfs_build_vcall_offset_vtbl_entries): Don't use skip_rtti_stuff.
	(build_rtti_vtbl_entries): New function.
	(set_rtti_entry): Remove.
	(build_primary_vtable): Don't use it.
	(build_secondary_vtable): Likewise.
	(start_vtable): Remove.
	(first_vfun_index): New function.
	(set_vindex): Likewise.
	(add_virtual_function): Don't call start_vtable.  Do call
	set_vindex.
	(set_primary_base): Rename parameter.
	(determine_primary_base): Likewise.
	(num_vfun_entries): Don't use skip_rtti_stuff.
	(num_extra_vtbl_entries): Include RTTI information.
	(build_vtbl_initializer): Use build_rtti_vtbl_entries.
	(skip_rtti_stuff): Remove.
	(dfs_modify_vtables): Don't use it.
	(modify_all_vtables): Don't use start_vtable.  Do use set_vindex.
	(layout_nonempty_base_or_field): Update size handling.
	(create_vtable_ptr): Tweak.
	(layout_class_type): Adjust parameter names.
	(finish_struct_1): Simplify.
	* cp-tree.h (CLASSTYPE_VSIZE): Tweak documentation.
	(skip_rtti_stuff): Remove.
	(first_vfun_index): New function.
	(dfs_vtable_path_unmarked_real_bases_queue_p): Remove.
	(dfs_vtable_path_marked_real_bases_queue_p): Remove.
	(marked_vtable_pathp): Declare.
	(unmarked_vtable_pathp): Likewise.
	* error.c (dump_expr): Use first_vfun_index to calculate vtable
	offsets.
	* rtti.c (build_headof): Look for RTTI at negative offsets.
	(get_tinfo_decl_dynamic): Likewise.
	(tinfo_base_init): Don't take the address of the TINFO_VTABLE_DECL
	here.
	(create_pseudo_type_info): Do it here instead.  Adjust so that
	vptr points at first virtual function.
	* search.c (marked_vtable_pathp): Make it global.
	(unmarked_vtable_pathp): Likewise.
	(dfs_vtable_path_unmarked_real_bases_queue_p): Remove.
	(dfs_vtable_path_marked_real_bases_queue_p): Likewise.
	(dfs_get_pure_virtuals): Don't use skip_rtti_stuff.
	(get_pure_virtuals): Likewise.
	(expand_upcast_fixups): Likewise.
	* tree.c (debug_binfo): Likewise.
	* tinfo.cc (__dynamic_cast): Look for vtable_prefix at appropriate
	negative offset.

From-SVN: r32787
This commit is contained in:
Mark Mitchell 2000-03-28 19:27:15 +00:00 committed by Mark Mitchell
parent 65a0aad55d
commit da3d4dfa91
8 changed files with 275 additions and 287 deletions

View File

@ -1,3 +1,58 @@
2000-03-28 Mark Mitchell <mark@codesourcery.com>
Put RTTI entries at negative offsets in new ABI.
* class.c (dfs_build_vbase_offset_vtbl_entries): Put the first
vbase offset at index -3, not -1.
(build_vtabe_offset_vtbl_entries): Use unmarked_vtable_pathp, not
dfs_vtable_path_unmarked_real_bases_queue_p to walk bases.
(dfs_build_vcall_offset_vtbl_entries): Don't use skip_rtti_stuff.
(build_rtti_vtbl_entries): New function.
(set_rtti_entry): Remove.
(build_primary_vtable): Don't use it.
(build_secondary_vtable): Likewise.
(start_vtable): Remove.
(first_vfun_index): New function.
(set_vindex): Likewise.
(add_virtual_function): Don't call start_vtable. Do call
set_vindex.
(set_primary_base): Rename parameter.
(determine_primary_base): Likewise.
(num_vfun_entries): Don't use skip_rtti_stuff.
(num_extra_vtbl_entries): Include RTTI information.
(build_vtbl_initializer): Use build_rtti_vtbl_entries.
(skip_rtti_stuff): Remove.
(dfs_modify_vtables): Don't use it.
(modify_all_vtables): Don't use start_vtable. Do use set_vindex.
(layout_nonempty_base_or_field): Update size handling.
(create_vtable_ptr): Tweak.
(layout_class_type): Adjust parameter names.
(finish_struct_1): Simplify.
* cp-tree.h (CLASSTYPE_VSIZE): Tweak documentation.
(skip_rtti_stuff): Remove.
(first_vfun_index): New function.
(dfs_vtable_path_unmarked_real_bases_queue_p): Remove.
(dfs_vtable_path_marked_real_bases_queue_p): Remove.
(marked_vtable_pathp): Declare.
(unmarked_vtable_pathp): Likewise.
* error.c (dump_expr): Use first_vfun_index to calculate vtable
offsets.
* rtti.c (build_headof): Look for RTTI at negative offsets.
(get_tinfo_decl_dynamic): Likewise.
(tinfo_base_init): Don't take the address of the TINFO_VTABLE_DECL
here.
(create_pseudo_type_info): Do it here instead. Adjust so that
vptr points at first virtual function.
* search.c (marked_vtable_pathp): Make it global.
(unmarked_vtable_pathp): Likewise.
(dfs_vtable_path_unmarked_real_bases_queue_p): Remove.
(dfs_vtable_path_marked_real_bases_queue_p): Likewise.
(dfs_get_pure_virtuals): Don't use skip_rtti_stuff.
(get_pure_virtuals): Likewise.
(expand_upcast_fixups): Likewise.
* tree.c (debug_binfo): Likewise.
* tinfo.cc (__dynamic_cast): Look for vtable_prefix at appropriate
negative offset.
Sun Mar 26 20:15:26 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* class.c (check_field_decl): Fix typo.

View File

@ -80,7 +80,6 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
static void set_rtti_entry PARAMS ((tree, tree, tree));
static int build_primary_vtable PARAMS ((tree, tree));
static int build_secondary_vtable PARAMS ((tree, tree));
static tree dfs_finish_vtbls PARAMS ((tree, void *));
@ -142,7 +141,6 @@ static tree dfs_vcall_offset_queue_p PARAMS ((tree, void *));
static tree dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
static tree dfs_count_virtuals PARAMS ((tree, void *));
static void start_vtable PARAMS ((tree, int *));
static void layout_vtable_decl PARAMS ((tree, int));
static int num_vfun_entries PARAMS ((tree));
static tree dfs_find_final_overrider PARAMS ((tree, void *));
@ -162,6 +160,8 @@ static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */
@ -279,7 +279,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
base. */
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list))
BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0);
BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0);
else
{
BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
@ -333,11 +333,11 @@ build_vbase_offset_vtbl_entries (binfo, t)
TREE_TYPE (list) = binfo;
dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries,
dfs_vtable_path_unmarked_real_bases_queue_p,
unmarked_vtable_pathp,
list);
dfs_walk (binfo,
dfs_vtable_path_unmark,
dfs_vtable_path_marked_real_bases_queue_p,
marked_vtable_pathp,
list);
inits = nreverse (TREE_VALUE (list));
@ -405,9 +405,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
/* We chain the offsets on in reverse order. That's correct --
build_vtbl_initializer will straighten them out. */
for (virtuals = skip_rtti_stuff (binfo,
BINFO_TYPE (binfo),
NULL);
for (virtuals = BINFO_VIRTUALS (binfo);
virtuals;
virtuals = TREE_CHAIN (virtuals))
{
@ -486,6 +484,82 @@ build_vcall_offset_vtbl_entries (binfo, t)
return vod.inits;
}
/* Return vtbl initializers for the RTTI entries coresponding to the
BINFO's vtable. BINFO is a part of the hierarchy dominated by
T. */
static tree
build_rtti_vtbl_entries (binfo, t)
tree binfo;
tree t;
{
tree b;
tree basetype;
tree inits;
tree offset;
tree decl;
tree init;
basetype = BINFO_TYPE (binfo);
inits = NULL_TREE;
/* For a COM object there is no RTTI entry. */
if (CLASSTYPE_COM_INTERFACE (basetype))
return inits;
/* To find the complete object, we will first convert to our most
primary base, and then add the offset in the vtbl to that value. */
b = binfo;
while (CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (b)))
b = BINFO_BASETYPE (b,
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (b)));
offset = size_diffop (size_zero_node, BINFO_OFFSET (b));
/* Add the offset-to-top entry. */
if (flag_vtable_thunks)
{
/* Convert the offset to look like a function pointer, so that
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
inits = tree_cons (NULL_TREE, init, inits);
}
/* The second entry is, in the case of the new ABI, the address of
the typeinfo object, or, in the case of the old ABI, a function
which returns a typeinfo object. */
if (new_abi_rtti_p ())
{
if (flag_rtti)
decl = build_unary_op (ADDR_EXPR, get_tinfo_decl (t), 0);
else
decl = integer_zero_node;
/* Convert the declaration to a type that can be stored in the
vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
TREE_CONSTANT (init) = 1;
}
else
{
if (flag_rtti)
decl = get_tinfo_decl (t);
else
decl = abort_fndecl;
/* Convert the declaration to a type that can be stored in the
vtable. */
init = build1 (ADDR_EXPR, vfunc_ptr_type_node, decl);
TREE_CONSTANT (init) = 1;
init = build_vtable_entry (offset, integer_zero_node, init);
}
/* Hook the RTTI declaration onto the list. */
inits = tree_cons (NULL_TREE, init, inits);
return inits;
}
/* Returns a pointer to the virtual base class of EXP that has the
indicated TYPE. EXP is of class type, not a pointer type. */
@ -945,47 +1019,6 @@ get_derived_offset (binfo, type)
return size_binop (MINUS_EXPR, offset1, offset2);
}
/* Update the rtti info for this class. */
static void
set_rtti_entry (virtuals, offset, type)
tree virtuals, offset, type;
{
tree decl;
if (CLASSTYPE_COM_INTERFACE (type))
return;
if (flag_rtti)
decl = get_tinfo_decl (type);
else if (!new_abi_rtti_p ())
/* If someone tries to get RTTI information for a type compiled
without RTTI, they're out of luck. By calling __pure_virtual
in this case, we give a small clue as to what went wrong. We
could consider having a __no_typeinfo function as well, for a
more specific hint. */
decl = abort_fndecl;
else
/* For the new-abi, we just point to the type_info object. */
decl = NULL_TREE;
if (flag_vtable_thunks)
{
/* The first slot holds the offset. */
BV_DELTA (virtuals) = offset;
BV_VCALL_INDEX (virtuals) = integer_zero_node;
/* The next node holds the decl. */
virtuals = TREE_CHAIN (virtuals);
offset = ssize_int (0);
}
/* This slot holds the function to call. */
BV_DELTA (virtuals) = offset;
BV_VCALL_INDEX (virtuals) = integer_zero_node;
BV_FN (virtuals) = decl;
}
/* Create a VAR_DECL for a primary or secondary vtable for
CLASS_TYPE. Use NAME for the name of the vtable, and VTABLE_TYPE
for its type. */
@ -1067,8 +1100,6 @@ build_primary_vtable (binfo, type)
if (binfo)
{
tree offset;
if (BINFO_NEW_VTABLE_MARKED (binfo, type))
/* We have already created a vtable for this base, so there's
no need to do it again. */
@ -1079,11 +1110,6 @@ build_primary_vtable (binfo, type)
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
DECL_SIZE_UNIT (decl)
= TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo)));
/* Now do rtti stuff. */
offset = get_derived_offset (TYPE_BINFO (type), NULL_TREE);
offset = size_diffop (size_zero_node, offset);
set_rtti_entry (virtuals, offset, type);
}
else
{
@ -1171,10 +1197,6 @@ build_secondary_vtable (binfo, for_type)
else
offset = BINFO_OFFSET (binfo);
set_rtti_entry (BINFO_VIRTUALS (binfo),
size_diffop (size_zero_node, offset),
for_type);
/* In the new ABI, secondary vtables are laid out as part of the
same structure as the primary vtable. */
if (merge_primary_and_secondary_vtables_p ())
@ -1349,42 +1371,52 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals)
}
}
/* Call this function whenever its known that a vtable for T is going
to be needed. It's safe to call it more than once. *HAS_VIRTUAL_P
is initialized to the number of slots that are reserved at the
beginning of the vtable for RTTI information. */
/* Return the index (in the virtual function table) of the first
virtual function. */
int
first_vfun_index (t)
tree t;
{
/* Under the old ABI, the offset-to-top and RTTI entries are at
indices zero and one; under the new ABI, the first virtual
function is at index zero. */
if (!CLASSTYPE_COM_INTERFACE (t) && !flag_new_abi)
return flag_vtable_thunks ? 2 : 1;
return 0;
}
/* Set DECL_VINDEX for DECL. VINDEX_P is the number of virtual
functions present in the vtable so far. */
static void
start_vtable (t, has_virtual_p)
set_vindex (t, decl, vfuns_p)
tree t;
int *has_virtual_p;
tree decl;
int *vfuns_p;
{
if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t))
{
/* If we are using thunks, use two slots at the front, one
for the offset pointer, one for the tdesc pointer.
For ARM-style vtables, use the same slot for both. */
if (flag_vtable_thunks)
*has_virtual_p = 2;
else
*has_virtual_p = 1;
}
int vindex;
vindex = (*vfuns_p)++;
vindex += first_vfun_index (t);
DECL_VINDEX (decl) = build_shared_int_cst (vindex);
}
/* Add a virtual function to all the appropriate vtables for the class
T. DECL_VINDEX(X) should be error_mark_node, if we want to
allocate a new slot in our table. If it is error_mark_node, we
know that no other function from another vtable is overridden by X.
HAS_VIRTUAL keeps track of how many virtuals there are in our main
vtable for the type, and we build upon the NEW_VIRTUALS list
VFUNS_P keeps track of how many virtuals there are in our
main vtable for the type, and we build upon the NEW_VIRTUALS list
and return it. */
static void
add_virtual_function (new_virtuals_p, overridden_virtuals_p,
has_virtual, fndecl, t)
vfuns_p, fndecl, t)
tree *new_virtuals_p;
tree *overridden_virtuals_p;
int *has_virtual;
int *vfuns_p;
tree fndecl;
tree t; /* Structure type. */
{
@ -1409,10 +1441,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
/* We remember that this was the base sub-object for rtti. */
CLASSTYPE_RTTI (t) = t;
start_vtable (t, has_virtual);
/* Now assign virtual dispatch information. */
DECL_VINDEX (fndecl) = build_shared_int_cst ((*has_virtual)++);
set_vindex (t, fndecl, vfuns_p);
DECL_VIRTUAL_CONTEXT (fndecl) = t;
/* Save the state we've computed on the NEW_VIRTUALS list. */
@ -1969,10 +1999,10 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
/* Make the Ith baseclass of T its primary base. */
static void
set_primary_base (t, i, has_virtual_p)
set_primary_base (t, i, vfuns_p)
tree t;
int i;
int *has_virtual_p;
int *vfuns_p;
{
tree basetype;
@ -1982,15 +2012,15 @@ set_primary_base (t, i, has_virtual_p)
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
*has_virtual_p = CLASSTYPE_VSIZE (basetype);
*vfuns_p = CLASSTYPE_VSIZE (basetype);
}
/* Determine the primary class for T. */
static void
determine_primary_base (t, has_virtual_p)
determine_primary_base (t, vfuns_p)
tree t;
int *has_virtual_p;
int *vfuns_p;
{
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
@ -1998,7 +2028,7 @@ determine_primary_base (t, has_virtual_p)
if (n_baseclasses == 0)
return;
*has_virtual_p = 0;
*vfuns_p = 0;
for (i = 0; i < n_baseclasses; i++)
{
@ -2021,7 +2051,7 @@ determine_primary_base (t, has_virtual_p)
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
set_primary_base (t, i, has_virtual_p);
set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
}
else
@ -2039,8 +2069,8 @@ determine_primary_base (t, has_virtual_p)
VF_BASETYPE_VALUE (vfields),
CLASSTYPE_VFIELDS (t));
if (*has_virtual_p == 0)
set_primary_base (t, i, has_virtual_p);
if (*vfuns_p == 0)
set_primary_base (t, i, vfuns_p);
}
}
}
@ -2060,7 +2090,7 @@ determine_primary_base (t, has_virtual_p)
if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype))
{
set_primary_base (t, i, has_virtual_p);
set_primary_base (t, i, vfuns_p);
CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
break;
}
@ -2557,9 +2587,7 @@ static int
num_vfun_entries (binfo)
tree binfo;
{
return list_length (skip_rtti_stuff (binfo,
BINFO_TYPE (binfo),
NULL));
return list_length (BINFO_VIRTUALS (binfo));
}
/* Called from num_extra_vtbl_entries via dfs_walk. */
@ -2609,7 +2637,19 @@ num_extra_vtbl_entries (binfo)
entries += vod.offsets;
}
return entries ? size_int (entries) : size_zero_node;
/* When laying out COM-compatible classes, there are no RTTI
entries. */
if (CLASSTYPE_COM_INTERFACE (type))
;
/* When using vtable thunks, there are two RTTI entries: the "offset
to top" value and the RTTI entry itself. */
else if (flag_vtable_thunks)
entries += 2;
/* When not using vtable thunks there is only a single entry. */
else
entries += 1;
return size_int (entries);
}
/* Returns the offset (in bytes) from the beginning of BINFO's vtable
@ -2636,7 +2676,6 @@ build_vtbl_initializer (binfo, t)
{
tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE;
tree type = BINFO_TYPE (binfo);
/* Add entries to the vtable that indicate how to adjust the this
pointer when calling a virtual function in this class. */
@ -2646,48 +2685,8 @@ build_vtbl_initializer (binfo, t)
inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
inits);
/* Process the RTTI stuff at the head of the list. If we're not
using vtable thunks, then the RTTI entry is just an ordinary
function, and we can process it just like the other virtual
function entries. */
if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks)
{
tree offset;
tree init;
/* The first entry is an offset. */
offset = TREE_PURPOSE (v);
my_friendly_assert (TREE_CODE (offset) == INTEGER_CST,
19990727);
/* Convert the offset to look like a function pointer, so that
we can put it in the vtable. */
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
TREE_CONSTANT (init) = 1;
inits = tree_cons (NULL_TREE, init, inits);
v = TREE_CHAIN (v);
if (new_abi_rtti_p ())
{
tree decl = TREE_VALUE (v);
if (decl)
decl = build_unary_op (ADDR_EXPR, decl, 0);
else
decl = integer_zero_node;
decl = build1 (NOP_EXPR, vfunc_ptr_type_node, decl);
TREE_CONSTANT (decl) = 1;
decl = build_vtable_entry (integer_zero_node, integer_zero_node,
decl);
inits = tree_cons (NULL_TREE, decl, inits);
v = TREE_CHAIN (v);
}
/* In the old abi the second entry (the tdesc pointer) is
just an ordinary function, so it can be dealt with like the
virtual functions. */
}
/* Add entries to the vtable for RTTI. */
inits = chainon (build_rtti_vtbl_entries (binfo, t), inits);
/* Go through all the ordinary virtual functions, building up
initializers. */
@ -3048,43 +3047,6 @@ find_final_overrider (t, binfo, fn)
return build_tree_list (ffod.overriding_fn, ffod.overriding_base);
}
/* Return the BINFO_VIRTUALS list for BINFO, without the RTTI stuff at
the front. If non-NULL, N is set to the number of entries
skipped. */
tree
skip_rtti_stuff (binfo, t, n)
tree binfo;
tree t;
HOST_WIDE_INT *n;
{
tree virtuals;
if (CLASSTYPE_COM_INTERFACE (t))
return 0;
if (n)
*n = 0;
virtuals = BINFO_VIRTUALS (binfo);
if (virtuals)
{
/* We always reserve a slot for the offset/tdesc entry. */
if (n)
++*n;
virtuals = TREE_CHAIN (virtuals);
}
if (flag_vtable_thunks && virtuals)
{
/* The second slot is reserved for the tdesc pointer when thunks
are used. */
if (n)
++*n;
virtuals = TREE_CHAIN (virtuals);
}
return virtuals;
}
/* Called via dfs_walk. Returns BINFO if BINFO has the same type as
DATA (which is really an _TYPE node). */
@ -3125,10 +3087,8 @@ dfs_modify_vtables (binfo, data)
/* Now, go through each of the virtual functions in the virtual
function table for BINFO. Find the final overrider, and
update the BINFO_VIRTUALS list appropriately. */
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL),
old_virtuals = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (binfo)),
BINFO_TYPE (binfo),
NULL);
for (virtuals = BINFO_VIRTUALS (binfo),
old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
virtuals;
virtuals = TREE_CHAIN (virtuals),
old_virtuals = TREE_CHAIN (old_virtuals))
@ -3138,17 +3098,16 @@ dfs_modify_vtables (binfo, data)
tree overrider;
tree vindex;
tree delta;
HOST_WIDE_INT vindex_val, i;
HOST_WIDE_INT vindex_val;
HOST_WIDE_INT i;
/* Find the function which originally caused this vtable
entry to be present. */
fn = BV_FN (old_virtuals);
vindex = DECL_VINDEX (fn);
b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
fn = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (b)),
BINFO_TYPE (b),
&i);
fn = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (b)));
i = first_vfun_index (BINFO_TYPE (b));
vindex_val = tree_low_cst (vindex, 0);
while (i < vindex_val)
{
@ -3195,9 +3154,9 @@ dfs_modify_vtables (binfo, data)
which should therefore be appended to the end of the vtable for T. */
static tree
modify_all_vtables (t, has_virtual_p, overridden_virtuals)
modify_all_vtables (t, vfuns_p, overridden_virtuals)
tree t;
int *has_virtual_p;
int *vfuns_p;
tree overridden_virtuals;
{
tree binfo;
@ -3224,11 +3183,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
if (BINFO_VIRTUALS (binfo)
&& !value_member (fn, BINFO_VIRTUALS (binfo)))
{
/* We know we need a vtable for this class now. */
start_vtable (t, has_virtual_p);
/* Set the vtable index. */
DECL_VINDEX (fn)
= build_shared_int_cst ((*has_virtual_p)++);
set_vindex (t, fn, vfuns_p);
/* We don't need to convert to a base class when calling
this function. */
DECL_VIRTUAL_CONTEXT (fn) = t;
@ -4220,9 +4176,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
/* Now that we know where it wil be placed, update its
BINFO_OFFSET. */
offset = convert (ssizetype, byte_position (decl));
offset = byte_position (decl);
if (binfo)
propagate_binfo_offsets (binfo, offset);
propagate_binfo_offsets (binfo,
convert (ssizetype, offset));
/* 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.
@ -4243,7 +4200,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
{
/* Undo the propogate_binfo_offsets call. */
offset = size_diffop (size_zero_node, offset);
propagate_binfo_offsets (binfo, offset);
propagate_binfo_offsets (binfo, convert (ssizetype, offset));
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
@ -4601,11 +4558,11 @@ check_bases_and_members (t, empty_p)
responsibility to do that. */
static tree
create_vtable_ptr (t, empty_p, has_virtual_p,
create_vtable_ptr (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
int *empty_p;
int *has_virtual_p;
int *vfuns_p;
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
@ -4616,17 +4573,15 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
if (DECL_VINDEX (fn))
add_virtual_function (new_virtuals_p, overridden_virtuals_p,
has_virtual_p, fn, t);
vfuns_p, fn, t);
/* Even if there weren't any new virtual functions, we might need a
/* If we couldn't find an appropriate base class, create a new field
here. Even if there weren't any new virtual functions, we might need a
new virtual function table if we're supposed to include vptrs in
all classes that need them. */
if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())
start_vtable (t, has_virtual_p);
/* If we couldn't find an appropriate base class, create a new field
here. */
if (*has_virtual_p && !TYPE_VFIELD (t))
if (!TYPE_VFIELD (t)
&& (*vfuns_p
|| (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())))
{
/* We build this decl with vtbl_ptr_type_node, which is a
`vtable_entry_type*'. It might seem more precise to use
@ -4972,11 +4927,11 @@ end_of_class (t, include_virtuals_p)
pointer. */
static void
layout_class_type (t, empty_p, has_virtual_p,
layout_class_type (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p)
tree t;
int *empty_p;
int *has_virtual_p;
int *vfuns_p;
tree *new_virtuals_p;
tree *overridden_virtuals_p;
{
@ -4995,10 +4950,10 @@ layout_class_type (t, empty_p, has_virtual_p,
/* If possible, we reuse the virtual function table pointer from one
of our base classes. */
determine_primary_base (t, has_virtual_p);
determine_primary_base (t, vfuns_p);
/* Create a pointer to our virtual function table. */
vptr = create_vtable_ptr (t, empty_p, has_virtual_p,
vptr = create_vtable_ptr (t, empty_p, vfuns_p,
new_virtuals_p, overridden_virtuals_p);
/* Under the new ABI, the vptr is always the first thing in the
@ -5215,7 +5170,7 @@ finish_struct_1 (t)
tree t;
{
tree x;
int has_virtual;
int vfuns;
/* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is
a FUNCTION_DECL. Each of these functions is a virtual function
declared in T that does not override any virtual function from a
@ -5246,7 +5201,7 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_VFIELD_PARENT (t) = -1;
has_virtual = 0;
vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE;
/* Do end-of-class semantic processing: checking the validity of the
@ -5254,7 +5209,7 @@ finish_struct_1 (t)
check_bases_and_members (t, &empty);
/* Layout the class itself. */
layout_class_type (t, &empty, &has_virtual,
layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals);
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
@ -5278,7 +5233,7 @@ finish_struct_1 (t)
}
overridden_virtuals
= modify_all_vtables (t, &has_virtual, nreverse (overridden_virtuals));
= modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
/* If necessary, create the primary vtable for this class. */
if (new_virtuals
@ -5288,22 +5243,7 @@ finish_struct_1 (t)
new_virtuals = nreverse (new_virtuals);
/* We must enter these virtuals into the table. */
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t))
{
if (! CLASSTYPE_COM_INTERFACE (t))
{
/* The second slot is for the tdesc pointer when thunks
are used. */
if (flag_vtable_thunks)
new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
/* The first slot is for the rtti offset. */
new_virtuals = tree_cons (NULL_TREE, NULL_TREE, new_virtuals);
set_rtti_entry (new_virtuals,
convert (ssizetype, integer_zero_node), t);
}
build_primary_vtable (NULL_TREE, t);
}
build_primary_vtable (NULL_TREE, t);
else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
/* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */
@ -5346,7 +5286,7 @@ finish_struct_1 (t)
my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
20000116);
CLASSTYPE_VSIZE (t) = has_virtual;
CLASSTYPE_VSIZE (t) = vfuns;
/* Entries for virtual functions defined in the primary base are
followed by entries for new functions unique to this class. */
TYPE_BINFO_VIRTUALS (t)

View File

@ -1545,8 +1545,8 @@ struct lang_type
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
: NULL_TREE)
/* The number of virtual functions defined for this
_CLASSTYPE node. */
/* The number of virtual functions present in this classes virtual
function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* A chain of BINFOs for the direct and indirect virtual base classes
@ -3685,8 +3685,7 @@ extern void push_lang_context PARAMS ((tree));
extern void pop_lang_context PARAMS ((void));
extern tree instantiate_type PARAMS ((tree, tree, int));
extern void print_class_statistics PARAMS ((void));
extern tree skip_rtti_stuff PARAMS ((tree, tree,
HOST_WIDE_INT *));
extern int first_vfun_index PARAMS ((tree));
extern void build_self_reference PARAMS ((void));
extern void warn_hidden PARAMS ((tree));
extern tree get_enclosing_class PARAMS ((tree));
@ -4212,11 +4211,9 @@ extern tree dfs_skip_nonprimary_vbases_unmarkedp PARAMS ((tree, void *));
extern tree dfs_skip_nonprimary_vbases_markedp PARAMS ((tree, void *));
extern tree dfs_unmarked_real_bases_queue_p PARAMS ((tree, void *));
extern tree dfs_marked_real_bases_queue_p PARAMS ((tree, void *));
extern tree dfs_vtable_path_unmarked_real_bases_queue_p
PARAMS ((tree, void *));
extern tree dfs_vtable_path_marked_real_bases_queue_p
PARAMS ((tree, void *));
extern tree dfs_skip_vbases PARAMS ((tree, void *));
extern tree marked_vtable_pathp PARAMS ((tree, void *));
extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
extern void mark_primary_bases PARAMS ((tree));
extern tree convert_pointer_to_vbase PARAMS ((tree, tree));
extern tree find_vbase_instance PARAMS ((tree, tree));

View File

@ -1857,7 +1857,7 @@ dump_expr (t, flags)
t = TYPE_METHOD_BASETYPE (t);
virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
n = tree_low_cst (idx, 0);
n = tree_low_cst (idx, 0) - first_vfun_index (t);
/* Map vtable index back one, to allow for the null pointer to
member. */

View File

@ -132,6 +132,7 @@ build_headof (exp)
tree type = TREE_TYPE (exp);
tree aref;
tree offset;
tree index;
my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112);
type = TREE_TYPE (type);
@ -151,7 +152,15 @@ build_headof (exp)
/* We use this a couple of times below, protect it. */
exp = save_expr (exp);
aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);
/* Under the new ABI, the offset-to-top field is at index -2 from
the vptr. */
if (new_abi_rtti_p ())
index = build_int_2 (-2, -1);
/* But under the old ABI, it is at offset zero. */
else
index = integer_zero_node;
aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), index);
if (flag_vtable_thunks)
offset = aref;
@ -230,6 +239,7 @@ get_tinfo_decl_dynamic (exp)
{
/* build reference to type_info from vtable. */
tree t;
tree index;
if (! flag_rtti)
error ("taking dynamic typeid of object with -fno-rtti");
@ -247,10 +257,15 @@ get_tinfo_decl_dynamic (exp)
exp = build_indirect_ref (exp, NULL_PTR);
}
if (flag_vtable_thunks)
t = build_vfn_ref ((tree *) 0, exp, integer_one_node);
/* The RTTI information is always in the vtable, but it's at
different indices depending on the ABI. */
if (new_abi_rtti_p ())
index = minus_one_node;
else if (flag_vtable_thunks)
index = integer_one_node;
else
t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);
index = integer_zero_node;
t = build_vfn_ref ((tree *) 0, exp, index);
TREE_TYPE (t) = build_pointer_type (tinfo_decl_type);
return t;
}
@ -1284,8 +1299,7 @@ tinfo_base_init (desc, target)
if (TINFO_VTABLE_DECL (desc))
{
tree vtbl_ptr = build_unary_op (ADDR_EXPR, TINFO_VTABLE_DECL (desc), 0);
tree vtbl_ptr = TINFO_VTABLE_DECL (desc);
init = tree_cons (NULL_TREE, vtbl_ptr, init);
}
@ -1616,7 +1630,18 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
/* Get the vtable decl. */
real_type = xref_tag (class_type_node, get_identifier (real_name), 1);
vtable_decl = get_vtable_decl (real_type, /*complete=*/1);
vtable_decl = build_unary_op (ADDR_EXPR, vtable_decl, 0);
/* Under the new ABI, we need to point into the middle of the
vtable. */
if (vbase_offsets_in_vtable_p ())
{
vtable_decl = build (PLUS_EXPR, TREE_TYPE (vtable_decl),
vtable_decl,
size_extra_vtbl_entries (TYPE_BINFO (real_type)));
TREE_CONSTANT (vtable_decl) = 1;
}
/* First field is the pseudo type_info base class. */
fields[0] = build_lang_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);

View File

@ -104,8 +104,6 @@ static void expand_upcast_fixups
static void fixup_virtual_upcast_offsets
PARAMS ((tree, tree, int, int, tree, tree, tree, tree,
tree *));
static tree marked_vtable_pathp PARAMS ((tree, void *));
static tree unmarked_vtable_pathp PARAMS ((tree, void *));
static tree marked_new_vtablep PARAMS ((tree, void *));
static tree unmarked_new_vtablep PARAMS ((tree, void *));
static tree marked_pushdecls_p PARAMS ((tree, void *));
@ -2346,30 +2344,6 @@ dfs_marked_real_bases_queue_p (binfo, data)
return binfo ? markedp (binfo, NULL) : NULL_TREE;
}
/* Like dfs_unmarked_real_bases_queue_p but walks only into things
that are not BINFO_VTABLE_PATH_MARKED. */
tree
dfs_vtable_path_unmarked_real_bases_queue_p (binfo, data)
tree binfo;
void *data;
{
binfo = get_shared_vbase_if_not_primary (binfo, data);
return binfo ? unmarked_vtable_pathp (binfo, NULL): NULL_TREE;
}
/* Like dfs_unmarked_real_bases_queue_p but walks only into things
that are BINFO_VTABLE_PATH_MARKED. */
tree
dfs_vtable_path_marked_real_bases_queue_p (binfo, data)
tree binfo;
void *data;
{
binfo = get_shared_vbase_if_not_primary (binfo, data);
return binfo ? marked_vtable_pathp (binfo, NULL): NULL_TREE;
}
/* A queue function that skips all virtual bases (and their
bases). */
@ -2400,9 +2374,7 @@ dfs_get_pure_virtuals (binfo, data)
{
tree virtuals;
for (virtuals = skip_rtti_stuff (binfo,
BINFO_TYPE (binfo),
NULL);
for (virtuals = BINFO_VIRTUALS (binfo);
virtuals;
virtuals = TREE_CHAIN (virtuals))
if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals)))
@ -2447,7 +2419,7 @@ get_pure_virtuals (type)
{
tree virtuals;
for (virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL);
for (virtuals = BINFO_VIRTUALS (vbases);
virtuals;
virtuals = TREE_CHAIN (virtuals))
{
@ -2527,7 +2499,7 @@ unmarkedp (binfo, data)
return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
static tree
tree
marked_vtable_pathp (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
@ -2535,7 +2507,7 @@ marked_vtable_pathp (binfo, data)
return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
}
static tree
tree
unmarked_vtable_pathp (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
@ -2863,9 +2835,10 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
*vbase_offsets = delta;
}
virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
while (virtuals)
for (virtuals = BINFO_VIRTUALS (binfo),
n = first_vfun_index (BINFO_TYPE (binfo));
virtuals;
virtuals = TREE_CHAIN (virtuals), ++n)
{
tree current_fndecl = TREE_VALUE (virtuals);
@ -2956,8 +2929,6 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
old_delta));
}
++n;
virtuals = TREE_CHAIN (virtuals);
}
}

View File

@ -1100,9 +1100,8 @@ __dynamic_cast (const void *src_ptr, // object started from
{
const void *vtable = *static_cast <const void *const *> (src_ptr);
const vtable_prefix *prefix =
adjust_pointer <vtable_prefix> (vtable, 0);
// FIXME: the above offset should be -offsetof (vtable_prefix, origin));
// but we don't currently layout vtables correctly.
adjust_pointer <vtable_prefix> (vtable,
-offsetof (vtable_prefix, origin));
const void *whole_ptr =
adjust_pointer <void> (src_ptr, prefix->whole_object);
const __class_type_info *whole_type = prefix->whole_type;

View File

@ -925,7 +925,8 @@ debug_binfo (elem)
else
fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\n");
virtuals = skip_rtti_stuff (elem, BINFO_TYPE (elem), &n);
virtuals = BINFO_VIRTUALS (elem);
n = first_vfun_index (BINFO_TYPE (elem));
while (virtuals)
{