Commit da3d4dfa by Mark Mitchell Committed by Mark Mitchell

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
parent 65a0aad5
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> Sun Mar 26 20:15:26 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* class.c (check_field_decl): Fix typo. * class.c (check_field_decl): Fix typo.
......
...@@ -80,7 +80,6 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree)); ...@@ -80,7 +80,6 @@ static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree)); static tree get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree)); static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls 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_primary_vtable PARAMS ((tree, tree));
static int build_secondary_vtable PARAMS ((tree, tree)); static int build_secondary_vtable PARAMS ((tree, tree));
static tree dfs_finish_vtbls PARAMS ((tree, void *)); static tree dfs_finish_vtbls PARAMS ((tree, void *));
...@@ -142,7 +141,6 @@ static tree dfs_vcall_offset_queue_p 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 dfs_build_vcall_offset_vtbl_entries PARAMS ((tree, void *));
static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree)); static tree build_vcall_offset_vtbl_entries PARAMS ((tree, tree));
static tree dfs_count_virtuals PARAMS ((tree, void *)); static tree dfs_count_virtuals PARAMS ((tree, void *));
static void start_vtable PARAMS ((tree, int *));
static void layout_vtable_decl PARAMS ((tree, int)); static void layout_vtable_decl PARAMS ((tree, int));
static int num_vfun_entries PARAMS ((tree)); static int num_vfun_entries PARAMS ((tree));
static tree dfs_find_final_overrider PARAMS ((tree, void *)); static tree dfs_find_final_overrider PARAMS ((tree, void *));
...@@ -162,6 +160,8 @@ static int layout_conflict_p PARAMS ((tree, varray_type)); ...@@ -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 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, varray_type));
static void accumulate_vtbl_inits PARAMS ((tree, tree)); 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. */ /* Variables shared between class.c and call.c. */
...@@ -279,7 +279,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data) ...@@ -279,7 +279,7 @@ dfs_build_vbase_offset_vtbl_entries (binfo, data)
base. */ base. */
vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list)); vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), TREE_PURPOSE (list));
if (!TREE_VALUE (list)) if (!TREE_VALUE (list))
BINFO_VPTR_FIELD (vbase) = build_int_2 (-1, 0); BINFO_VPTR_FIELD (vbase) = build_int_2 (-3, 0);
else else
{ {
BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list)); BINFO_VPTR_FIELD (vbase) = TREE_PURPOSE (TREE_VALUE (list));
...@@ -333,11 +333,11 @@ build_vbase_offset_vtbl_entries (binfo, t) ...@@ -333,11 +333,11 @@ build_vbase_offset_vtbl_entries (binfo, t)
TREE_TYPE (list) = binfo; TREE_TYPE (list) = binfo;
dfs_walk (binfo, dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries, dfs_build_vbase_offset_vtbl_entries,
dfs_vtable_path_unmarked_real_bases_queue_p, unmarked_vtable_pathp,
list); list);
dfs_walk (binfo, dfs_walk (binfo,
dfs_vtable_path_unmark, dfs_vtable_path_unmark,
dfs_vtable_path_marked_real_bases_queue_p, marked_vtable_pathp,
list); list);
inits = nreverse (TREE_VALUE (list)); inits = nreverse (TREE_VALUE (list));
...@@ -405,9 +405,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data) ...@@ -405,9 +405,7 @@ dfs_build_vcall_offset_vtbl_entries (binfo, data)
/* We chain the offsets on in reverse order. That's correct -- /* We chain the offsets on in reverse order. That's correct --
build_vtbl_initializer will straighten them out. */ build_vtbl_initializer will straighten them out. */
for (virtuals = skip_rtti_stuff (binfo, for (virtuals = BINFO_VIRTUALS (binfo);
BINFO_TYPE (binfo),
NULL);
virtuals; virtuals;
virtuals = TREE_CHAIN (virtuals)) virtuals = TREE_CHAIN (virtuals))
{ {
...@@ -486,6 +484,82 @@ build_vcall_offset_vtbl_entries (binfo, t) ...@@ -486,6 +484,82 @@ build_vcall_offset_vtbl_entries (binfo, t)
return vod.inits; 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 /* Returns a pointer to the virtual base class of EXP that has the
indicated TYPE. EXP is of class type, not a pointer type. */ indicated TYPE. EXP is of class type, not a pointer type. */
...@@ -945,47 +1019,6 @@ get_derived_offset (binfo, type) ...@@ -945,47 +1019,6 @@ get_derived_offset (binfo, type)
return size_binop (MINUS_EXPR, offset1, offset2); 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 /* Create a VAR_DECL for a primary or secondary vtable for
CLASS_TYPE. Use NAME for the name of the vtable, and VTABLE_TYPE CLASS_TYPE. Use NAME for the name of the vtable, and VTABLE_TYPE
for its type. */ for its type. */
...@@ -1067,8 +1100,6 @@ build_primary_vtable (binfo, type) ...@@ -1067,8 +1100,6 @@ build_primary_vtable (binfo, type)
if (binfo) if (binfo)
{ {
tree offset;
if (BINFO_NEW_VTABLE_MARKED (binfo, type)) if (BINFO_NEW_VTABLE_MARKED (binfo, type))
/* We have already created a vtable for this base, so there's /* We have already created a vtable for this base, so there's
no need to do it again. */ no need to do it again. */
...@@ -1079,11 +1110,6 @@ build_primary_vtable (binfo, type) ...@@ -1079,11 +1110,6 @@ build_primary_vtable (binfo, type)
DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo))); DECL_SIZE (decl) = TYPE_SIZE (TREE_TYPE (BINFO_VTABLE (binfo)));
DECL_SIZE_UNIT (decl) DECL_SIZE_UNIT (decl)
= TYPE_SIZE_UNIT (TREE_TYPE (BINFO_VTABLE (binfo))); = 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 else
{ {
...@@ -1171,10 +1197,6 @@ build_secondary_vtable (binfo, for_type) ...@@ -1171,10 +1197,6 @@ build_secondary_vtable (binfo, for_type)
else else
offset = BINFO_OFFSET (binfo); 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 /* In the new ABI, secondary vtables are laid out as part of the
same structure as the primary vtable. */ same structure as the primary vtable. */
if (merge_primary_and_secondary_vtables_p ()) if (merge_primary_and_secondary_vtables_p ())
...@@ -1349,42 +1371,52 @@ modify_vtable_entry (t, binfo, fndecl, delta, virtuals) ...@@ -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 /* Return the index (in the virtual function table) of the first
to be needed. It's safe to call it more than once. *HAS_VIRTUAL_P virtual function. */
is initialized to the number of slots that are reserved at the
beginning of the vtable for RTTI information. */ 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 static void
start_vtable (t, has_virtual_p) set_vindex (t, decl, vfuns_p)
tree t; tree t;
int *has_virtual_p; tree decl;
int *vfuns_p;
{ {
if (*has_virtual_p == 0 && ! CLASSTYPE_COM_INTERFACE (t)) int vindex;
{
/* If we are using thunks, use two slots at the front, one vindex = (*vfuns_p)++;
for the offset pointer, one for the tdesc pointer. vindex += first_vfun_index (t);
For ARM-style vtables, use the same slot for both. */ DECL_VINDEX (decl) = build_shared_int_cst (vindex);
if (flag_vtable_thunks)
*has_virtual_p = 2;
else
*has_virtual_p = 1;
}
} }
/* Add a virtual function to all the appropriate vtables for the class /* 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 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 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. 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 VFUNS_P keeps track of how many virtuals there are in our
vtable for the type, and we build upon the NEW_VIRTUALS list main vtable for the type, and we build upon the NEW_VIRTUALS list
and return it. */ and return it. */
static void static void
add_virtual_function (new_virtuals_p, overridden_virtuals_p, add_virtual_function (new_virtuals_p, overridden_virtuals_p,
has_virtual, fndecl, t) vfuns_p, fndecl, t)
tree *new_virtuals_p; tree *new_virtuals_p;
tree *overridden_virtuals_p; tree *overridden_virtuals_p;
int *has_virtual; int *vfuns_p;
tree fndecl; tree fndecl;
tree t; /* Structure type. */ tree t; /* Structure type. */
{ {
...@@ -1409,10 +1441,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p, ...@@ -1409,10 +1441,8 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
/* We remember that this was the base sub-object for rtti. */ /* We remember that this was the base sub-object for rtti. */
CLASSTYPE_RTTI (t) = t; CLASSTYPE_RTTI (t) = t;
start_vtable (t, has_virtual);
/* Now assign virtual dispatch information. */ /* 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; DECL_VIRTUAL_CONTEXT (fndecl) = t;
/* Save the state we've computed on the NEW_VIRTUALS list. */ /* 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, ...@@ -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. */ /* Make the Ith baseclass of T its primary base. */
static void static void
set_primary_base (t, i, has_virtual_p) set_primary_base (t, i, vfuns_p)
tree t; tree t;
int i; int i;
int *has_virtual_p; int *vfuns_p;
{ {
tree basetype; tree basetype;
...@@ -1982,15 +2012,15 @@ set_primary_base (t, i, has_virtual_p) ...@@ -1982,15 +2012,15 @@ set_primary_base (t, i, has_virtual_p)
TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype); TYPE_BINFO_VIRTUALS (t) = TYPE_BINFO_VIRTUALS (basetype);
TYPE_VFIELD (t) = TYPE_VFIELD (basetype); TYPE_VFIELD (t) = TYPE_VFIELD (basetype);
CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype); CLASSTYPE_RTTI (t) = CLASSTYPE_RTTI (basetype);
*has_virtual_p = CLASSTYPE_VSIZE (basetype); *vfuns_p = CLASSTYPE_VSIZE (basetype);
} }
/* Determine the primary class for T. */ /* Determine the primary class for T. */
static void static void
determine_primary_base (t, has_virtual_p) determine_primary_base (t, vfuns_p)
tree t; tree t;
int *has_virtual_p; int *vfuns_p;
{ {
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t); int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
...@@ -1998,7 +2028,7 @@ determine_primary_base (t, has_virtual_p) ...@@ -1998,7 +2028,7 @@ determine_primary_base (t, has_virtual_p)
if (n_baseclasses == 0) if (n_baseclasses == 0)
return; return;
*has_virtual_p = 0; *vfuns_p = 0;
for (i = 0; i < n_baseclasses; i++) for (i = 0; i < n_baseclasses; i++)
{ {
...@@ -2021,7 +2051,7 @@ determine_primary_base (t, has_virtual_p) ...@@ -2021,7 +2051,7 @@ determine_primary_base (t, has_virtual_p)
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) 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)); CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
} }
else else
...@@ -2039,8 +2069,8 @@ determine_primary_base (t, has_virtual_p) ...@@ -2039,8 +2069,8 @@ determine_primary_base (t, has_virtual_p)
VF_BASETYPE_VALUE (vfields), VF_BASETYPE_VALUE (vfields),
CLASSTYPE_VFIELDS (t)); CLASSTYPE_VFIELDS (t));
if (*has_virtual_p == 0) if (*vfuns_p == 0)
set_primary_base (t, i, has_virtual_p); set_primary_base (t, i, vfuns_p);
} }
} }
} }
...@@ -2060,7 +2090,7 @@ determine_primary_base (t, has_virtual_p) ...@@ -2060,7 +2090,7 @@ determine_primary_base (t, has_virtual_p)
if (TREE_VIA_VIRTUAL (base_binfo) if (TREE_VIA_VIRTUAL (base_binfo)
&& CLASSTYPE_NEARLY_EMPTY_P (basetype)) && 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)); CLASSTYPE_VFIELDS (t) = copy_list (CLASSTYPE_VFIELDS (basetype));
break; break;
} }
...@@ -2557,9 +2587,7 @@ static int ...@@ -2557,9 +2587,7 @@ static int
num_vfun_entries (binfo) num_vfun_entries (binfo)
tree binfo; tree binfo;
{ {
return list_length (skip_rtti_stuff (binfo, return list_length (BINFO_VIRTUALS (binfo));
BINFO_TYPE (binfo),
NULL));
} }
/* Called from num_extra_vtbl_entries via dfs_walk. */ /* Called from num_extra_vtbl_entries via dfs_walk. */
...@@ -2609,7 +2637,19 @@ num_extra_vtbl_entries (binfo) ...@@ -2609,7 +2637,19 @@ num_extra_vtbl_entries (binfo)
entries += vod.offsets; 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 /* Returns the offset (in bytes) from the beginning of BINFO's vtable
...@@ -2636,7 +2676,6 @@ build_vtbl_initializer (binfo, t) ...@@ -2636,7 +2676,6 @@ build_vtbl_initializer (binfo, t)
{ {
tree v = BINFO_VIRTUALS (binfo); tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE; tree inits = NULL_TREE;
tree type = BINFO_TYPE (binfo);
/* Add entries to the vtable that indicate how to adjust the this /* Add entries to the vtable that indicate how to adjust the this
pointer when calling a virtual function in this class. */ pointer when calling a virtual function in this class. */
...@@ -2646,48 +2685,8 @@ build_vtbl_initializer (binfo, t) ...@@ -2646,48 +2685,8 @@ build_vtbl_initializer (binfo, t)
inits = chainon (build_vbase_offset_vtbl_entries (binfo, t), inits = chainon (build_vbase_offset_vtbl_entries (binfo, t),
inits); inits);
/* Process the RTTI stuff at the head of the list. If we're not /* Add entries to the vtable for RTTI. */
using vtable thunks, then the RTTI entry is just an ordinary inits = chainon (build_rtti_vtbl_entries (binfo, t), inits);
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. */
}
/* Go through all the ordinary virtual functions, building up /* Go through all the ordinary virtual functions, building up
initializers. */ initializers. */
...@@ -3048,43 +3047,6 @@ find_final_overrider (t, binfo, fn) ...@@ -3048,43 +3047,6 @@ find_final_overrider (t, binfo, fn)
return build_tree_list (ffod.overriding_fn, ffod.overriding_base); 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 /* Called via dfs_walk. Returns BINFO if BINFO has the same type as
DATA (which is really an _TYPE node). */ DATA (which is really an _TYPE node). */
...@@ -3125,10 +3087,8 @@ dfs_modify_vtables (binfo, data) ...@@ -3125,10 +3087,8 @@ dfs_modify_vtables (binfo, data)
/* Now, go through each of the virtual functions in the virtual /* Now, go through each of the virtual functions in the virtual
function table for BINFO. Find the final overrider, and function table for BINFO. Find the final overrider, and
update the BINFO_VIRTUALS list appropriately. */ update the BINFO_VIRTUALS list appropriately. */
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), NULL), for (virtuals = BINFO_VIRTUALS (binfo),
old_virtuals = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (binfo)), old_virtuals = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (binfo)));
BINFO_TYPE (binfo),
NULL);
virtuals; virtuals;
virtuals = TREE_CHAIN (virtuals), virtuals = TREE_CHAIN (virtuals),
old_virtuals = TREE_CHAIN (old_virtuals)) old_virtuals = TREE_CHAIN (old_virtuals))
...@@ -3138,17 +3098,16 @@ dfs_modify_vtables (binfo, data) ...@@ -3138,17 +3098,16 @@ dfs_modify_vtables (binfo, data)
tree overrider; tree overrider;
tree vindex; tree vindex;
tree delta; 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 /* Find the function which originally caused this vtable
entry to be present. */ entry to be present. */
fn = BV_FN (old_virtuals); fn = BV_FN (old_virtuals);
vindex = DECL_VINDEX (fn); vindex = DECL_VINDEX (fn);
b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn)); b = dfs_walk (binfo, dfs_find_base, NULL, DECL_VIRTUAL_CONTEXT (fn));
fn = skip_rtti_stuff (TYPE_BINFO (BINFO_TYPE (b)), fn = BINFO_VIRTUALS (TYPE_BINFO (BINFO_TYPE (b)));
BINFO_TYPE (b), i = first_vfun_index (BINFO_TYPE (b));
&i);
vindex_val = tree_low_cst (vindex, 0); vindex_val = tree_low_cst (vindex, 0);
while (i < vindex_val) while (i < vindex_val)
{ {
...@@ -3195,9 +3154,9 @@ dfs_modify_vtables (binfo, data) ...@@ -3195,9 +3154,9 @@ dfs_modify_vtables (binfo, data)
which should therefore be appended to the end of the vtable for T. */ which should therefore be appended to the end of the vtable for T. */
static tree static tree
modify_all_vtables (t, has_virtual_p, overridden_virtuals) modify_all_vtables (t, vfuns_p, overridden_virtuals)
tree t; tree t;
int *has_virtual_p; int *vfuns_p;
tree overridden_virtuals; tree overridden_virtuals;
{ {
tree binfo; tree binfo;
...@@ -3224,11 +3183,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals) ...@@ -3224,11 +3183,8 @@ modify_all_vtables (t, has_virtual_p, overridden_virtuals)
if (BINFO_VIRTUALS (binfo) if (BINFO_VIRTUALS (binfo)
&& !value_member (fn, 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. */ /* Set the vtable index. */
DECL_VINDEX (fn) set_vindex (t, fn, vfuns_p);
= build_shared_int_cst ((*has_virtual_p)++);
/* We don't need to convert to a base class when calling /* We don't need to convert to a base class when calling
this function. */ this function. */
DECL_VIRTUAL_CONTEXT (fn) = t; DECL_VIRTUAL_CONTEXT (fn) = t;
...@@ -4220,9 +4176,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, v) ...@@ -4220,9 +4176,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
/* Now that we know where it wil be placed, update its /* Now that we know where it wil be placed, update its
BINFO_OFFSET. */ BINFO_OFFSET. */
offset = convert (ssizetype, byte_position (decl)); offset = byte_position (decl);
if (binfo) 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 /* 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.
...@@ -4243,7 +4200,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v) ...@@ -4243,7 +4200,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, v)
{ {
/* Undo the propogate_binfo_offsets call. */ /* Undo the propogate_binfo_offsets call. */
offset = size_diffop (size_zero_node, offset); 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 /* 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
...@@ -4601,11 +4558,11 @@ check_bases_and_members (t, empty_p) ...@@ -4601,11 +4558,11 @@ check_bases_and_members (t, empty_p)
responsibility to do that. */ responsibility to do that. */
static tree 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) new_virtuals_p, overridden_virtuals_p)
tree t; tree t;
int *empty_p; int *empty_p;
int *has_virtual_p; int *vfuns_p;
tree *new_virtuals_p; tree *new_virtuals_p;
tree *overridden_virtuals_p; tree *overridden_virtuals_p;
{ {
...@@ -4616,17 +4573,15 @@ create_vtable_ptr (t, empty_p, has_virtual_p, ...@@ -4616,17 +4573,15 @@ create_vtable_ptr (t, empty_p, has_virtual_p,
for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn)) for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
if (DECL_VINDEX (fn)) if (DECL_VINDEX (fn))
add_virtual_function (new_virtuals_p, overridden_virtuals_p, 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 new virtual function table if we're supposed to include vptrs in
all classes that need them. */ all classes that need them. */
if (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ()) if (!TYPE_VFIELD (t)
start_vtable (t, has_virtual_p); && (*vfuns_p
|| (TYPE_CONTAINS_VPTR_P (t) && vptrs_present_everywhere_p ())))
/* If we couldn't find an appropriate base class, create a new field
here. */
if (*has_virtual_p && !TYPE_VFIELD (t))
{ {
/* We build this decl with vtbl_ptr_type_node, which is a /* We build this decl with vtbl_ptr_type_node, which is a
`vtable_entry_type*'. It might seem more precise to use `vtable_entry_type*'. It might seem more precise to use
...@@ -4972,11 +4927,11 @@ end_of_class (t, include_virtuals_p) ...@@ -4972,11 +4927,11 @@ end_of_class (t, include_virtuals_p)
pointer. */ pointer. */
static void 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) new_virtuals_p, overridden_virtuals_p)
tree t; tree t;
int *empty_p; int *empty_p;
int *has_virtual_p; int *vfuns_p;
tree *new_virtuals_p; tree *new_virtuals_p;
tree *overridden_virtuals_p; tree *overridden_virtuals_p;
{ {
...@@ -4995,10 +4950,10 @@ layout_class_type (t, empty_p, has_virtual_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 /* If possible, we reuse the virtual function table pointer from one
of our base classes. */ 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. */ /* 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); new_virtuals_p, overridden_virtuals_p);
/* Under the new ABI, the vptr is always the first thing in the /* Under the new ABI, the vptr is always the first thing in the
...@@ -5215,7 +5170,7 @@ finish_struct_1 (t) ...@@ -5215,7 +5170,7 @@ finish_struct_1 (t)
tree t; tree t;
{ {
tree x; tree x;
int has_virtual; int vfuns;
/* The NEW_VIRTUALS is a TREE_LIST. The TREE_VALUE of each node is /* 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 a FUNCTION_DECL. Each of these functions is a virtual function
declared in T that does not override any virtual function from a declared in T that does not override any virtual function from a
...@@ -5246,7 +5201,7 @@ finish_struct_1 (t) ...@@ -5246,7 +5201,7 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_GOT_SEMICOLON (t) = 0;
CLASSTYPE_VFIELD_PARENT (t) = -1; CLASSTYPE_VFIELD_PARENT (t) = -1;
has_virtual = 0; vfuns = 0;
CLASSTYPE_RTTI (t) = NULL_TREE; CLASSTYPE_RTTI (t) = NULL_TREE;
/* Do end-of-class semantic processing: checking the validity of the /* Do end-of-class semantic processing: checking the validity of the
...@@ -5254,7 +5209,7 @@ finish_struct_1 (t) ...@@ -5254,7 +5209,7 @@ finish_struct_1 (t)
check_bases_and_members (t, &empty); check_bases_and_members (t, &empty);
/* Layout the class itself. */ /* Layout the class itself. */
layout_class_type (t, &empty, &has_virtual, layout_class_type (t, &empty, &vfuns,
&new_virtuals, &overridden_virtuals); &new_virtuals, &overridden_virtuals);
/* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we /* Set up the DECL_FIELD_BITPOS of the vfield if we need to, as we
...@@ -5278,7 +5233,7 @@ finish_struct_1 (t) ...@@ -5278,7 +5233,7 @@ finish_struct_1 (t)
} }
overridden_virtuals 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 necessary, create the primary vtable for this class. */
if (new_virtuals if (new_virtuals
...@@ -5288,22 +5243,7 @@ finish_struct_1 (t) ...@@ -5288,22 +5243,7 @@ finish_struct_1 (t)
new_virtuals = nreverse (new_virtuals); new_virtuals = nreverse (new_virtuals);
/* We must enter these virtuals into the table. */ /* We must enter these virtuals into the table. */
if (!CLASSTYPE_HAS_PRIMARY_BASE_P (t)) 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)) else if (! BINFO_NEW_VTABLE_MARKED (TYPE_BINFO (t), t))
/* Here we know enough to change the type of our virtual /* Here we know enough to change the type of our virtual
function table, but we will wait until later this function. */ function table, but we will wait until later this function. */
...@@ -5346,7 +5286,7 @@ finish_struct_1 (t) ...@@ -5346,7 +5286,7 @@ finish_struct_1 (t)
my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE, my_friendly_assert (TYPE_BINFO_VIRTUALS (t) == NULL_TREE,
20000116); 20000116);
CLASSTYPE_VSIZE (t) = has_virtual; CLASSTYPE_VSIZE (t) = vfuns;
/* Entries for virtual functions defined in the primary base are /* Entries for virtual functions defined in the primary base are
followed by entries for new functions unique to this class. */ followed by entries for new functions unique to this class. */
TYPE_BINFO_VIRTUALS (t) TYPE_BINFO_VIRTUALS (t)
......
...@@ -1545,8 +1545,8 @@ struct lang_type ...@@ -1545,8 +1545,8 @@ struct lang_type
CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \ CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (NODE))) \
: NULL_TREE) : NULL_TREE)
/* The number of virtual functions defined for this /* The number of virtual functions present in this classes virtual
_CLASSTYPE node. */ function table. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* A chain of BINFOs for the direct and indirect virtual base classes /* A chain of BINFOs for the direct and indirect virtual base classes
...@@ -3685,8 +3685,7 @@ extern void push_lang_context PARAMS ((tree)); ...@@ -3685,8 +3685,7 @@ extern void push_lang_context PARAMS ((tree));
extern void pop_lang_context PARAMS ((void)); extern void pop_lang_context PARAMS ((void));
extern tree instantiate_type PARAMS ((tree, tree, int)); extern tree instantiate_type PARAMS ((tree, tree, int));
extern void print_class_statistics PARAMS ((void)); extern void print_class_statistics PARAMS ((void));
extern tree skip_rtti_stuff PARAMS ((tree, tree, extern int first_vfun_index PARAMS ((tree));
HOST_WIDE_INT *));
extern void build_self_reference PARAMS ((void)); extern void build_self_reference PARAMS ((void));
extern void warn_hidden PARAMS ((tree)); extern void warn_hidden PARAMS ((tree));
extern tree get_enclosing_class PARAMS ((tree)); extern tree get_enclosing_class PARAMS ((tree));
...@@ -4212,11 +4211,9 @@ extern tree dfs_skip_nonprimary_vbases_unmarkedp PARAMS ((tree, void *)); ...@@ -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_skip_nonprimary_vbases_markedp PARAMS ((tree, void *));
extern tree dfs_unmarked_real_bases_queue_p 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_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 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 void mark_primary_bases PARAMS ((tree));
extern tree convert_pointer_to_vbase PARAMS ((tree, tree)); extern tree convert_pointer_to_vbase PARAMS ((tree, tree));
extern tree find_vbase_instance PARAMS ((tree, tree)); extern tree find_vbase_instance PARAMS ((tree, tree));
......
...@@ -1857,7 +1857,7 @@ dump_expr (t, flags) ...@@ -1857,7 +1857,7 @@ dump_expr (t, flags)
t = TYPE_METHOD_BASETYPE (t); t = TYPE_METHOD_BASETYPE (t);
virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (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 /* Map vtable index back one, to allow for the null pointer to
member. */ member. */
......
...@@ -132,6 +132,7 @@ build_headof (exp) ...@@ -132,6 +132,7 @@ build_headof (exp)
tree type = TREE_TYPE (exp); tree type = TREE_TYPE (exp);
tree aref; tree aref;
tree offset; tree offset;
tree index;
my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112); my_friendly_assert (TREE_CODE (type) == POINTER_TYPE, 20000112);
type = TREE_TYPE (type); type = TREE_TYPE (type);
...@@ -151,7 +152,15 @@ build_headof (exp) ...@@ -151,7 +152,15 @@ build_headof (exp)
/* We use this a couple of times below, protect it. */ /* We use this a couple of times below, protect it. */
exp = save_expr (exp); 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) if (flag_vtable_thunks)
offset = aref; offset = aref;
...@@ -230,6 +239,7 @@ get_tinfo_decl_dynamic (exp) ...@@ -230,6 +239,7 @@ get_tinfo_decl_dynamic (exp)
{ {
/* build reference to type_info from vtable. */ /* build reference to type_info from vtable. */
tree t; tree t;
tree index;
if (! flag_rtti) if (! flag_rtti)
error ("taking dynamic typeid of object with -fno-rtti"); error ("taking dynamic typeid of object with -fno-rtti");
...@@ -247,10 +257,15 @@ get_tinfo_decl_dynamic (exp) ...@@ -247,10 +257,15 @@ get_tinfo_decl_dynamic (exp)
exp = build_indirect_ref (exp, NULL_PTR); exp = build_indirect_ref (exp, NULL_PTR);
} }
if (flag_vtable_thunks) /* The RTTI information is always in the vtable, but it's at
t = build_vfn_ref ((tree *) 0, exp, integer_one_node); 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 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); TREE_TYPE (t) = build_pointer_type (tinfo_decl_type);
return t; return t;
} }
...@@ -1284,8 +1299,7 @@ tinfo_base_init (desc, target) ...@@ -1284,8 +1299,7 @@ tinfo_base_init (desc, target)
if (TINFO_VTABLE_DECL (desc)) 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); init = tree_cons (NULL_TREE, vtbl_ptr, init);
} }
...@@ -1616,6 +1630,17 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...)) ...@@ -1616,6 +1630,17 @@ create_pseudo_type_info VPARAMS((const char *real_name, int ident, ...))
/* Get the vtable decl. */ /* Get the vtable decl. */
real_type = xref_tag (class_type_node, get_identifier (real_name), 1); real_type = xref_tag (class_type_node, get_identifier (real_name), 1);
vtable_decl = get_vtable_decl (real_type, /*complete=*/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. */ /* First field is the pseudo type_info base class. */
fields[0] = build_lang_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node); fields[0] = build_lang_decl (FIELD_DECL, NULL_TREE, ti_desc_type_node);
......
...@@ -104,8 +104,6 @@ static void expand_upcast_fixups ...@@ -104,8 +104,6 @@ static void expand_upcast_fixups
static void fixup_virtual_upcast_offsets static void fixup_virtual_upcast_offsets
PARAMS ((tree, tree, int, int, tree, tree, tree, tree, PARAMS ((tree, tree, int, int, tree, 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 marked_new_vtablep PARAMS ((tree, void *));
static tree unmarked_new_vtablep PARAMS ((tree, void *)); static tree unmarked_new_vtablep PARAMS ((tree, void *));
static tree marked_pushdecls_p PARAMS ((tree, void *)); static tree marked_pushdecls_p PARAMS ((tree, void *));
...@@ -2346,30 +2344,6 @@ dfs_marked_real_bases_queue_p (binfo, data) ...@@ -2346,30 +2344,6 @@ dfs_marked_real_bases_queue_p (binfo, data)
return binfo ? markedp (binfo, NULL) : NULL_TREE; 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 /* A queue function that skips all virtual bases (and their
bases). */ bases). */
...@@ -2400,9 +2374,7 @@ dfs_get_pure_virtuals (binfo, data) ...@@ -2400,9 +2374,7 @@ dfs_get_pure_virtuals (binfo, data)
{ {
tree virtuals; tree virtuals;
for (virtuals = skip_rtti_stuff (binfo, for (virtuals = BINFO_VIRTUALS (binfo);
BINFO_TYPE (binfo),
NULL);
virtuals; virtuals;
virtuals = TREE_CHAIN (virtuals)) virtuals = TREE_CHAIN (virtuals))
if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals))) if (DECL_PURE_VIRTUAL_P (TREE_VALUE (virtuals)))
...@@ -2447,7 +2419,7 @@ get_pure_virtuals (type) ...@@ -2447,7 +2419,7 @@ get_pure_virtuals (type)
{ {
tree virtuals; tree virtuals;
for (virtuals = skip_rtti_stuff (vbases, BINFO_TYPE (vbases), NULL); for (virtuals = BINFO_VIRTUALS (vbases);
virtuals; virtuals;
virtuals = TREE_CHAIN (virtuals)) virtuals = TREE_CHAIN (virtuals))
{ {
...@@ -2527,7 +2499,7 @@ unmarkedp (binfo, data) ...@@ -2527,7 +2499,7 @@ unmarkedp (binfo, data)
return !BINFO_MARKED (binfo) ? binfo : NULL_TREE; return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
} }
static tree tree
marked_vtable_pathp (binfo, data) marked_vtable_pathp (binfo, data)
tree binfo; tree binfo;
void *data ATTRIBUTE_UNUSED; void *data ATTRIBUTE_UNUSED;
...@@ -2535,7 +2507,7 @@ marked_vtable_pathp (binfo, data) ...@@ -2535,7 +2507,7 @@ marked_vtable_pathp (binfo, data)
return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE; return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
} }
static tree tree
unmarked_vtable_pathp (binfo, data) unmarked_vtable_pathp (binfo, data)
tree binfo; tree binfo;
void *data ATTRIBUTE_UNUSED; void *data ATTRIBUTE_UNUSED;
...@@ -2863,9 +2835,10 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, ...@@ -2863,9 +2835,10 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
*vbase_offsets = delta; *vbase_offsets = delta;
} }
virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n); for (virtuals = BINFO_VIRTUALS (binfo),
n = first_vfun_index (BINFO_TYPE (binfo));
while (virtuals) virtuals;
virtuals = TREE_CHAIN (virtuals), ++n)
{ {
tree current_fndecl = TREE_VALUE (virtuals); tree current_fndecl = TREE_VALUE (virtuals);
...@@ -2956,8 +2929,6 @@ expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t, ...@@ -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, finish_expr_stmt (build_modify_expr (new_delta, NOP_EXPR,
old_delta)); old_delta));
} }
++n;
virtuals = TREE_CHAIN (virtuals);
} }
} }
......
...@@ -1100,9 +1100,8 @@ __dynamic_cast (const void *src_ptr, // object started from ...@@ -1100,9 +1100,8 @@ __dynamic_cast (const void *src_ptr, // object started from
{ {
const void *vtable = *static_cast <const void *const *> (src_ptr); const void *vtable = *static_cast <const void *const *> (src_ptr);
const vtable_prefix *prefix = const vtable_prefix *prefix =
adjust_pointer <vtable_prefix> (vtable, 0); adjust_pointer <vtable_prefix> (vtable,
// FIXME: the above offset should be -offsetof (vtable_prefix, origin)); -offsetof (vtable_prefix, origin));
// but we don't currently layout vtables correctly.
const void *whole_ptr = const void *whole_ptr =
adjust_pointer <void> (src_ptr, prefix->whole_object); adjust_pointer <void> (src_ptr, prefix->whole_object);
const __class_type_info *whole_type = prefix->whole_type; const __class_type_info *whole_type = prefix->whole_type;
......
...@@ -925,7 +925,8 @@ debug_binfo (elem) ...@@ -925,7 +925,8 @@ debug_binfo (elem)
else else
fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "no vtable decl yet\n");
fprintf (stderr, "virtuals:\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) while (virtuals)
{ {
......
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