This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Generate VTTs
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: Generate VTTs
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 21 May 2000 18:18:16 -0700
- Organization: CodeSourcery, LLC
This patch causes the compiler to generate VTTs under the new ABI.
These are the things that will be used in the new ABI to avoid the
infamous "vtable-thunks bug". That work isn't yet complete -- now we
have the data structures but the constructors and destructors haven't
been modified to take advantage of them.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2000-05-21 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (SET_BINFO_NEW_VTABLE_MARKED): Add sanity checks.
(VTT_NAME_PREFIX): New macro.
(CTOR_VTBL_NAME_PREFIX): Likewise.
(get_ctor_vtbl_name): New function.
* class.c (get_vtable_name): Simplify.
(get_vtt_name): New function.
(get_vtable_decl): Don't set IDENTIFIER_GLOBAL_VALUE.
(dfs_mark_primary_bases): Update the CLASSTYPE_VBASECLASSES list
when a virtual base becomes primary.
(finish_struct_1): Set CLASSTYPE_VFIELDS a little earlier. Build
VTTs.
(finish_vtbls): Adjust calls to accumulate_vtbl_inits to pass in
additional parameters.
(dfs_finish_vtbls): Don't clear BINFO_NEW_VTABLE_MARKED.
(initialize_array): New function.
(build_vtt): Likewise.
(build_vtt_inits): Likewise.
(dfs_build_vtt_inits): Likewise.
(dfs_fixup_binfo_vtbls): Likewise.
(build_ctor_vtbl_group): Likewise.
(initialize_vtable): Use initialize_array.
(accumulate_vtbl_inits): Reimplement to handle construction
vtables.
(dfs_accumulate_vtbl_inits): Likewise.
(bulid_vtbl_initializer): Adjust parameter name.
* method.c (build_typename_overload): Remove #if 0'd code.
(get_ctor_vtbl_name): New function.
* search.c (dfs_walk_real): Use BINFO_N_BASETYPES.
(init_vbase_pointers): Don't mess with the TREE_CHAIN of a binfo.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.303
diff -c -p -r1.303 class.c
*** class.c 2000/05/19 23:06:54 1.303
--- class.c 2000/05/22 01:07:01
*************** static tree get_basefndecls PARAMS ((tre
*** 93,99 ****
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));
--- 93,100 ----
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, tree, tree, tree,
! tree));
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));
*************** static void dump_class_hierarchy_r PARAM
*** 157,162 ****
--- 158,164 ----
extern void dump_class_hierarchy PARAMS ((tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
+ static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
tree, tree,
varray_type));
*************** static tree dfs_search_base_offsets PARA
*** 166,172 ****
static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
! 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));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
--- 168,174 ----
static int layout_conflict_p PARAMS ((tree, varray_type));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static void layout_empty_base PARAMS ((tree, tree, varray_type));
! static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static void set_vindex PARAMS ((tree, tree, int *));
static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree,
*************** static void clone_constructors_and_destr
*** 177,182 ****
--- 179,189 ----
static tree build_clone PARAMS ((tree, tree));
static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
static tree copy_virtuals PARAMS ((tree));
+ static void build_ctor_vtbl_group PARAMS ((tree, tree));
+ static void build_vtt PARAMS ((tree));
+ static tree *build_vtt_inits PARAMS ((tree, tree, tree *));
+ static tree dfs_build_vtt_inits PARAMS ((tree, void *));
+ static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
/* Variables shared between class.c and call.c. */
*************** static tree
*** 621,642 ****
get_vtable_name (type)
tree type;
{
! tree type_id = build_typename_overload (type);
! char *buf = (char *) alloca (strlen (VTABLE_NAME_PREFIX)
! + IDENTIFIER_LENGTH (type_id) + 2);
! const char *ptr = IDENTIFIER_POINTER (type_id);
! int i;
! for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
! #if 0
! /* We don't take off the numbers; build_secondary_vtable uses the
! DECL_ASSEMBLER_NAME for the type, which includes the number
! in `3foo'. If we were to pull them off here, we'd end up with
! something like `_vt.foo.3bar', instead of a uniform definition. */
! while (ptr[i] >= '0' && ptr[i] <= '9')
! i += 1;
! #endif
! sprintf (buf, "%s%s", VTABLE_NAME_PREFIX, ptr+i);
! return get_identifier (buf);
}
/* Return the offset to the main vtable for a given base BINFO. */
--- 628,646 ----
get_vtable_name (type)
tree type;
{
! return build_overload_with_type (get_identifier (VTABLE_NAME_PREFIX),
! type);
! }
!
! /* Return an IDENTIFIER_NODE for the name of the virtual table table
! for TYPE. */
!
! static tree
! get_vtt_name (type)
! tree type;
! {
! return build_overload_with_type (get_identifier (VTT_NAME_PREFIX),
! type);
}
/* Return the offset to the main vtable for a given base BINFO. */
*************** get_vtable_decl (type, complete)
*** 727,733 ****
decl = build_vtable (type, name, void_type_node);
decl = pushdecl_top_level (decl);
! SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
--- 731,738 ----
decl = build_vtable (type, name, void_type_node);
decl = pushdecl_top_level (decl);
! my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
! 20000517);
/* At one time the vtable info was grabbed 2 words at a time. This
fails on sparc unless you have 8-byte alignment. (tiemann) */
*************** dfs_mark_primary_bases (binfo, data)
*** 1692,1706 ****
else
{
tree shared_binfo;
! shared_binfo
! = binfo_for_vbase (BINFO_TYPE (base_binfo), (tree) data);
/* If this virtual base is not already primary somewhere else in
the hiearchy, then we'll be using this copy. */
if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
{
! BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
}
}
--- 1697,1719 ----
else
{
tree shared_binfo;
+ tree type;
! type = (tree) data;
! shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
/* If this virtual base is not already primary somewhere else in
the hiearchy, then we'll be using this copy. */
if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
{
! /* Make sure the CLASSTYPE_VBASECLASSES list contains the
! primary copy; it's the one that really exists. */
! if (base_binfo != shared_binfo)
! TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
! CLASSTYPE_VBASECLASSES (type)))
! = base_binfo;
!
! BINFO_VBASE_PRIMARY_P (base_binfo) = 1;
BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
}
}
*************** finish_struct_1 (t)
*** 4900,4905 ****
--- 4913,4924 ----
overridden_virtuals
= modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
+ /* If we created a new vtbl pointer for this class, add it to the
+ list. */
+ if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+ CLASSTYPE_VFIELDS (t)
+ = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
+
/* If necessary, create the primary vtable for this class. */
if (new_virtuals
|| overridden_virtuals
*************** finish_struct_1 (t)
*** 4962,4973 ****
= chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
}
- /* If we created a new vtbl pointer for this class, add it to the
- list. */
- if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
- CLASSTYPE_VFIELDS (t)
- = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
-
finish_struct_bits (t);
/* Complete the rtl for any static member objects of the type we're
--- 4981,4986 ----
*************** finish_struct_1 (t)
*** 5020,5025 ****
--- 5033,5040 ----
/* Make the rtl for any new vtables we have created, and unmark
the base types we marked. */
finish_vtbls (t);
+ /* Build the VTT for T. */
+ build_vtt (t);
if (TYPE_VFIELD (t))
{
*************** finish_vtbls (t)
*** 6373,6388 ****
first, followed by the non-virtual secondary vtables in
inheritance graph order. */
list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
! TREE_TYPE (list) = t;
! accumulate_vtbl_inits (TYPE_BINFO (t), list);
/* Then come the virtual bases, also in inheritance graph
order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
if (!TREE_VIA_VIRTUAL (vbase))
continue;
! accumulate_vtbl_inits (binfo_for_vbase (BINFO_TYPE (vbase), t),
! list);
}
if (TYPE_BINFO_VTABLE (t))
--- 6388,6403 ----
first, followed by the non-virtual secondary vtables in
inheritance graph order. */
list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
! accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
! TYPE_BINFO (t), t, list);
/* Then come the virtual bases, also in inheritance graph
order. */
for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
{
if (!TREE_VIA_VIRTUAL (vbase))
continue;
!
! accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
}
if (TYPE_BINFO_VTABLE (t))
*************** dfs_finish_vtbls (binfo, data)
*** 6406,6419 ****
{
tree t = (tree) data;
! if (!BINFO_PRIMARY_MARKED_P (binfo)
! && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
! && BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
build_vtbl_initializer (binfo, binfo, t,
TYPE_BINFO (t), NULL));
- CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
SET_BINFO_MARKED (binfo);
return NULL_TREE;
--- 6421,6431 ----
{
tree t = (tree) data;
! if (BINFO_NEW_VTABLE_MARKED (binfo, t))
initialize_vtable (binfo,
build_vtbl_initializer (binfo, binfo, t,
TYPE_BINFO (t), NULL));
SET_BINFO_MARKED (binfo);
return NULL_TREE;
*************** initialize_vtable (binfo, inits)
*** 6426,6521 ****
tree binfo;
tree inits;
{
- tree context;
tree decl;
layout_vtable_decl (binfo, list_length (inits));
decl = get_vtbl_decl_for_binfo (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;
}
! /* Add the vtbl initializers for BINFO (and its non-primary,
! non-virtual bases) to the list of INITS. */
static void
! accumulate_vtbl_inits (binfo, inits)
tree binfo;
! tree inits;
{
! /* Walk the BINFO and its bases. We walk in preorder so that as we
! initialize each vtable we can figure out at what offset the
! secondary vtable lies from the primary vtable. */
dfs_walk_real (binfo,
! dfs_accumulate_vtbl_inits,
NULL,
! dfs_skip_vbases,
! inits);
}
! /* 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;
{
! tree l;
tree t;
l = (tree) data;
! t = TREE_TYPE (l);
! if (!BINFO_PRIMARY_MARKED_P (binfo)
! && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
! && BINFO_NEW_VTABLE_MARKED (binfo, t))
{
! tree inits;
tree vtbl;
tree index;
int non_fn_entries;
/* Compute the initializer for this vtable. */
! inits = build_vtbl_initializer (binfo, binfo, t, TYPE_BINFO (t),
&non_fn_entries);
! /* Set BINFO_VTABLE to the address where the VPTR should point. */
vtbl = TREE_PURPOSE (l);
vtbl = build1 (ADDR_EXPR,
! build_pointer_type (TREE_TYPE (vtbl)),
vtbl);
index = size_binop (PLUS_EXPR,
size_int (non_fn_entries),
size_int (list_length (TREE_VALUE (l))));
! BINFO_VTABLE (binfo)
! = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
! size_binop (MULT_EXPR,
! TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
! index));
!
! /* Add the initializers for this vtable to the initializers for
! the other vtables we've already got. */
! TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
}
! CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
!
! return NULL_TREE;
}
/* Construct the initializer for BINFOs virtual function table. BINFO
is part of the hierarchy dominated by T. If we're building a
! construction vtable, the ORIGINAL_BINFO is the binfo we should use
! to find the actual function pointers to put in the vtable.
! Otherwise, ORIGINAL_BINFO should be the same as BINFO. The
! RTTI_DOMINATOR is the BINFO that should be indicated by the RTTI
! information in the vtable; it will be a base class of T, rather
! than T itself, if we are building a construction vtable.
The value returned is a TREE_LIST suitable for wrapping in a
CONSTRUCTOR to use as the DECL_INITIAL for a vtable. If
--- 6438,6809 ----
tree binfo;
tree inits;
{
tree decl;
layout_vtable_decl (binfo, list_length (inits));
decl = get_vtbl_decl_for_binfo (binfo);
+ initialize_array (decl, inits);
+ }
+
+ /* Initialize DECL (a declaration for a namespace-scope array) with
+ the INITS. */
+
+ static void
+ initialize_array (decl, inits)
+ tree decl;
+ tree inits;
+ {
+ tree context;
+
context = DECL_CONTEXT (decl);
! DECL_CONTEXT (decl) = NULL_TREE;
DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
DECL_CONTEXT (decl) = context;
}
! /* Build the VTT (virtual table table) for T. */
static void
! build_vtt (t)
! tree t;
! {
! tree inits;
! tree type;
! tree vtt;
!
! /* Under the old ABI, we don't use VTTs. */
! if (!flag_new_abi)
! return;
!
! /* Build up the initializers for the VTT. */
! inits = NULL_TREE;
! build_vtt_inits (TYPE_BINFO (t), t, &inits);
!
! /* If we didn't need a VTT, we're done. */
! if (!inits)
! return;
!
! /* Figure out the type of the VTT. */
! type = build_index_type (size_int (list_length (inits)));
! type = build_cplus_array_type (const_ptr_type_node, type);
!
! /* Now, build the VTT object itself. */
! vtt = build_vtable (t, get_vtt_name (t), type);
! pushdecl_top_level (vtt);
! initialize_array (vtt, inits);
! }
!
! /* Recursively build the VTT-initializer for BINFO (which is in the
! hierarchy dominated by T). INITS points to the end of the
! initializer list to date. */
!
! static tree *
! build_vtt_inits (binfo, t, inits)
tree binfo;
! tree t;
! tree *inits;
{
! int i;
! tree b;
! tree init;
! tree secondary_vptrs;
! int ctor_vtbl_p;
!
! /* We only need VTTs for subobjects with virtual bases. */
! if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
! return inits;
!
! /* We need to use a construction vtable if this is not the primary
! VTT. */
! ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
! if (ctor_vtbl_p)
! build_ctor_vtbl_group (binfo, t);
!
! /* Add the address of the primary vtable for the complete object. */
! init = BINFO_VTABLE (binfo);
! if (TREE_CODE (init) == TREE_LIST)
! init = TREE_PURPOSE (init);
! *inits = build_tree_list (NULL_TREE, init);
! inits = &TREE_CHAIN (*inits);
!
! /* Recursively add the secondary VTTs for non-virtual bases. */
! for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
! {
! b = BINFO_BASETYPE (binfo, i);
! if (!TREE_VIA_VIRTUAL (b))
! inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits);
! }
!
! /* Add secondary virtual pointers for all subobjects of BINFO with
! either virtual bases or virtual functions overridden along a
! virtual path between the declaration and D, except subobjects
! that are non-virtual primary bases. */
! secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
dfs_walk_real (binfo,
! dfs_build_vtt_inits,
NULL,
! dfs_unmarked_real_bases_queue_p,
! secondary_vptrs);
! dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
! BINFO_TYPE (binfo));
!
! /* The secondary vptrs come back in reverse order. After we reverse
! them, and add the INITS, the last init will be the first element
! of the chain. */
! secondary_vptrs = TREE_VALUE (secondary_vptrs);
! if (secondary_vptrs)
! {
! *inits = nreverse (secondary_vptrs);
! inits = &TREE_CHAIN (secondary_vptrs);
! my_friendly_assert (*inits == NULL_TREE, 20000517);
! }
!
! /* Add the secondary VTTs for virtual bases. */
! for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
! {
! tree vbase;
!
! if (!TREE_VIA_VIRTUAL (b))
! continue;
!
! vbase = binfo_for_vbase (BINFO_TYPE (b), t);
! inits = build_vtt_inits (vbase, t, inits);
! }
!
! return inits;
}
! /* Called from build_vtt_inits via dfs_walk. */
static tree
! dfs_build_vtt_inits (binfo, data)
tree binfo;
void *data;
{
! tree l;
tree t;
+ tree init;
l = (tree) data;
! t = TREE_PURPOSE (l);
!
! SET_BINFO_MARKED (binfo);
! /* We don't care about bases that don't have vtables. */
! if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
! return NULL_TREE;
!
! /* We're only interested in proper subobjects of T. */
! if (same_type_p (BINFO_TYPE (binfo), t))
! return NULL_TREE;
!
! /* We're not interested in non-virtual primary bases. */
! if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
! return NULL_TREE;
!
! /* If BINFO doesn't have virtual bases, then we have to look to see
! whether or not any virtual functions were overidden along a
! virtual path between the declaration and T. */
! if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
! /* FIXME: Implement this. */
! ;
!
! /* Add the initializer for this secondary vptr. */
! init = BINFO_VTABLE (binfo);
! if (TREE_CODE (init) == TREE_LIST)
! init = TREE_PURPOSE (init);
!
! TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
!
! return NULL_TREE;
! }
!
! /* Called from build_vtt_inits via dfs_walk. */
!
! static tree
! dfs_fixup_binfo_vtbls (binfo, data)
! tree binfo;
! void *data ATTRIBUTE_UNUSED;
! {
! CLEAR_BINFO_MARKED (binfo);
!
! /* We don't care about bases that don't have vtables. */
! if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
! return NULL_TREE;
!
! /* If we scribbled the construction vtable vptr into BINFO, clear it
! out now. */
! if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST)
! BINFO_VTABLE (binfo) = TREE_VALUE (BINFO_VTABLE (binfo));
!
! return NULL_TREE;
! }
!
! /* Build the construction vtable group for BINFO which is in the
! hierarchy dominated by T. */
!
! static void
! build_ctor_vtbl_group (binfo, t)
! tree binfo;
! tree t;
! {
! tree list;
! tree type;
! tree vtbl;
! tree inits;
! tree id;
!
! /* See if we've already create this construction vtable group. */
! id = get_ctor_vtbl_name (t, binfo);
! if (IDENTIFIER_GLOBAL_VALUE (id))
! return;
!
! /* Build a version of VTBL (with the wrong type) for use in
! constructing the addresses of secondary vtables in the
! construction vtable group. */
! vtbl = build_vtable (BINFO_TYPE (binfo), id, vtable_entry_type);
! list = build_tree_list (vtbl, NULL_TREE);
! accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
! binfo, t, list);
!
! /* Figure out the type of the construction vtable. */
! type = build_index_type (size_int (list_length (inits)));
! type = build_cplus_array_type (vtable_entry_type, type);
! TREE_TYPE (vtbl) = type;
!
! /* Initialize the construction vtable. */
! pushdecl_top_level (vtbl);
! initialize_array (vtbl, inits);
! }
!
! /* Add the vtbl initializers for BINFO (and its non-primary,
! non-virtual bases) to the list of INITS. BINFO is in the hierarchy
! dominated by T. ORIG_BINFO must have the same type as BINFO, but
! may be different from BINFO if we are building a construction
! vtable. RTTI_BINFO gives the object that should be used as the
! complete object for BINFO. */
!
! static void
! accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
! tree binfo;
! tree orig_binfo;
! tree rtti_binfo;
! tree t;
! tree inits;
! {
! int i;
! int ctor_vtbl_p;
!
! my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
! BINFO_TYPE (orig_binfo)),
! 20000517);
!
! /* This is a construction vtable if the RTTI type is not the most
! derived type in the hierarchy. */
! ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
!
! /* If we're building a construction vtable, we're not interested in
! subobjects that don't require construction vtables. */
! if (ctor_vtbl_p
! && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
! return;
!
! /* Build the initializers for the BINFO-in-T vtable. */
! TREE_VALUE (inits)
! = chainon (TREE_VALUE (inits),
! dfs_accumulate_vtbl_inits (binfo, orig_binfo,
! rtti_binfo, t, inits));
!
! /* Walk the BINFO and its bases. We walk in preorder so that as we
! initialize each vtable we can figure out at what offset the
! secondary vtable lies from the primary vtable. We can't use
! dfs_walk here because we need to iterate through bases of BINFO
! and RTTI_BINFO simultaneously. */
! for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
{
! tree base_binfo;
!
! base_binfo = BINFO_BASETYPE (binfo, i);
! /* Skip virtual bases. */
! if (TREE_VIA_VIRTUAL (base_binfo))
! continue;
! accumulate_vtbl_inits (base_binfo,
! BINFO_BASETYPE (orig_binfo, i),
! rtti_binfo,
! t,
! inits);
! }
! }
!
! /* 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). Returns the initializers for the BINFO vtable. */
!
! static tree
! dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
! tree binfo;
! tree orig_binfo;
! tree rtti_binfo;
! tree t;
! tree l;
! {
! tree inits = NULL_TREE;
! int ctor_vtbl_p;
!
! /* This is a construction vtable if the RTTI type is not the most
! derived type in the hierarchy. */
! ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
!
! if (BINFO_NEW_VTABLE_MARKED (binfo, t)
! /* We need a new vtable, even for a primary base, when we're
! building a construction vtable. */
! || (ctor_vtbl_p && orig_binfo == rtti_binfo))
! {
tree vtbl;
tree index;
int non_fn_entries;
/* Compute the initializer for this vtable. */
! inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
&non_fn_entries);
! /* Figure out the position to which the VPTR should point. */
vtbl = TREE_PURPOSE (l);
vtbl = build1 (ADDR_EXPR,
! vtbl_ptr_type_node,
vtbl);
index = size_binop (PLUS_EXPR,
size_int (non_fn_entries),
size_int (list_length (TREE_VALUE (l))));
! index = size_binop (MULT_EXPR,
! TYPE_SIZE_UNIT (vtable_entry_type),
! index);
! vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
! TREE_CONSTANT (vtbl) = 1;
!
! /* For an ordinary vtable, set BINFO_VTABLE. */
! if (!ctor_vtbl_p)
! BINFO_VTABLE (binfo) = vtbl;
! /* For a construction vtable, we can't overwrite BINFO_VTABLE.
! So, we make a TREE_LIST. Later, dfs_fixup_binfo_vtbls will
! straighten this out. */
! else
! BINFO_VTABLE (binfo) = build_tree_list (vtbl,
! BINFO_VTABLE (binfo));
}
! return inits;
}
/* Construct the initializer for BINFOs virtual function table. BINFO
is part of the hierarchy dominated by T. If we're building a
! construction vtable, the ORIG_BINFO is the binfo we should use to
! find the actual function pointers to put in the vtable. Otherwise,
! ORIG_BINFO should be the same as BINFO. The RTTI_DOMINATOR is the
! BINFO that should be indicated by the RTTI information in the
! vtable; it will be a base class of T, rather than T itself, if we
! are building a construction vtable.
The value returned is a TREE_LIST suitable for wrapping in a
CONSTRUCTOR to use as the DECL_INITIAL for a vtable. If
*************** dfs_accumulate_vtbl_inits (binfo, data)
*** 6523,6532 ****
number of non-function entries in the vtable. */
static tree
! build_vtbl_initializer (binfo, original_binfo, t, rtti_binfo,
! non_fn_entries_p)
tree binfo;
! tree original_binfo;
tree t;
tree rtti_binfo;
int *non_fn_entries_p;
--- 6811,6819 ----
number of non-function entries in the vtable. */
static tree
! build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
tree binfo;
! tree orig_binfo;
tree t;
tree rtti_binfo;
int *non_fn_entries_p;
*************** build_vtbl_initializer (binfo, original_
*** 6563,6569 ****
/* Go through all the ordinary virtual functions, building up
initializers. */
vfun_inits = NULL_TREE;
! for (v = BINFO_VIRTUALS (original_binfo); v; v = TREE_CHAIN (v))
{
tree delta;
tree vcall_index;
--- 6850,6856 ----
/* Go through all the ordinary virtual functions, building up
initializers. */
vfun_inits = NULL_TREE;
! for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
{
tree delta;
tree vcall_index;
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.456
diff -c -p -r1.456 cp-tree.h
*** cp-tree.h 2000/05/21 17:01:21 1.456
--- cp-tree.h 2000/05/22 01:07:05
*************** struct lang_type
*** 1597,1603 ****
/* A chain of BINFOs for the direct and indirect virtual base classes
that this type uses in a post-order depth-first left-to-right
order. (In other words, these bases appear in the order that they
! should be initialized.) */
#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
--- 1597,1607 ----
/* A chain of BINFOs for the direct and indirect virtual base classes
that this type uses in a post-order depth-first left-to-right
order. (In other words, these bases appear in the order that they
! should be initialized.) If a virtual base is primary, then the
! primary copy will appear on this list. Thus, the BINFOs on this
! list are all "real"; they are the same BINFOs that will be
! encountered when using dfs_unmarked_real_bases_queue_p and related
! functions. */
#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
/* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
*************** struct lang_type
*** 1721,1728 ****
B is part of the hierarchy dominated by C. */
#define BINFO_NEW_VTABLE_MARKED(B, C) \
(TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
! #define SET_BINFO_NEW_VTABLE_MARKED(B, C) \
! (BINFO_NEW_VTABLE_MARKED (B, C) = 1)
#define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
(BINFO_NEW_VTABLE_MARKED (B, C) = 0)
--- 1725,1739 ----
B is part of the hierarchy dominated by C. */
#define BINFO_NEW_VTABLE_MARKED(B, C) \
(TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
!
! /* Any subobject that needs a new vtable must have a vptr and must not
! be a primary base (since it would then use the vtable from a
! derived class.) */
! #define SET_BINFO_NEW_VTABLE_MARKED(B, C) \
! (BINFO_NEW_VTABLE_MARKED (B, C) = 1, \
! my_friendly_assert (!BINFO_PRIMARY_MARKED_P (B), 20000517), \
! my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE, \
! 20000517))
#define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
(BINFO_NEW_VTABLE_MARKED (B, C) = 0)
*************** extern tree original_function_name;
*** 3438,3443 ****
--- 3449,3463 ----
#define EXCEPTION_CLEANUP_NAME "exception cleanup"
+ /* The name used as a prefix for VTTs. When the new ABI mangling
+ scheme is implemented, this should be removed. */
+
+ #define VTT_NAME_PREFIX "__vtt_"
+
+ /* The name used as a prefix for construction vtables. */
+
+ #define CTOR_VTBL_NAME_PREFIX "__ctorvt_"
+
#define THIS_NAME_P(ID_NODE) (strcmp(IDENTIFIER_POINTER (ID_NODE), "this") == 0)
#if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL)
*************** extern void emit_thunk PARAMS ((tree)
*** 4187,4192 ****
--- 4207,4213 ----
extern void synthesize_method PARAMS ((tree));
extern tree get_id_2 PARAMS ((const char *, tree));
extern tree implicitly_declare_fn PARAMS ((special_function_kind, tree, int));
+ extern tree get_ctor_vtbl_name PARAMS ((tree, tree));
/* In optimize.c */
extern void optimize_function PARAMS ((tree));
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.155
diff -c -p -r1.155 method.c
*** method.c 2000/05/19 23:06:55 1.155
--- method.c 2000/05/22 01:07:06
*************** build_typename_overload (type)
*** 1766,1774 ****
build_mangled_name (type, 0, 1);
id = get_identifier (obstack_base (&scratch_obstack));
IDENTIFIER_OPNAME_P (id) = 1;
- #if 0
- IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type);
- #endif
TREE_TYPE (id) = type;
end_squangling ();
return id;
--- 1766,1771 ----
*************** get_id_2 (name, name2)
*** 1797,1802 ****
--- 1794,1821 ----
OB_PUTCP (name);
OB_PUTID (name2);
OB_FINISH ();
+ return get_identifier (obstack_base (&scratch_obstack));
+ }
+
+ /* Returns the name of a construction vtable group. TYPE is the most
+ derived class in the hierarhcy. BINFO is the most derived class in
+ the construction vtable group. */
+
+ tree
+ get_ctor_vtbl_name (type, binfo)
+ tree type;
+ tree binfo;
+ {
+ start_squangling ();
+ OB_INIT ();
+ OB_PUTCP (CTOR_VTBL_NAME_PREFIX);
+ build_mangled_name (type, 0, 0);
+ OB_PUTC ('_');
+ build_mangled_name (BINFO_TYPE (binfo), 0, 0);
+ OB_PUTC ('_');
+ build_overload_int (BINFO_OFFSET (binfo), mf_none);
+ OB_FINISH ();
+ end_squangling ();
return get_identifier (obstack_base (&scratch_obstack));
}
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.179
diff -c -p -r1.179 search.c
*** search.c 2000/05/21 17:01:22 1.179
--- search.c 2000/05/22 01:07:08
*************** dfs_walk_real (binfo, prefn, postfn, qfn
*** 1859,1865 ****
/* Process the basetypes. */
binfos = BINFO_BASETYPES (binfo);
! n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
--- 1859,1865 ----
/* Process the basetypes. */
binfos = BINFO_BASETYPES (binfo);
! n_baselinks = BINFO_N_BASETYPES (binfo);
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
*************** init_vbase_pointers (type, decl_ptr)
*** 2521,2527 ****
vi.inits = NULL_TREE;
/* Build up a list of the initializers. */
- TREE_CHAIN (binfo) = decl_ptr;
dfs_walk_real (binfo,
dfs_init_vbase_pointers, 0,
unmarked_vtable_pathp,
--- 2521,2526 ----