mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-19 09:49:41 +08:00
cp-tree.h (merge_primary_and_secondary_vtables_p): New macro.
* cp-tree.h (merge_primary_and_secondary_vtables_p): New macro. * class.c (build_secondary_vtable): Reorganize. Don't create a new vtable under the new ABI. (layout_vtable_decl): Don't add num_extra_vtbl_entries when computing the size. (build_vtbl_initializer): Don't return a CONSTRUCTOR; just return the initializing elements. (initialize_vtable): New function. (dfs_finish_vtbls): Use it. (dfs_accumulate_vtbl_inits): New function. (finish_vtbls): Merge primary and secondary vtables under the new ABI. (finish_struct_1): Remove redundant call to layout_vtable_decl. * init.c (expand_virtual_init): Deal with BINFO_VTABLEs that aren't VAR_DECLs. From-SVN: r32083
This commit is contained in:
parent
b9f3920101
commit
8d7a5379cd
@ -1,5 +1,21 @@
|
||||
2000-02-20 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.h (merge_primary_and_secondary_vtables_p): New macro.
|
||||
* class.c (build_secondary_vtable): Reorganize. Don't create a
|
||||
new vtable under the new ABI.
|
||||
(layout_vtable_decl): Don't add num_extra_vtbl_entries when
|
||||
computing the size.
|
||||
(build_vtbl_initializer): Don't return a CONSTRUCTOR; just return
|
||||
the initializing elements.
|
||||
(initialize_vtable): New function.
|
||||
(dfs_finish_vtbls): Use it.
|
||||
(dfs_accumulate_vtbl_inits): New function.
|
||||
(finish_vtbls): Merge primary and secondary vtables under the new
|
||||
ABI.
|
||||
(finish_struct_1): Remove redundant call to layout_vtable_decl.
|
||||
* init.c (expand_virtual_init): Deal with BINFO_VTABLEs that
|
||||
aren't VAR_DECLs.
|
||||
|
||||
* class.c (build_vtable): New function, split out from ...
|
||||
(get_vtable_decl): ... here, and ...
|
||||
(build_secondary_vtable): ... here.
|
||||
|
198
gcc/cp/class.c
198
gcc/cp/class.c
@ -84,6 +84,7 @@ 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 *));
|
||||
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, void *));
|
||||
static void finish_vtbls PARAMS ((tree));
|
||||
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
|
||||
static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
|
||||
@ -153,6 +154,7 @@ static tree dfs_find_base PARAMS ((tree, void *));
|
||||
static int make_new_vtable PARAMS ((tree, tree));
|
||||
extern void dump_class_hierarchy PARAMS ((tree, int));
|
||||
static tree build_vtable PARAMS ((tree, tree, tree));
|
||||
static void initialize_vtable PARAMS ((tree, tree));
|
||||
|
||||
/* Variables shared between class.c and call.c. */
|
||||
|
||||
@ -1140,13 +1142,52 @@ build_secondary_vtable (binfo, for_type)
|
||||
joiner = JOINER;
|
||||
#endif
|
||||
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
my_friendly_assert (binfo == BINFO_FOR_VBASE (BINFO_TYPE (binfo),
|
||||
current_class_type),
|
||||
170);
|
||||
|
||||
if (BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
/* We already created a vtable for this base. There's no need to
|
||||
do it again. */
|
||||
return 0;
|
||||
|
||||
basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));
|
||||
/* Remember that we've created a vtable for this BINFO, so that we
|
||||
don't try to do so again. */
|
||||
SET_BINFO_NEW_VTABLE_MARKED (binfo);
|
||||
|
||||
/* Make fresh virtual list, so we can smash it later. */
|
||||
BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
|
||||
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
{
|
||||
tree binfo1 = BINFO_FOR_VBASE (BINFO_TYPE (binfo), for_type);
|
||||
|
||||
/* XXX - This should never happen, if it does, the caller should
|
||||
ensure that the binfo is from for_type's binfos, not from any
|
||||
base type's. We can remove all this code after a while. */
|
||||
if (binfo1 != binfo)
|
||||
warning ("internal inconsistency: binfo offset error for rtti");
|
||||
|
||||
offset = BINFO_OFFSET (binfo1);
|
||||
}
|
||||
else
|
||||
offset = BINFO_OFFSET (binfo);
|
||||
|
||||
set_rtti_entry (BINFO_VIRTUALS (binfo),
|
||||
ssize_binop (MINUS_EXPR, integer_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 ())
|
||||
{
|
||||
BINFO_VTABLE (binfo) = NULL_TREE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create the declaration for the secondary vtable. */
|
||||
basetype = TYPE_MAIN_VARIANT (BINFO_TYPE (binfo));
|
||||
buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype);
|
||||
i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1;
|
||||
|
||||
@ -1228,38 +1269,11 @@ build_secondary_vtable (binfo, for_type)
|
||||
DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
|
||||
BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);
|
||||
|
||||
/* Make fresh virtual list, so we can smash it later. */
|
||||
BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));
|
||||
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
{
|
||||
tree binfo1 = BINFO_FOR_VBASE (BINFO_TYPE (binfo), for_type);
|
||||
|
||||
/* XXX - This should never happen, if it does, the caller should
|
||||
ensure that the binfo is from for_type's binfos, not from any
|
||||
base type's. We can remove all this code after a while. */
|
||||
if (binfo1 != binfo)
|
||||
warning ("internal inconsistency: binfo offset error for rtti");
|
||||
|
||||
offset = BINFO_OFFSET (binfo1);
|
||||
}
|
||||
else
|
||||
offset = BINFO_OFFSET (binfo);
|
||||
|
||||
set_rtti_entry (BINFO_VIRTUALS (binfo),
|
||||
ssize_binop (MINUS_EXPR, integer_zero_node, offset),
|
||||
for_type);
|
||||
|
||||
#ifdef GATHER_STATISTICS
|
||||
n_vtables += 1;
|
||||
n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
|
||||
#endif
|
||||
|
||||
if (TREE_VIA_VIRTUAL (binfo))
|
||||
my_friendly_assert (binfo == BINFO_FOR_VBASE (BINFO_TYPE (binfo),
|
||||
current_class_type),
|
||||
170);
|
||||
SET_BINFO_NEW_VTABLE_MARKED (binfo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2505,9 +2519,9 @@ duplicate_tag_error (t)
|
||||
TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Make the BINFO's vtablehave N entries, including RTTI entries, but
|
||||
not including vbase and vcall offsets. Set its type and call the
|
||||
backend to lay it out. */
|
||||
/* Make the BINFO's vtablehave N entries, including RTTI entries,
|
||||
vbase and vcall offsets, etc. Set its type and call the backend
|
||||
to lay it out. */
|
||||
|
||||
static void
|
||||
layout_vtable_decl (binfo, n)
|
||||
@ -2518,9 +2532,6 @@ layout_vtable_decl (binfo, n)
|
||||
tree atype;
|
||||
|
||||
itype = size_int (n);
|
||||
itype = size_binop (PLUS_EXPR,
|
||||
itype,
|
||||
num_extra_vtbl_entries (binfo));
|
||||
atype = build_cplus_array_type (vtable_entry_type,
|
||||
build_index_type (itype));
|
||||
layout_type (atype);
|
||||
@ -2621,7 +2632,9 @@ size_extra_vtbl_entries (binfo)
|
||||
}
|
||||
|
||||
/* Construct the initializer for BINFOs virtual function table. BINFO
|
||||
is part of the hierarchy dominated by T. */
|
||||
is part of the hierarchy dominated by T. The value returned is a
|
||||
TREE_LIST suitable for wrapping in a CONSTRUCTOR to use as the
|
||||
DECL_INITIAL for a vtable. */
|
||||
|
||||
static tree
|
||||
build_vtbl_initializer (binfo, t)
|
||||
@ -2722,9 +2735,26 @@ build_vtbl_initializer (binfo, t)
|
||||
|
||||
/* The initializers were built up in reverse order; straighten them
|
||||
out now. */
|
||||
inits = nreverse (inits);
|
||||
/* Package all the initializers up as an array initializer. */
|
||||
return build_nt (CONSTRUCTOR, NULL_TREE, inits);
|
||||
return nreverse (inits);
|
||||
}
|
||||
|
||||
/* Initialize the vtable for BINFO with the INITS. */
|
||||
|
||||
static void
|
||||
initialize_vtable (binfo, inits)
|
||||
tree binfo;
|
||||
tree inits;
|
||||
{
|
||||
tree context;
|
||||
tree decl;
|
||||
|
||||
layout_vtable_decl (binfo, list_length (inits));
|
||||
decl = BINFO_VTABLE (binfo);
|
||||
context = DECL_CONTEXT (decl);
|
||||
DECL_CONTEXT (decl) = 0;
|
||||
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
|
||||
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
|
||||
DECL_CONTEXT (decl) = context;
|
||||
}
|
||||
|
||||
/* Called from finish_vtbls via dfs_walk. */
|
||||
@ -2733,21 +2763,59 @@ static tree
|
||||
dfs_finish_vtbls (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
{
|
||||
if (!BINFO_PRIMARY_MARKED_P (binfo)
|
||||
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
|
||||
&& BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
initialize_vtable (binfo,
|
||||
build_vtbl_initializer (binfo, (tree) data));
|
||||
|
||||
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
|
||||
SET_BINFO_MARKED (binfo);
|
||||
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
/* Called from finish_vtbls via dfs_walk when using the new ABI.
|
||||
Accumulates the vtable initializers for all of the vtables into
|
||||
TREE_VALUE (DATA). */
|
||||
|
||||
static tree
|
||||
dfs_accumulate_vtbl_inits (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
{
|
||||
if (!BINFO_PRIMARY_MARKED_P (binfo)
|
||||
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
|
||||
&& BINFO_NEW_VTABLE_MARKED (binfo))
|
||||
{
|
||||
tree decl;
|
||||
tree context;
|
||||
|
||||
layout_vtable_decl (binfo, list_length (BINFO_VIRTUALS (binfo)));
|
||||
decl = BINFO_VTABLE (binfo);
|
||||
context = DECL_CONTEXT (decl);
|
||||
DECL_CONTEXT (decl) = 0;
|
||||
DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data);
|
||||
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
|
||||
DECL_CONTEXT (decl) = context;
|
||||
tree l;
|
||||
tree t;
|
||||
|
||||
l = (tree) data;
|
||||
t = TREE_PURPOSE (l);
|
||||
|
||||
/* If this is a secondary vtable, record its location. */
|
||||
if (binfo != TYPE_BINFO (t))
|
||||
{
|
||||
tree vtbl;
|
||||
|
||||
vtbl = TYPE_BINFO_VTABLE (t);
|
||||
vtbl = build1 (ADDR_EXPR,
|
||||
build_pointer_type (TREE_TYPE (vtbl)),
|
||||
vtbl);
|
||||
BINFO_VTABLE (binfo)
|
||||
= build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
|
||||
size_binop (MULT_EXPR,
|
||||
TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
|
||||
size_int (list_length (TREE_VALUE (l)))));
|
||||
}
|
||||
|
||||
/* Add the initializers for this vtable to the initailizers for
|
||||
the other vtables we've already got. */
|
||||
TREE_VALUE (l)
|
||||
= chainon (TREE_VALUE (l),
|
||||
build_vtbl_initializer (binfo, t));
|
||||
}
|
||||
|
||||
CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
|
||||
@ -2762,8 +2830,27 @@ static void
|
||||
finish_vtbls (t)
|
||||
tree t;
|
||||
{
|
||||
dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
|
||||
dfs_unmarked_real_bases_queue_p, t);
|
||||
if (merge_primary_and_secondary_vtables_p ())
|
||||
{
|
||||
tree list;
|
||||
|
||||
/* Under the new ABI, we lay out the primary and secondary
|
||||
vtables in one contiguous vtable. The primary vtable is
|
||||
first, followed by the secondary vtables as encountered in a
|
||||
pre-order depth-first left-to-right traversal. */
|
||||
list = build_tree_list (t, NULL_TREE);
|
||||
dfs_walk_real (TYPE_BINFO (t),
|
||||
dfs_accumulate_vtbl_inits,
|
||||
NULL,
|
||||
dfs_unmarked_real_bases_queue_p,
|
||||
list);
|
||||
if (TYPE_BINFO_VTABLE (t))
|
||||
initialize_vtable (TYPE_BINFO (t), TREE_VALUE (list));
|
||||
}
|
||||
else
|
||||
dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls,
|
||||
dfs_unmarked_real_bases_queue_p, t);
|
||||
|
||||
dfs_walk (TYPE_BINFO (t), dfs_unmark,
|
||||
dfs_marked_real_bases_queue_p, t);
|
||||
}
|
||||
@ -5039,10 +5126,6 @@ finish_struct_1 (t)
|
||||
= chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
|
||||
}
|
||||
|
||||
/* Now lay out the virtual function table. */
|
||||
if (has_virtual)
|
||||
layout_vtable_decl (TYPE_BINFO (t), has_virtual);
|
||||
|
||||
/* If we created a new vtbl pointer for this class, add it to the
|
||||
list. */
|
||||
if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1)
|
||||
@ -5098,6 +5181,10 @@ finish_struct_1 (t)
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the rtl for any new vtables we have created, and unmark
|
||||
the base types we marked. */
|
||||
finish_vtbls (t);
|
||||
|
||||
if (CLASSTYPE_VSIZE (t) != 0)
|
||||
{
|
||||
/* In addition to this one, all the other vfields should be listed. */
|
||||
@ -5113,9 +5200,6 @@ finish_struct_1 (t)
|
||||
t);
|
||||
}
|
||||
|
||||
/* Make the rtl for any new vtables we have created, and unmark
|
||||
the base types we marked. */
|
||||
finish_vtbls (t);
|
||||
hack_incomplete_structures (t);
|
||||
|
||||
if (warn_overloaded_virtual)
|
||||
|
@ -251,6 +251,10 @@ extern int flag_rtti;
|
||||
to get the type_info object address. */
|
||||
#define new_abi_rtti_p() (flag_new_abi)
|
||||
|
||||
/* Nonzero if primary and secondary vtables are combined into a single
|
||||
vtable. */
|
||||
#define merge_primary_and_secondary_vtables_p() (flag_new_abi)
|
||||
|
||||
|
||||
/* Language-dependent contents of an identifier. */
|
||||
|
||||
|
@ -656,9 +656,21 @@ expand_virtual_init (binfo, decl)
|
||||
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);
|
||||
|
||||
if (TREE_CODE (vtbl) == VAR_DECL)
|
||||
{
|
||||
assemble_external (vtbl);
|
||||
TREE_USED (vtbl) = 1;
|
||||
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
|
||||
}
|
||||
else
|
||||
/* Under the new ABI, secondary vtables are stored with the
|
||||
primary vtable. So, the BINFO_VTABLE may be an expression for
|
||||
computing the secondary vtable, rather than the secondary
|
||||
vtable itself. */
|
||||
my_friendly_assert (merge_primary_and_secondary_vtables_p (),
|
||||
20000220);
|
||||
|
||||
/* Under the new ABI, we need to point into the middle of the
|
||||
vtable. */
|
||||
if (vbase_offsets_in_vtable_p ())
|
||||
|
Loading…
Reference in New Issue
Block a user