Commit bbd15aac by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (flag_new_abi): Move.

	* cp-tree.h (flag_new_abi): Move.
	(flag_use_cxa_atexit): Likewise.
	(flag_honor_std): Likewise.
	(flag_rtti): Likewise.
	(vbase_offsets_in_vtable_p): Define.
	(vptrs_present_everywhere_p): Likewise.
	(TYPE_CONTAINS_VPTR_P): Likewise.
	(dfs_walk_real): Declare.
	* class.c (build_vbase_pointer_fields): Check
	vbase_offsets_in_vtable_p.
	(dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
	BINFO_VPTR_FIELD.
	(build_vbase_offset_vtbl_entries): Simplify.
	(build_vbase_offset_vtbl_entries): Adjust.
	(build_vbase_pointer): Add ability to look up vbase offsets in
	vtable.
	(start_vtable): New function.
	(add_virtual_function): Use it.
	(determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
	(num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
	(build_vtbl_initializer): Take the type of the complete object as
	input.  Use it to correctly calculate vbase offsets.
	(dfs_finish_vtbls): Pass the complete type to
	build_vtbl_initializer.
	(check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
	(create_vtable_ptr): Create a vtable even if there are no
	new virtual functions, under the new ABI.
	(finish_struct_1): Likewise.
	(get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
	* decl.c (exapnd_static_init): Remove call to
	preserve_initializer.
	* decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
	vtables.
	* init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
	(expand_virtual_init): Use vbase_offsets_in_vtable_p.
	(construct_virtual_bases): Don't initialize virtual base pointers
	under the new ABI.
	(build_aggr_init): Clean up comment.
	(expand_aggr_init_1): Likewise.
	* rtti.c (expand_class_desc): Store the virtual function table
	index where the vbase offset lives in the offset field.
	* search.c (dfs_walk_real): Make it global.
	(dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
	* tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.

	* tinfo.h (USItype): Make it signed under the new ABI.
	* tinfo.cc (convert_to_base): New function.  Encapsulate base
	conversion logic here.
	(__class_type_info::do_upcast): Use it.
	(__class_type_info::do_dyncast): Likewise.
	(__class_type_info::do_find_public_subobj): Likewise.

From-SVN: r31452
parent 2a198bc4
2000-01-16 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (flag_new_abi): Move.
(flag_use_cxa_atexit): Likewise.
(flag_honor_std): Likewise.
(flag_rtti): Likewise.
(vbase_offsets_in_vtable_p): Define.
(vptrs_present_everywhere_p): Likewise.
(TYPE_CONTAINS_VPTR_P): Likewise.
(dfs_walk_real): Declare.
* class.c (build_vbase_pointer_fields): Check
vbase_offsets_in_vtable_p.
(dfs_build_vbase_offset_vtbl_entries): Record the vbase indices in
BINFO_VPTR_FIELD.
(build_vbase_offset_vtbl_entries): Simplify.
(build_vbase_offset_vtbl_entries): Adjust.
(build_vbase_pointer): Add ability to look up vbase offsets in
vtable.
(start_vtable): New function.
(add_virtual_function): Use it.
(determine_primary_base): Use TYPE_CONTAINS_VPTR_P.
(num_extra_vtbl_entries): Use vbase_offsets_in_vtable_p.
(build_vtbl_initializer): Take the type of the complete object as
input. Use it to correctly calculate vbase offsets.
(dfs_finish_vtbls): Pass the complete type to
build_vtbl_initializer.
(check_bases_and_members): Use TYPE_CONTAINS_VPTR_P.
(create_vtable_ptr): Create a vtable even if there are no
new virtual functions, under the new ABI.
(finish_struct_1): Likewise.
(get_vfield_name): Use TYPE_CONTAINS_VPTR_P.
* decl.c (exapnd_static_init): Remove call to
preserve_initializer.
* decl2.c (mark_vtable_entries): Tweak to handle vbase offsets in
vtables.
* init.c (initialize_vtbl_ptrs): Initialize them in pre-order.
(expand_virtual_init): Use vbase_offsets_in_vtable_p.
(construct_virtual_bases): Don't initialize virtual base pointers
under the new ABI.
(build_aggr_init): Clean up comment.
(expand_aggr_init_1): Likewise.
* rtti.c (expand_class_desc): Store the virtual function table
index where the vbase offset lives in the offset field.
* search.c (dfs_walk_real): Make it global.
(dfs_debug_mark): Use TYPE_CONTAINS_VPTR_P.
* tree.c (make_binfo): Don't clear BINFO_VPTR_FIELD.
* tinfo.h (USItype): Make it signed under the new ABI.
* tinfo.cc (convert_to_base): New function. Encapsulate base
conversion logic here.
(__class_type_info::do_upcast): Use it.
(__class_type_info::do_dyncast): Likewise.
(__class_type_info::do_find_public_subobj): Likewise.
* init.c (construct_virtual_bases): Don't look up the addresses of
virtual bases at run-time.
......
......@@ -177,7 +177,44 @@ Boston, MA 02111-1307, USA. */
#define RECORD_OR_UNION_TYPE_CHECK(NODE) NODE
#endif
/* ABI control. */
/* Nonzero to enable experimental ABI changes. */
extern int flag_new_abi;
/* Nonzero to use __cxa_atexit, rather than atexit, to register
destructors for local statics and global objects. */
extern int flag_use_cxa_atexit;
/* Nonzero to not ignore namespace std. */
extern int flag_honor_std;
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
/* Nonzero if virtual base class offsets are stored in the virtual
function table. Zero if, instead, a pointer to the virtual base is
stored in the object itself. */
#define vbase_offsets_in_vtable_p() (flag_new_abi)
/* Nonzero if a derived class that needs a vptr should always get one,
even if a non-primary base class already has one. For example,
given:
struct S { int i; virtual void f(); };
struct T : virtual public S {};
one could either reuse the vptr in `S' for `T', or create a new
vptr for `T'. If this flag is nonzero we choose the latter
alternative; otherwise, we choose the former. */
#define vptrs_present_everywhere_p() (flag_new_abi)
/* Language-dependent contents of an identifier. */
struct lang_identifier
......@@ -2156,6 +2193,12 @@ struct lang_decl
polymorphic class. */
#define TYPE_POLYMORPHIC_P(NODE) (TREE_LANG_FLAG_2 (NODE))
/* Nonzero if this class has a virtual function table pointer. */
#define TYPE_CONTAINS_VPTR_P(NODE) \
(TYPE_POLYMORPHIC_P (NODE) \
|| (vbase_offsets_in_vtable_p () \
&& TYPE_USES_VIRTUAL_BASECLASSES (NODE)))
extern int flag_new_for_scope;
/* This flag is true of a local VAR_DECL if it was declared in a for
......@@ -3160,10 +3203,6 @@ extern struct pending_inline *pending_inlines;
extern int flag_this_is_variable;
/* Nonzero means generate 'rtti' that give run-time type information. */
extern int flag_rtti;
/* Nonzero means do emit exported implementations of functions even if
they can be inlined. */
......@@ -3187,19 +3226,6 @@ extern int flag_implicit_templates;
extern int flag_weak;
/* Nonzero to enable experimental ABI changes. */
extern int flag_new_abi;
/* Nonzero to use __cxa_atexit, rather than atexit, to register
destructors for local statics and global objects. */
extern int flag_use_cxa_atexit;
/* Nonzero to not ignore namespace std. */
extern int flag_honor_std;
/* Nonzero if we should expand functions calls inline at the tree
level, rather than at the RTL level. */
......@@ -3961,6 +3987,11 @@ extern tree dfs_walk PROTO((tree,
tree (*)(tree, void *),
tree (*) (tree, void *),
void *));
extern tree dfs_walk_real PROTO ((tree,
tree (*) (tree, void *),
tree (*) (tree, void *),
tree (*) (tree, void *),
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 *));
......
......@@ -8201,15 +8201,7 @@ expand_static_init (decl, init)
finish_if_stmt ();
}
else
{
/* This code takes into account memory allocation policy of
`start_decl'. Namely, if TYPE_NEEDS_CONSTRUCTING does not
hold for this object, then we must make permanent the storage
currently in the temporary obstack. */
if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
preserve_initializer ();
static_aggregates = tree_cons (init, decl, static_aggregates);
}
static_aggregates = tree_cons (init, decl, static_aggregates);
}
/* Finish the declaration of a catch-parameter. */
......
......@@ -2296,8 +2296,9 @@ mark_vtable_entries (decl)
fnaddr = (flag_vtable_thunks ? TREE_VALUE (entries)
: FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)));
if (TREE_CODE (fnaddr) == NOP_EXPR)
/* RTTI offset. */
if (TREE_CODE (fnaddr) != ADDR_EXPR)
/* This entry is an offset: a virtual base class offset, a
virtual call offset, and RTTI offset, etc. */
continue;
fn = TREE_OPERAND (fnaddr, 0);
......
......@@ -119,8 +119,12 @@ initialize_vtbl_ptrs (type, addr)
{
tree list = build_tree_list (type, addr);
dfs_walk (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
dfs_unmarked_real_bases_queue_p, list);
/* Walk through the hierarchy, initializing the vptr in each base
class. We do these in pre-order because under the new ABI we
can't find the virtual bases for a class until we've initialized
the vtbl for that class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
NULL, dfs_unmarked_real_bases_queue_p, list);
dfs_walk (TYPE_BINFO (type), dfs_unmark,
dfs_marked_real_bases_queue_p, type);
if (TYPE_USES_VIRTUAL_BASECLASSES (type))
......@@ -657,7 +661,7 @@ expand_virtual_init (binfo, decl)
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)
if (vbase_offsets_in_vtable_p ())
vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
size_extra_vtbl_entries (binfo));
......@@ -720,7 +724,7 @@ expand_aggr_vbase_init_1 (binfo, exp, addr, init_list)
/* Construct the virtual base-classes of THIS_REF (whose address is
THIS_PTR). The object has the indicated TYPE. The construction
actually takes place only if FLAG is non-zero. INIT_LIST is list
of initialization for constructor to perform. */
of initializations for constructors to perform. */
static void
construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
......@@ -731,21 +735,25 @@ construct_virtual_bases (type, this_ref, this_ptr, init_list, flag)
tree flag;
{
tree vbases;
tree result;
tree if_stmt;
/* If there are no virtual baseclasses, we shouldn't even be here. */
my_friendly_assert (TYPE_USES_VIRTUAL_BASECLASSES (type), 19990621);
/* First set the pointers in our object that tell us where to find
our virtual baseclasses. */
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, if_stmt);
result = init_vbase_pointers (type, this_ptr);
if (result)
finish_expr_stmt (build_compound_expr (result));
finish_then_clause (if_stmt);
finish_if_stmt ();
if (!vbase_offsets_in_vtable_p ())
{
tree if_stmt;
tree result;
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, if_stmt);
result = init_vbase_pointers (type, this_ptr);
if (result)
finish_expr_stmt (build_compound_expr (result));
finish_then_clause (if_stmt);
finish_if_stmt ();
}
/* Now, run through the baseclasses, initializing each. */
for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;
......@@ -1019,11 +1027,6 @@ finish_init_stmts (stmt_expr, compound_stmt)
If `init' is a CONSTRUCTOR, then we emit a warning message,
explaining that such initializations are invalid.
ALIAS_THIS is nonzero iff we are initializing something which is
essentially an alias for current_class_ref. In this case, the base
constructor may move it on us, and we must keep track of such
deviations.
If INIT resolves to a CALL_EXPR which happens to return
something of the type we are looking for, then we know
that we can safely use that call to perform the
......@@ -1217,8 +1220,6 @@ expand_default_init (binfo, true_exp, exp, init, flags)
from TRUE_EXP. In constructors, we don't know anything about
the value being initialized.
ALIAS_THIS serves the same purpose it serves for expand_aggr_init.
FLAGS is just passes to `build_method_call'. See that function for
its description. */
......
/* RunTime Type Identification
Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.
Copyright (C) 1995, 96-97, 1998, 1999, 2000 Free Software Foundation, Inc.
Mostly written by Jason Merrill (jason@cygnus.com).
This file is part of GNU CC.
......@@ -811,7 +811,8 @@ expand_class_desc (tdecl, type)
(type_info_type_node,
TYPE_QUAL_CONST)));
fields [1] = build_lang_decl
(FIELD_DECL, NULL_TREE, unsigned_intSI_type_node);
(FIELD_DECL, NULL_TREE,
flag_new_abi ? intSI_type_node : unsigned_intSI_type_node);
DECL_BIT_FIELD (fields[1]) = 1;
DECL_FIELD_SIZE (fields[1]) = 29;
......@@ -839,15 +840,26 @@ expand_class_desc (tdecl, type)
if (TREE_VIA_VIRTUAL (binfo))
{
tree t = BINFO_TYPE (binfo);
const char *name;
tree field;
FORMAT_VBASE_NAME (name, t);
field = lookup_field (type, get_identifier (name), 0, 0);
offset = size_binop (FLOOR_DIV_EXPR,
DECL_FIELD_BITPOS (field), size_int (BITS_PER_UNIT));
offset = convert (sizetype, offset);
if (!vbase_offsets_in_vtable_p ())
{
tree t = BINFO_TYPE (binfo);
const char *name;
tree field;
FORMAT_VBASE_NAME (name, t);
field = lookup_field (type, get_identifier (name), 0, 0);
offset = size_binop (FLOOR_DIV_EXPR,
DECL_FIELD_BITPOS (field),
size_int (BITS_PER_UNIT));
offset = convert (sizetype, offset);
}
else
{
/* Under the new ABI, we store the vtable offset at which
the virtual base offset can be found. */
tree vbase = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
offset = convert (sizetype, BINFO_VPTR_FIELD (vbase));
}
}
else
offset = BINFO_OFFSET (binfo);
......
......@@ -126,11 +126,6 @@ static tree bfs_walk
void *));
static tree lookup_field_queue_p PROTO((tree, void *));
static tree lookup_field_r PROTO((tree, void *));
static tree dfs_walk_real PROTO ((tree,
tree (*) (tree, void *),
tree (*) (tree, void *),
tree (*) (tree, void *),
void *));
static tree get_virtuals_named_this_r PROTO ((tree, void *));
static tree context_for_name_lookup PROTO ((tree));
static tree canonical_binfo PROTO ((tree));
......@@ -1773,7 +1768,7 @@ bfs_walk (binfo, fn, qfn, data)
performed, and PREFN is called in preorder, while POSTFN is called
in postorder. */
static tree
tree
dfs_walk_real (binfo, prefn, postfn, qfn, data)
tree binfo;
tree (*prefn) PROTO((tree, void *));
......@@ -3200,9 +3195,9 @@ maybe_suppress_debug_info (t)
TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
else if (CLASSTYPE_INTERFACE_KNOWN (t))
/* Don't set it. */;
/* If the class has virtual functions, write out the debug info
along with the vtable. */
else if (TYPE_POLYMORPHIC_P (t))
/* If the class has a vtable, write out the debug info along with
the vtable. */
else if (TYPE_CONTAINS_VPTR_P (t))
TYPE_DECL_SUPPRESS_DEBUG (TYPE_MAIN_DECL (t)) = 1;
/* Otherwise, just emit the debug info normally. */
......
// Methods for type_info for -*- C++ -*- Run Time Type Identification.
// Copyright (C) 1994, 1996, 1998, 1999 Free Software Foundation
// Copyright (C) 1994, 1996, 1998, 1999, 2000 Free Software Foundation
// This file is part of GNU CC.
......@@ -31,6 +31,34 @@
#include "tinfo.h"
#include "new" // for placement new
namespace
{
// ADDR is a pointer to an object. Convert it to a pointer to a base,
// using OFFSET.
inline void*
convert_to_base (void *addr, bool is_virtual, USItype offset)
{
if (!addr)
return NULL;
if (!is_virtual)
return (char *) addr + offset;
#ifdef __GXX_ABI_VERSION
// Under the new ABI, the offset gives us an index into the vtable,
// which contains an offset to the virtual base. The vptr is always
// the first thing in the object.
std::ptrdiff_t *vtable = *((std::ptrdiff_t **) addr);
return ((char *) addr) + vtable[offset];
#else
// Under the old ABI, the offset gives us the address of a pointer
// to the virtual base.
return *((void **) ((char *) addr + offset));
#endif
}
}
// This file contains the minimal working set necessary to link with code
// that uses virtual functions and -frtti but does not actually use RTTI
// functionality.
......@@ -254,14 +282,11 @@ do_upcast (sub_kind access_path,
upcast_result result2;
void *p = objptr;
sub_kind sub_access = access_path;
if (p)
p = (char *)p + base_list[i].offset;
p = convert_to_base (p,
base_list[i].is_virtual,
base_list[i].offset);
if (base_list[i].is_virtual)
{
if (p)
p = *(void **)p;
sub_access = sub_kind (sub_access | contained_virtual_mask);
}
sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base_list[i].access != PUBLIC)
sub_access = sub_kind (sub_access & ~contained_public_mask);
if (base_list[i].base->do_upcast (sub_access, target, p, result2))
......@@ -344,13 +369,13 @@ do_dyncast (int boff, sub_kind access_path,
for (size_t i = n_bases; i--;)
{
dyncast_result result2;
void *p = (char *)objptr + base_list[i].offset;
void *p;
sub_kind sub_access = access_path;
p = convert_to_base (objptr,
base_list[i].is_virtual,
base_list[i].offset);
if (base_list[i].is_virtual)
{
p = *(void **)p;
sub_access = sub_kind (sub_access | contained_virtual_mask);
}
sub_access = sub_kind (sub_access | contained_virtual_mask);
if (base_list[i].access != PUBLIC)
sub_access = sub_kind (sub_access & ~contained_public_mask);
......@@ -492,13 +517,15 @@ do_find_public_subobj (int boff, const type_info &subtype, void *objptr, void *s
{
if (base_list[i].access != PUBLIC)
continue; // Not public, can't be here.
void *p = (char *)objptr + base_list[i].offset;
if (base_list[i].is_virtual)
{
if (boff == -1)
continue; // Not a virtual base, so can't be here.
p = *(void **)p;
}
void *p;
if (base_list[i].is_virtual && boff == -1)
// Not a virtual base, so can't be here.
continue;
p = convert_to_base (objptr,
base_list[i].is_virtual,
base_list[i].offset);
sub_kind base_kind = base_list[i].base->do_find_public_subobj
(boff, subtype, p, subptr);
......
// RTTI support internals for -*- C++ -*-
// Copyright (C) 1994, 1995, 1996, 1998, 1999 Free Software Foundation
// Copyright (C) 1994, 1995, 1996, 1998, 1999, 2000 Free Software Foundation
#include "typeinfo"
......@@ -167,7 +167,11 @@ public:
// type_info for a general class.
#ifdef __GXX_ABI_VERSION
typedef int USItype __attribute__ ((mode (SI)));
#else
typedef unsigned int USItype __attribute__ ((mode (SI)));
#endif
struct __class_type_info : public __user_type_info {
enum access { PUBLIC = 1, PROTECTED = 2, PRIVATE = 3 };
......
......@@ -860,7 +860,6 @@ make_binfo (offset, binfo, vtable, virtuals)
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
BINFO_VIRTUALS (new_binfo) = virtuals;
BINFO_VPTR_FIELD (new_binfo) = NULL_TREE;
if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE)
BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo));
......
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