Commit 8d7a5379 by Mark Mitchell Committed by Mark Mitchell

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
parent b9f39201
2000-02-20 Mark Mitchell <mark@codesourcery.com> 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 ... * class.c (build_vtable): New function, split out from ...
(get_vtable_decl): ... here, and ... (get_vtable_decl): ... here, and ...
(build_secondary_vtable): ... here. (build_secondary_vtable): ... here.
......
...@@ -84,6 +84,7 @@ static void set_rtti_entry PARAMS ((tree, tree, tree)); ...@@ -84,6 +84,7 @@ 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 *));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, void *));
static void finish_vtbls PARAMS ((tree)); static void finish_vtbls PARAMS ((tree));
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *)); static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
static void add_virtual_function PARAMS ((tree *, tree *, int *, 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 *)); ...@@ -153,6 +154,7 @@ static tree dfs_find_base PARAMS ((tree, void *));
static int make_new_vtable PARAMS ((tree, tree)); static int make_new_vtable PARAMS ((tree, tree));
extern void dump_class_hierarchy PARAMS ((tree, int)); extern void dump_class_hierarchy PARAMS ((tree, int));
static tree build_vtable PARAMS ((tree, tree, tree)); static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
/* Variables shared between class.c and call.c. */ /* Variables shared between class.c and call.c. */
...@@ -1140,13 +1142,52 @@ build_secondary_vtable (binfo, for_type) ...@@ -1140,13 +1142,52 @@ build_secondary_vtable (binfo, for_type)
joiner = JOINER; joiner = JOINER;
#endif #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)) if (BINFO_NEW_VTABLE_MARKED (binfo))
/* We already created a vtable for this base. There's no need to /* We already created a vtable for this base. There's no need to
do it again. */ do it again. */
return 0; 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); buf2 = TYPE_ASSEMBLER_NAME_STRING (basetype);
i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1; i = TYPE_ASSEMBLER_NAME_LENGTH (basetype) + 1;
...@@ -1228,38 +1269,11 @@ build_secondary_vtable (binfo, for_type) ...@@ -1228,38 +1269,11 @@ build_secondary_vtable (binfo, for_type)
DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl); DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);
BINFO_VTABLE (binfo) = pushdecl_top_level (new_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 #ifdef GATHER_STATISTICS
n_vtables += 1; n_vtables += 1;
n_vtable_elems += list_length (BINFO_VIRTUALS (binfo)); n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));
#endif #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; return 1;
} }
...@@ -2505,9 +2519,9 @@ duplicate_tag_error (t) ...@@ -2505,9 +2519,9 @@ duplicate_tag_error (t)
TYPE_NONCOPIED_PARTS (t) = NULL_TREE; TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
} }
/* Make the BINFO's vtablehave N entries, including RTTI entries, but /* Make the BINFO's vtablehave N entries, including RTTI entries,
not including vbase and vcall offsets. Set its type and call the vbase and vcall offsets, etc. Set its type and call the backend
backend to lay it out. */ to lay it out. */
static void static void
layout_vtable_decl (binfo, n) layout_vtable_decl (binfo, n)
...@@ -2518,9 +2532,6 @@ layout_vtable_decl (binfo, n) ...@@ -2518,9 +2532,6 @@ layout_vtable_decl (binfo, n)
tree atype; tree atype;
itype = size_int (n); itype = size_int (n);
itype = size_binop (PLUS_EXPR,
itype,
num_extra_vtbl_entries (binfo));
atype = build_cplus_array_type (vtable_entry_type, atype = build_cplus_array_type (vtable_entry_type,
build_index_type (itype)); build_index_type (itype));
layout_type (atype); layout_type (atype);
...@@ -2621,7 +2632,9 @@ size_extra_vtbl_entries (binfo) ...@@ -2621,7 +2632,9 @@ size_extra_vtbl_entries (binfo)
} }
/* Construct the initializer for BINFOs virtual function table. 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 static tree
build_vtbl_initializer (binfo, t) build_vtbl_initializer (binfo, t)
...@@ -2722,9 +2735,26 @@ build_vtbl_initializer (binfo, t) ...@@ -2722,9 +2735,26 @@ build_vtbl_initializer (binfo, t)
/* The initializers were built up in reverse order; straighten them /* The initializers were built up in reverse order; straighten them
out now. */ out now. */
inits = nreverse (inits); return nreverse (inits);
/* Package all the initializers up as an array initializer. */ }
return build_nt (CONSTRUCTOR, NULL_TREE, 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. */ /* Called from finish_vtbls via dfs_walk. */
...@@ -2737,17 +2767,55 @@ dfs_finish_vtbls (binfo, data) ...@@ -2737,17 +2767,55 @@ dfs_finish_vtbls (binfo, data)
if (!BINFO_PRIMARY_MARKED_P (binfo) if (!BINFO_PRIMARY_MARKED_P (binfo)
&& CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)) && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
&& BINFO_NEW_VTABLE_MARKED (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 l;
tree context; tree t;
layout_vtable_decl (binfo, list_length (BINFO_VIRTUALS (binfo))); l = (tree) data;
decl = BINFO_VTABLE (binfo); t = TREE_PURPOSE (l);
context = DECL_CONTEXT (decl);
DECL_CONTEXT (decl) = 0; /* If this is a secondary vtable, record its location. */
DECL_INITIAL (decl) = build_vtbl_initializer (binfo, (tree) data); if (binfo != TYPE_BINFO (t))
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0); {
DECL_CONTEXT (decl) = context; 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); CLEAR_BINFO_NEW_VTABLE_MARKED (binfo);
...@@ -2762,8 +2830,27 @@ static void ...@@ -2762,8 +2830,27 @@ static void
finish_vtbls (t) finish_vtbls (t)
tree t; tree t;
{ {
dfs_walk (TYPE_BINFO (t), dfs_finish_vtbls, if (merge_primary_and_secondary_vtables_p ())
dfs_unmarked_real_bases_queue_p, t); {
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_walk (TYPE_BINFO (t), dfs_unmark,
dfs_marked_real_bases_queue_p, t); dfs_marked_real_bases_queue_p, t);
} }
...@@ -5039,10 +5126,6 @@ finish_struct_1 (t) ...@@ -5039,10 +5126,6 @@ finish_struct_1 (t)
= chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals); = 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 /* If we created a new vtbl pointer for this class, add it to the
list. */ list. */
if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1) if (TYPE_VFIELD (t) && CLASSTYPE_VFIELD_PARENT (t) == -1)
...@@ -5098,6 +5181,10 @@ finish_struct_1 (t) ...@@ -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) if (CLASSTYPE_VSIZE (t) != 0)
{ {
/* In addition to this one, all the other vfields should be listed. */ /* In addition to this one, all the other vfields should be listed. */
...@@ -5113,9 +5200,6 @@ finish_struct_1 (t) ...@@ -5113,9 +5200,6 @@ finish_struct_1 (t)
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); hack_incomplete_structures (t);
if (warn_overloaded_virtual) if (warn_overloaded_virtual)
......
...@@ -251,6 +251,10 @@ extern int flag_rtti; ...@@ -251,6 +251,10 @@ extern int flag_rtti;
to get the type_info object address. */ to get the type_info object address. */
#define new_abi_rtti_p() (flag_new_abi) #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. */ /* Language-dependent contents of an identifier. */
......
...@@ -656,9 +656,21 @@ expand_virtual_init (binfo, decl) ...@@ -656,9 +656,21 @@ expand_virtual_init (binfo, decl)
vtype = DECL_CONTEXT (TYPE_VFIELD (type)); vtype = DECL_CONTEXT (TYPE_VFIELD (type));
vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0); vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo)); vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
assemble_external (vtbl);
TREE_USED (vtbl) = 1; if (TREE_CODE (vtbl) == VAR_DECL)
vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl); {
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 /* Under the new ABI, we need to point into the middle of the
vtable. */ vtable. */
if (vbase_offsets_in_vtable_p ()) if (vbase_offsets_in_vtable_p ())
......
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