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:
parent
2f4facc91e
commit
70ae320124
@ -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
|
||||
|
161
gcc/cp/class.c
161
gcc/cp/class.c
@ -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. */
|
||||
|
@ -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));
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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); }
|
||||
|
Loading…
Reference in New Issue
Block a user