cp-tree.h (num_extra_vtbl_entries): New function.

* cp-tree.h (num_extra_vtbl_entries): New function.
	(size_extra_vtbl_entries): Likewise.
	(dfs_vtable_path_unmark): Likewise.
	(dfs_vtable_path_unmarked_real_bases_queue_p): Likewise.
	(dfs_vtable_path_marked_real_bases_queue_p): Likewise.
	* class.c (num_extra_vtbl_entries): New function.
	(size_extra_vtbl_entries): Likewise.
	(dfs_build_vbase_offset_vtbl_entries): New function.
	(build_vbase_offset_vtbl_entries): Likewise.
	(build_vtbl_initializer): Use it.
	(finish_struct_1): Adjust vtable sizes (using
	num_extra_vtbl_entries).
	* expr.c (cplus_expand_expr): Assert that the DECL_RTL for a
	THUNK_DECL is non-NULL before expanding it.
	* init.c (expand_virtual_init): Adjust the vtable pointer by
	size_extra_vtbl_entries before storing it.
	* search.c (get_shared_vase_if_not_primary): Adjust prototype.
	Handle TREE_LIST parameters here, not in the dfs_* functions.
	(dfs_unmarked_real_bases_queue_p): Adjust.
	(dfs_marked_real_bases_queue_p): Likewise.
	(dfs_vtable_path_unmarked_real_bases_queue_p): New function.
	(dfs_vtable_path_marked_real_bases_queue_p): New function.
	(dfs_vtable_path_unmark): Likewise.

From-SVN: r31439
This commit is contained in:
Mark Mitchell 2000-01-16 16:59:44 +00:00 committed by Mark Mitchell
parent 2f4facc91e
commit 70ae320124
6 changed files with 246 additions and 26 deletions

View File

@ -1,3 +1,29 @@
2000-01-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (num_extra_vtbl_entries): New function.
(size_extra_vtbl_entries): Likewise.
(dfs_vtable_path_unmark): Likewise.
(dfs_vtable_path_unmarked_real_bases_queue_p): Likewise.
(dfs_vtable_path_marked_real_bases_queue_p): Likewise.
* class.c (num_extra_vtbl_entries): New function.
(size_extra_vtbl_entries): Likewise.
(dfs_build_vbase_offset_vtbl_entries): New function.
(build_vbase_offset_vtbl_entries): Likewise.
(build_vtbl_initializer): Use it.
(finish_struct_1): Adjust vtable sizes (using
num_extra_vtbl_entries).
* expr.c (cplus_expand_expr): Assert that the DECL_RTL for a
THUNK_DECL is non-NULL before expanding it.
* init.c (expand_virtual_init): Adjust the vtable pointer by
size_extra_vtbl_entries before storing it.
* search.c (get_shared_vase_if_not_primary): Adjust prototype.
Handle TREE_LIST parameters here, not in the dfs_* functions.
(dfs_unmarked_real_bases_queue_p): Adjust.
(dfs_marked_real_bases_queue_p): Likewise.
(dfs_vtable_path_unmarked_real_bases_queue_p): New function.
(dfs_vtable_path_marked_real_bases_queue_p): New function.
(dfs_vtable_path_unmark): Likewise.
2000-01-14 Mark Mitchell <mark@codesourcery.com>
* optimize.c (copy_body_r): Clear the operand three of a

View File

@ -144,6 +144,8 @@ static void remove_base_field PROTO((tree, tree, tree *));
static void remove_base_fields PROTO((tree));
static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *));
static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *));
static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *));
static tree build_vbase_offset_vtbl_entries PROTO((tree));
/* Variables shared between class.c and call.c. */
@ -2138,6 +2140,148 @@ duplicate_tag_error (t)
TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
}
/* Returns the number of extra entries (at negative indices) required
for BINFO's vtable. */
tree
num_extra_vtbl_entries (binfo)
tree binfo;
{
tree type;
int entries;
/* Under the old ABI, there are no entries at negative offsets. */
if (!flag_new_abi)
return size_zero_node;
type = BINFO_TYPE (binfo);
entries = 0;
/* There is an entry for the offset to each virtual base. */
entries += list_length (CLASSTYPE_VBASECLASSES (type));
return size_int (entries);
}
/* Returns the offset (in bytes) from the beginning of BINFO's vtable
where the vptr should actually point. */
tree
size_extra_vtbl_entries (binfo)
tree binfo;
{
tree offset;
offset = size_binop (EXACT_DIV_EXPR,
TYPE_SIZE (vtable_entry_type),
size_int (BITS_PER_UNIT));
offset = size_binop (MULT_EXPR, offset, num_extra_vtbl_entries (binfo));
return fold (offset);
}
/* Called from build_vbase_offset_vtbl_entries via dfs_walk. */
static tree
dfs_build_vbase_offset_vtbl_entries (binfo, data)
tree binfo;
void *data;
{
tree list = (tree) data;
if (TREE_TYPE (list) == binfo)
/* The TREE_TYPE of LIST is the base class from which we started
walking. If that BINFO is virtual it's not a virtual baseclass
of itself. */
;
else if (TREE_VIA_VIRTUAL (binfo))
{
tree init;
init = BINFO_OFFSET (binfo);
init = build1 (NOP_EXPR, vtable_entry_type, init);
TREE_VALUE (list) = tree_cons (NULL_TREE, init, TREE_VALUE (list));
}
SET_BINFO_VTABLE_PATH_MARKED (binfo);
return NULL_TREE;
}
/* Returns the initializers for the vbase offset entries in the
vtable, in reverse order. */
static tree
build_vbase_offset_vtbl_entries (binfo)
tree binfo;
{
tree type;
tree inits;
tree init;
type = BINFO_TYPE (binfo);
if (!TYPE_USES_VIRTUAL_BASECLASSES (type))
return NULL_TREE;
inits = NULL_TREE;
/* Under the new ABI, the vtable contains offsets to all virtual
bases. The ABI specifies different layouts depending on whether
or not *all* of the bases of this type are virtual. */
if (CLASSTYPE_N_BASECLASSES (type)
== list_length (CLASSTYPE_VBASECLASSES (type)))
{
/* In this case, the offsets are allocated from right to left of
the declaration order in which the virtual bases appear. */
int i;
for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
{
tree vbase = BINFO_BASETYPE (binfo, i);
init = BINFO_OFFSET (vbase);
init = build1 (NOP_EXPR, vtable_entry_type, init);
inits = tree_cons (NULL_TREE, init, inits);
}
}
else
{
tree list;
/* While in this case, the offsets are allocated in the reverse
order of a depth-first left-to-right traversal of the
hierarchy. We use BINFO_VTABLE_PATH_MARKED because we are
ourselves during a dfs_walk, and so BINFO_MARKED is already
in use. */
list = build_tree_list (type, NULL_TREE);
TREE_TYPE (list) = binfo;
dfs_walk (binfo,
dfs_build_vbase_offset_vtbl_entries,
dfs_vtable_path_unmarked_real_bases_queue_p,
list);
dfs_walk (binfo,
dfs_vtable_path_unmark,
dfs_vtable_path_marked_real_bases_queue_p,
list);
inits = nreverse (TREE_VALUE (list));
}
/* We've now got offsets in the right oder. However, the offsets
we've stored are offsets from the beginning of the complete
object, and we need offsets from this BINFO. */
for (init = inits; init; init = TREE_CHAIN (init))
{
tree exp = TREE_VALUE (init);
exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
exp = build1 (NOP_EXPR, vtable_entry_type, TREE_VALUE (init));
exp = fold (exp);
TREE_CONSTANT (exp) = 1;
TREE_VALUE (init) = exp;
}
return inits;
}
/* Construct the initializer for BINFOs virtual function table. */
static tree
@ -2146,13 +2290,16 @@ build_vtbl_initializer (binfo)
{
tree v = BINFO_VIRTUALS (binfo);
tree inits = NULL_TREE;
tree type = BINFO_TYPE (binfo);
if (flag_new_abi)
inits = build_vbase_offset_vtbl_entries (binfo);
/* 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 (BINFO_TYPE (binfo))
&& flag_vtable_thunks)
if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks)
{
tree offset;
tree init;
@ -4764,9 +4911,15 @@ finish_struct_1 (t)
if (has_virtual)
{
/* Use size_int so values are memoized in common cases. */
tree itype = build_index_type (size_int (has_virtual));
tree atype = build_cplus_array_type (vtable_entry_type, itype);
tree itype;
tree atype;
itype = size_int (has_virtual);
itype = size_binop (PLUS_EXPR,
itype,
num_extra_vtbl_entries (TYPE_BINFO (t)));
atype = build_cplus_array_type (vtable_entry_type,
build_index_type (itype));
layout_type (atype);
/* We may have to grow the vtable. */

View File

@ -3464,6 +3464,8 @@ extern void unreverse_member_declarations PROTO((tree));
extern void invalidate_class_lookup_cache PROTO((void));
extern void maybe_note_name_used_in_class PROTO((tree, tree));
extern void note_name_declared_in_class PROTO((tree, tree));
extern tree num_extra_vtbl_entries PROTO((tree));
extern tree size_extra_vtbl_entries PROTO((tree));
/* in cvt.c */
extern tree convert_to_reference PROTO((tree, tree, int, int, tree));
@ -3961,12 +3963,17 @@ extern tree dfs_walk PROTO((tree,
void *));
extern tree dfs_unmark PROTO((tree, void *));
extern tree dfs_vbase_unmark PROTO((tree, void *));
extern tree dfs_vtable_path_unmark PROTO((tree, void *));
extern tree markedp PROTO((tree, void *));
extern tree unmarkedp PROTO((tree, void *));
extern tree dfs_skip_nonprimary_vbases_unmarkedp PROTO((tree, void *));
extern tree dfs_skip_nonprimary_vbases_markedp PROTO((tree, void *));
extern tree dfs_unmarked_real_bases_queue_p PROTO((tree, void *));
extern tree dfs_marked_real_bases_queue_p PROTO((tree, void *));
extern tree dfs_vtable_path_unmarked_real_bases_queue_p
PROTO((tree, void *));
extern tree dfs_vtable_path_marked_real_bases_queue_p
PROTO((tree, void *));
extern tree dfs_skip_vbases PROTO((tree, void *));
extern void mark_primary_bases PROTO((tree));
extern tree convert_pointer_to_vbase PROTO((tree, tree));

View File

@ -1,6 +1,6 @@
/* Convert language-specific tree expression to rtl instructions,
for GNU compiler.
Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
Copyright (C) 1988, 92-97, 1998, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -131,6 +131,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
}
case THUNK_DECL:
my_friendly_assert (DECL_RTL (exp) != NULL_RTX, 20000115);
return DECL_RTL (exp);
case THROW_EXPR:

View File

@ -648,21 +648,26 @@ expand_virtual_init (binfo, decl)
tree vtbl, vtbl_ptr;
tree vtype, vtype_binfo;
/* This code is crusty. Should be simple, like:
vtbl = BINFO_VTABLE (binfo);
*/
/* Compute the location of the vtable. */
vtype = DECL_CONTEXT (TYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
assemble_external (vtbl);
TREE_USED (vtbl) = 1;
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
/* Under the new ABI, we need to point into the middle of the
vtable. */
if (flag_new_abi)
vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
size_extra_vtbl_entries (binfo));
/* Compute the location of the vtpr. */
decl = convert_pointer_to_real (vtype_binfo, decl);
vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
if (vtbl_ptr == error_mark_node)
return;
/* Have to convert VTBL since array sizes may be different. */
/* Assign the vtable to the vptr. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
}

View File

@ -150,7 +150,7 @@ static void setup_class_bindings PROTO ((tree, int));
static int template_self_reference_p PROTO ((tree, tree));
static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree));
static tree dfs_mark_primary_bases PROTO((tree, void *));
static tree get_shared_vbase_if_not_primary PROTO((tree, tree));
static tree get_shared_vbase_if_not_primary PROTO((tree, void *));
static tree dfs_find_vbase_instance PROTO((tree, void *));
/* Allocate a level of searching. */
@ -2240,12 +2240,17 @@ mark_primary_bases (type)
either a non-virtual base or a primary virtual base. */
static tree
get_shared_vbase_if_not_primary (binfo, type)
get_shared_vbase_if_not_primary (binfo, data)
tree binfo;
tree type;
void *data;
{
if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
{
tree type = (tree) data;
if (TREE_CODE (type) == TREE_LIST)
type = TREE_PURPOSE (type);
/* This is a non-primary virtual base. If there is no primary
version, get the shared version. */
binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
@ -2271,11 +2276,7 @@ dfs_unmarked_real_bases_queue_p (binfo, data)
tree binfo;
void *data;
{
tree type = (tree) data;
if (TREE_CODE (type) == TREE_LIST)
type = TREE_PURPOSE (type);
binfo = get_shared_vbase_if_not_primary (binfo, type);
binfo = get_shared_vbase_if_not_primary (binfo, data);
return binfo ? unmarkedp (binfo, NULL) : NULL_TREE;
}
@ -2287,14 +2288,34 @@ dfs_marked_real_bases_queue_p (binfo, data)
tree binfo;
void *data;
{
tree type = (tree) data;
if (TREE_CODE (type) == TREE_LIST)
type = TREE_PURPOSE (type);
binfo = get_shared_vbase_if_not_primary (binfo, type);
binfo = get_shared_vbase_if_not_primary (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). */
@ -2546,15 +2567,22 @@ dfs_vbase_unmark (binfo, data)
return dfs_unmark (binfo, data);
}
/* Clear BINFO_VTABLE_PATH_MARKED. */
tree
dfs_vtable_path_unmark (binfo, data)
tree binfo;
void *data ATTRIBUTE_UNUSED;
{
CLEAR_BINFO_VTABLE_PATH_MARKED (binfo);
return NULL_TREE;
}
#if 0
static void
dfs_mark_vtable_path (binfo) tree binfo;
{ SET_BINFO_VTABLE_PATH_MARKED (binfo); }
static void
dfs_unmark_vtable_path (binfo) tree binfo;
{ CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); }
static void
dfs_mark_new_vtable (binfo) tree binfo;
{ SET_BINFO_NEW_VTABLE_MARKED (binfo); }