cp-tree.def (THUNK_DECL): Discuss vcall indices.
* cp-tree.def (THUNK_DECL): Discuss vcall indices. * cp-tree.h (BINFO_VIRTUALS): Update documentation. (BF_DELTA): New macro. (BF_VCALL_INDEX): Likewise. (BF_FN): Likewise. (THUNK_VCALL_OFFSET): Likewise. (make_thunk): Change prototype. * class.c (build_vtable_entry): Integrate build_vtable_entry_for_fn. Handle vcall indices. (build_vtable_entry_for_fn): Remove. (set_rtti_entry): Handle vcall indices. Use BF_DELTA, BF_VCALL_INDEX, BF_FN. (modify_vtable_entry): Integrate common code from modify_one_vtable and dfs_fixup_vtable_deltas. (add_virtual_function): Set BF_VCALL_INDEX. (build_vtbl_initializer): Simplify. Use BF_DELTA, BF_VCALL_INDEX, and BF_FN. (modify_one_vtable): Simplify. (dfs_fixup_vtable_deltas): Likewise. (override_one_vtable): Use BF_DELTA, BF_VCALL_INDEX, BF_FN. * method.c (make_thunk): Handle vcall indices. From-SVN: r31684
This commit is contained in:
parent
4fda2521e9
commit
c0bbf652c5
@ -1,3 +1,27 @@
|
||||
2000-01-27 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* cp-tree.def (THUNK_DECL): Discuss vcall indices.
|
||||
* cp-tree.h (BINFO_VIRTUALS): Update documentation.
|
||||
(BF_DELTA): New macro.
|
||||
(BF_VCALL_INDEX): Likewise.
|
||||
(BF_FN): Likewise.
|
||||
(THUNK_VCALL_OFFSET): Likewise.
|
||||
(make_thunk): Change prototype.
|
||||
* class.c (build_vtable_entry): Integrate
|
||||
build_vtable_entry_for_fn. Handle vcall indices.
|
||||
(build_vtable_entry_for_fn): Remove.
|
||||
(set_rtti_entry): Handle vcall indices. Use BF_DELTA,
|
||||
BF_VCALL_INDEX, BF_FN.
|
||||
(modify_vtable_entry): Integrate common code from
|
||||
modify_one_vtable and dfs_fixup_vtable_deltas.
|
||||
(add_virtual_function): Set BF_VCALL_INDEX.
|
||||
(build_vtbl_initializer): Simplify. Use BF_DELTA, BF_VCALL_INDEX,
|
||||
and BF_FN.
|
||||
(modify_one_vtable): Simplify.
|
||||
(dfs_fixup_vtable_deltas): Likewise.
|
||||
(override_one_vtable): Use BF_DELTA, BF_VCALL_INDEX, BF_FN.
|
||||
* method.c (make_thunk): Handle vcall indices.
|
||||
|
||||
2000-01-28 Nathan Sidwell <sidwell@codesourcery.com>
|
||||
|
||||
Compiler side new abi rtti (not enabled).
|
||||
|
306
gcc/cp/class.c
306
gcc/cp/class.c
@ -75,7 +75,7 @@ static class_stack_node_t current_class_stack;
|
||||
static tree get_vfield_name PARAMS ((tree));
|
||||
static void finish_struct_anon PARAMS ((tree));
|
||||
static tree build_vbase_pointer PARAMS ((tree, tree));
|
||||
static tree build_vtable_entry PARAMS ((tree, tree));
|
||||
static tree build_vtable_entry PARAMS ((tree, tree, tree));
|
||||
static tree get_vtable_name PARAMS ((tree));
|
||||
static tree get_derived_offset PARAMS ((tree, tree));
|
||||
static tree get_basefndecls PARAMS ((tree, tree));
|
||||
@ -85,8 +85,7 @@ static void prepare_fresh_vtable PARAMS ((tree, tree));
|
||||
static tree dfs_fixup_vtable_deltas PARAMS ((tree, void *));
|
||||
static tree dfs_finish_vtbls PARAMS ((tree, void *));
|
||||
static void finish_vtbls PARAMS ((tree));
|
||||
static void modify_vtable_entry PARAMS ((tree, tree, tree));
|
||||
static tree get_vtable_entry_n PARAMS ((tree, unsigned HOST_WIDE_INT));
|
||||
static void modify_vtable_entry PARAMS ((tree, tree, tree, tree));
|
||||
static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
|
||||
static tree delete_duplicate_fields_1 PARAMS ((tree, tree));
|
||||
static void delete_duplicate_fields PARAMS ((tree));
|
||||
@ -114,7 +113,6 @@ static tree fixed_type_or_null PARAMS ((tree, int *));
|
||||
static tree resolve_address_of_overloaded_function PARAMS ((tree, tree, int,
|
||||
int, tree));
|
||||
static void build_vtable_entry_ref PARAMS ((tree, tree, tree));
|
||||
static tree build_vtable_entry_for_fn PARAMS ((tree, tree));
|
||||
static tree build_vtbl_initializer PARAMS ((tree, tree));
|
||||
static int count_fields PARAMS ((tree));
|
||||
static int add_fields_to_vec PARAMS ((tree, tree, int));
|
||||
@ -683,23 +681,37 @@ build_vbase_path (code, type, expr, path, nonnull)
|
||||
|
||||
/* Virtual function things. */
|
||||
|
||||
/* Build an entry in the virtual function table.
|
||||
DELTA is the offset for the `this' pointer.
|
||||
PFN is an ADDR_EXPR containing a pointer to the virtual function.
|
||||
Note that the index (DELTA2) in the virtual function table
|
||||
is always 0. */
|
||||
/* Build an entry in the virtual function table. DELTA is the offset
|
||||
for the `this' pointer. VCALL_INDEX is the vtable index containing
|
||||
the vcall offset; zero if none. FNDECL is the virtual function
|
||||
itself. */
|
||||
|
||||
static tree
|
||||
build_vtable_entry (delta, pfn)
|
||||
tree delta, pfn;
|
||||
build_vtable_entry (delta, vcall_index, fndecl)
|
||||
tree delta;
|
||||
tree vcall_index;
|
||||
tree fndecl;
|
||||
{
|
||||
tree pfn;
|
||||
|
||||
/* Take the address of the function, considering it to be of an
|
||||
appropriate generic type. */
|
||||
pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
|
||||
/* The address of a function can't change. */
|
||||
TREE_CONSTANT (pfn) = 1;
|
||||
|
||||
if (flag_vtable_thunks)
|
||||
{
|
||||
HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
|
||||
if (idelta && ! DECL_PURE_VIRTUAL_P (TREE_OPERAND (pfn, 0)))
|
||||
HOST_WIDE_INT idelta;
|
||||
HOST_WIDE_INT ivindex;
|
||||
|
||||
idelta = TREE_INT_CST_LOW (delta);
|
||||
ivindex = TREE_INT_CST_LOW (vcall_index);
|
||||
if ((idelta || ivindex)
|
||||
&& ! DECL_PURE_VIRTUAL_P (TREE_OPERAND (pfn, 0)))
|
||||
{
|
||||
pfn = build1 (ADDR_EXPR, vtable_entry_type,
|
||||
make_thunk (pfn, idelta));
|
||||
pfn = make_thunk (pfn, idelta, ivindex);
|
||||
pfn = build1 (ADDR_EXPR, vtable_entry_type, pfn);
|
||||
TREE_READONLY (pfn) = 1;
|
||||
TREE_CONSTANT (pfn) = 1;
|
||||
}
|
||||
@ -716,6 +728,9 @@ build_vtable_entry (delta, pfn)
|
||||
build_tree_list (NULL_TREE, pfn)));
|
||||
tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);
|
||||
|
||||
/* We don't use vcall offsets when not using vtable thunks. */
|
||||
my_friendly_assert (integer_zerop (vcall_index), 20000125);
|
||||
|
||||
/* DELTA used to be constructed by `size_int' and/or size_binop,
|
||||
which caused overflow problems when it was negative. That should
|
||||
be fixed now. */
|
||||
@ -740,25 +755,6 @@ build_vtable_entry (delta, pfn)
|
||||
}
|
||||
}
|
||||
|
||||
/* Build a vtable entry for FNDECL. DELTA is the amount by which we
|
||||
must adjust the this pointer when calling F. */
|
||||
|
||||
static tree
|
||||
build_vtable_entry_for_fn (delta, fndecl)
|
||||
tree delta;
|
||||
tree fndecl;
|
||||
{
|
||||
tree pfn;
|
||||
|
||||
/* Take the address of the function, considering it to be of an
|
||||
appropriate generic type. */
|
||||
pfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);
|
||||
/* The address of a function can't change. */
|
||||
TREE_CONSTANT (pfn) = 1;
|
||||
/* Now build the vtable entry itself. */
|
||||
return build_vtable_entry (delta, pfn);
|
||||
}
|
||||
|
||||
/* We want to give the assembler the vtable identifier as well as
|
||||
the offset to the function pointer. So we generate
|
||||
|
||||
@ -984,16 +980,18 @@ set_rtti_entry (virtuals, offset, type)
|
||||
if (flag_vtable_thunks)
|
||||
{
|
||||
/* The first slot holds the offset. */
|
||||
TREE_PURPOSE (virtuals) = offset;
|
||||
BF_DELTA (virtuals) = offset;
|
||||
BF_VCALL_INDEX (virtuals) = integer_zero_node;
|
||||
|
||||
/* The next node holds the decl. */
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
offset = integer_zero_node;
|
||||
}
|
||||
|
||||
/* This slot holds the decl. */
|
||||
TREE_PURPOSE (virtuals) = offset;
|
||||
TREE_VALUE (virtuals) = decl;
|
||||
/* This slot holds the function to call. */
|
||||
BF_DELTA (virtuals) = offset;
|
||||
BF_VCALL_INDEX (virtuals) = integer_zero_node;
|
||||
BF_FN (virtuals) = decl;
|
||||
}
|
||||
|
||||
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
|
||||
@ -1263,42 +1261,71 @@ prepare_fresh_vtable (binfo, for_type)
|
||||
SET_BINFO_NEW_VTABLE_MARKED (binfo);
|
||||
}
|
||||
|
||||
/* Change the offset for the FNDECL entry to NEW_OFFSET. Also update
|
||||
DECL_VINDEX (FNDECL). */
|
||||
/* Make V, an entry on the BINFO_VIRTUALS list for BINFO (which is in
|
||||
the hierarchy dominated by T) list FNDECL as its BF_FN. */
|
||||
|
||||
static void
|
||||
modify_vtable_entry (old_entry_in_list, new_offset, fndecl)
|
||||
tree old_entry_in_list, new_offset, fndecl;
|
||||
modify_vtable_entry (t, binfo, fndecl, v)
|
||||
tree t;
|
||||
tree binfo;
|
||||
tree fndecl;
|
||||
tree v;
|
||||
{
|
||||
tree base_fndecl = TREE_VALUE (old_entry_in_list);
|
||||
tree base_offset, offset;
|
||||
tree context = DECL_CLASS_CONTEXT (fndecl);
|
||||
tree vfield = TYPE_VFIELD (t);
|
||||
tree this_offset;
|
||||
tree vcall_index;
|
||||
|
||||
/* Update the entry. */
|
||||
TREE_PURPOSE (old_entry_in_list) = new_offset;
|
||||
TREE_VALUE (old_entry_in_list) = fndecl;
|
||||
offset = get_class_offset (context, t, binfo, fndecl);
|
||||
|
||||
/* Now assign virtual dispatch information, if unset. We can
|
||||
dispatch this, through any overridden base function. */
|
||||
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
|
||||
/* Find the right offset for ythe this pointer based on the
|
||||
base class we just found. We have to take into
|
||||
consideration the virtual base class pointers that we
|
||||
stick in before the virtual function table pointer.
|
||||
|
||||
Also, we want just the delta between the most base class
|
||||
that we derived this vfield from and us. */
|
||||
base_offset
|
||||
= size_binop (PLUS_EXPR,
|
||||
get_derived_offset (binfo,
|
||||
DECL_VIRTUAL_CONTEXT (BF_FN (v))),
|
||||
BINFO_OFFSET (binfo));
|
||||
this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
|
||||
vcall_index = integer_zero_node;
|
||||
|
||||
if (fndecl != BF_FN (v)
|
||||
|| !tree_int_cst_equal (this_offset, BF_DELTA (v))
|
||||
|| !tree_int_cst_equal (vcall_index, BF_VCALL_INDEX (v)))
|
||||
{
|
||||
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
|
||||
DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl);
|
||||
}
|
||||
}
|
||||
tree base_fndecl;
|
||||
|
||||
/* Access the virtual function table entry N. VIRTUALS is the virtual
|
||||
function table's initializer. */
|
||||
/* Make sure we can modify the derived association with immunity. */
|
||||
if (binfo == TYPE_BINFO (t))
|
||||
/* In this case, it is *type*'s vtable we are modifying. We
|
||||
start with the approximation that it's vtable is that of
|
||||
the immediate base class. */
|
||||
build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
|
||||
else
|
||||
/* This is our very own copy of `basetype' to play with.
|
||||
Later, we will fill in all the virtual functions that
|
||||
override the virtual functions in these base classes which
|
||||
are not defined by the current type. */
|
||||
prepare_fresh_vtable (binfo, t);
|
||||
|
||||
static tree
|
||||
get_vtable_entry_n (virtuals, n)
|
||||
tree virtuals;
|
||||
unsigned HOST_WIDE_INT n;
|
||||
{
|
||||
while (n > 0)
|
||||
{
|
||||
--n;
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
base_fndecl = BF_FN (v);
|
||||
BF_DELTA (v) = this_offset;
|
||||
BF_VCALL_INDEX (v) = vcall_index;
|
||||
BF_FN (v) = fndecl;
|
||||
|
||||
/* Now assign virtual dispatch information, if unset. We can
|
||||
dispatch this, through any overridden base function. */
|
||||
if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
|
||||
{
|
||||
DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);
|
||||
DECL_VIRTUAL_CONTEXT (fndecl) = DECL_VIRTUAL_CONTEXT (base_fndecl);
|
||||
}
|
||||
}
|
||||
return virtuals;
|
||||
}
|
||||
|
||||
/* Call this function whenever its known that a vtable for T is going
|
||||
@ -1340,14 +1367,20 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
|
||||
tree fndecl;
|
||||
tree t; /* Structure type. */
|
||||
{
|
||||
tree new_virtual;
|
||||
|
||||
/* If this function doesn't override anything from a base class, we
|
||||
can just assign it a new DECL_VINDEX now. Otherwise, if it does
|
||||
override something, we keep it around and assign its DECL_VINDEX
|
||||
later, in modify_all_vtables. */
|
||||
if (TREE_CODE (DECL_VINDEX (fndecl)) == INTEGER_CST)
|
||||
/* We've already dealt with this function. */
|
||||
;
|
||||
else if (DECL_VINDEX (fndecl) == error_mark_node)
|
||||
return;
|
||||
|
||||
new_virtual = build_tree_list (integer_zero_node, fndecl);
|
||||
BF_VCALL_INDEX (new_virtual) = integer_zero_node;
|
||||
|
||||
if (DECL_VINDEX (fndecl) == error_mark_node)
|
||||
{
|
||||
/* FNDECL is a new virtual function; it doesn't override any
|
||||
virtual function in a base class. */
|
||||
@ -1362,15 +1395,15 @@ add_virtual_function (new_virtuals_p, overridden_virtuals_p,
|
||||
DECL_VIRTUAL_CONTEXT (fndecl) = t;
|
||||
|
||||
/* Save the state we've computed on the NEW_VIRTUALS list. */
|
||||
*new_virtuals_p = tree_cons (integer_zero_node,
|
||||
fndecl,
|
||||
*new_virtuals_p);
|
||||
TREE_CHAIN (new_virtual) = *new_virtuals_p;
|
||||
*new_virtuals_p = new_virtual;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FNDECL overrides a function from a base class. */
|
||||
TREE_CHAIN (new_virtual) = *overridden_virtuals_p;
|
||||
*overridden_virtuals_p = new_virtual;
|
||||
}
|
||||
else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)
|
||||
/* FNDECL overrides a function from a base class. */
|
||||
*overridden_virtuals_p = tree_cons (NULL_TREE,
|
||||
fndecl,
|
||||
*overridden_virtuals_p);
|
||||
}
|
||||
|
||||
extern struct obstack *current_obstack;
|
||||
@ -2615,7 +2648,6 @@ build_vtbl_initializer (binfo, t)
|
||||
we can put it in the vtable. */
|
||||
init = build1 (NOP_EXPR, vfunc_ptr_type_node, offset);
|
||||
TREE_CONSTANT (init) = 1;
|
||||
init = build_vtable_entry (integer_zero_node, init);
|
||||
inits = tree_cons (NULL_TREE, init, inits);
|
||||
|
||||
v = TREE_CHAIN (v);
|
||||
@ -2645,13 +2677,15 @@ build_vtbl_initializer (binfo, t)
|
||||
while (v)
|
||||
{
|
||||
tree delta;
|
||||
tree vcall_index;
|
||||
tree fn;
|
||||
tree init;
|
||||
|
||||
/* Pull the offset for `this', and the function to call, out of
|
||||
the list. */
|
||||
delta = TREE_PURPOSE (v);
|
||||
fn = TREE_VALUE (v);
|
||||
delta = BF_DELTA (v);
|
||||
vcall_index = BF_VCALL_INDEX (v);
|
||||
fn = BF_FN (v);
|
||||
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
|
||||
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
|
||||
|
||||
@ -2661,7 +2695,7 @@ build_vtbl_initializer (binfo, t)
|
||||
fn = abort_fndecl;
|
||||
|
||||
/* Package up that information for the vtable. */
|
||||
init = build_vtable_entry_for_fn (delta, fn);
|
||||
init = build_vtable_entry (delta, vcall_index, fn);
|
||||
/* And add it to the chain of initializers. */
|
||||
inits = tree_cons (NULL_TREE, init, inits);
|
||||
|
||||
@ -2928,11 +2962,11 @@ modify_one_vtable (binfo, t, fndecl)
|
||||
if (fndecl == NULL_TREE)
|
||||
return;
|
||||
|
||||
virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
|
||||
|
||||
while (virtuals)
|
||||
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
|
||||
virtuals;
|
||||
virtuals = TREE_CHAIN (virtuals), ++n)
|
||||
{
|
||||
tree current_fndecl = TREE_VALUE (virtuals);
|
||||
tree current_fndecl = BF_FN (virtuals);
|
||||
|
||||
/* We should never have an instance of __pure_virtual on the
|
||||
BINFO_VIRTUALS list. If we do, then we will never notice
|
||||
@ -2942,47 +2976,7 @@ modify_one_vtable (binfo, t, fndecl)
|
||||
19990727);
|
||||
|
||||
if (current_fndecl && overrides (fndecl, current_fndecl))
|
||||
{
|
||||
tree base_offset, offset;
|
||||
tree context = DECL_CLASS_CONTEXT (fndecl);
|
||||
tree vfield = TYPE_VFIELD (t);
|
||||
tree this_offset;
|
||||
|
||||
offset = get_class_offset (context, t, binfo, fndecl);
|
||||
|
||||
/* Find the right offset for the this pointer based on the
|
||||
base class we just found. We have to take into
|
||||
consideration the virtual base class pointers that we
|
||||
stick in before the virtual function table pointer.
|
||||
|
||||
Also, we want just the delta between the most base class
|
||||
that we derived this vfield from and us. */
|
||||
base_offset = size_binop (PLUS_EXPR,
|
||||
get_derived_offset (binfo, DECL_CONTEXT (current_fndecl)),
|
||||
BINFO_OFFSET (binfo));
|
||||
this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
|
||||
|
||||
if (binfo == TYPE_BINFO (t))
|
||||
/* In this case, it is *type*'s vtable we are modifying.
|
||||
We start with the approximation that it's vtable is
|
||||
that of the immediate base class. */
|
||||
build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
|
||||
else
|
||||
/* This is our very own copy of `basetype' to play with.
|
||||
Later, we will fill in all the virtual functions that
|
||||
override the virtual functions in these base classes
|
||||
which are not defined by the current type. */
|
||||
prepare_fresh_vtable (binfo, t);
|
||||
|
||||
#ifdef NOTQUITE
|
||||
cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
|
||||
#endif
|
||||
modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
|
||||
this_offset,
|
||||
fndecl);
|
||||
}
|
||||
++n;
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
modify_vtable_entry (t, binfo, fndecl, virtuals);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3104,58 +3098,14 @@ dfs_fixup_vtable_deltas (binfo, data)
|
||||
return NULL_TREE;
|
||||
}
|
||||
|
||||
virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
|
||||
|
||||
while (virtuals)
|
||||
for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
|
||||
virtuals;
|
||||
virtuals = TREE_CHAIN (virtuals), ++n)
|
||||
{
|
||||
tree fndecl = TREE_VALUE (virtuals);
|
||||
tree delta = TREE_PURPOSE (virtuals);
|
||||
tree fndecl = BF_FN (virtuals);
|
||||
|
||||
if (fndecl)
|
||||
{
|
||||
tree base_offset, offset;
|
||||
tree context = DECL_CLASS_CONTEXT (fndecl);
|
||||
tree vfield = TYPE_VFIELD (t);
|
||||
tree this_offset;
|
||||
|
||||
offset = get_class_offset (context, t, binfo, fndecl);
|
||||
|
||||
/* Find the right offset for the this pointer based on the
|
||||
base class we just found. We have to take into
|
||||
consideration the virtual base class pointers that we
|
||||
stick in before the virtual function table pointer.
|
||||
|
||||
Also, we want just the delta between the most base class
|
||||
that we derived this vfield from and us. */
|
||||
base_offset = size_binop (PLUS_EXPR,
|
||||
get_derived_offset (binfo,
|
||||
DECL_CONTEXT (fndecl)),
|
||||
BINFO_OFFSET (binfo));
|
||||
this_offset = ssize_binop (MINUS_EXPR, offset, base_offset);
|
||||
|
||||
if (! tree_int_cst_equal (this_offset, delta))
|
||||
{
|
||||
/* Make sure we can modify the derived association with immunity. */
|
||||
if (binfo == TYPE_BINFO (t))
|
||||
/* In this case, it is *type*'s vtable we are modifying.
|
||||
We start with the approximation that it's vtable is that
|
||||
of the immediate base class. */
|
||||
build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);
|
||||
else
|
||||
/* This is our very own copy of `basetype' to play
|
||||
with. Later, we will fill in all the virtual
|
||||
functions that override the virtual functions in
|
||||
these base classes which are not defined by the
|
||||
current type. */
|
||||
prepare_fresh_vtable (binfo, t);
|
||||
|
||||
modify_vtable_entry (get_vtable_entry_n (BINFO_VIRTUALS (binfo), n),
|
||||
this_offset,
|
||||
fndecl);
|
||||
}
|
||||
}
|
||||
++n;
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
modify_vtable_entry (t, binfo, fndecl, virtuals);
|
||||
}
|
||||
|
||||
return NULL_TREE;
|
||||
@ -3226,8 +3176,8 @@ override_one_vtable (binfo, old, t)
|
||||
|
||||
while (orig_virtuals)
|
||||
{
|
||||
tree fndecl = TREE_VALUE (virtuals);
|
||||
tree old_fndecl = TREE_VALUE (old_virtuals);
|
||||
tree fndecl = BF_FN (virtuals);
|
||||
tree old_fndecl = BF_FN (old_virtuals);
|
||||
|
||||
/* First check to see if they are the same. */
|
||||
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
|
||||
@ -3280,7 +3230,7 @@ override_one_vtable (binfo, old, t)
|
||||
}
|
||||
{
|
||||
/* This MUST be overridden, or the class is ill-formed. */
|
||||
tree fndecl = TREE_VALUE (virtuals);
|
||||
tree fndecl = BF_FN (virtuals);
|
||||
|
||||
fndecl = copy_node (fndecl);
|
||||
copy_lang_decl (fndecl);
|
||||
@ -3291,8 +3241,8 @@ override_one_vtable (binfo, old, t)
|
||||
|
||||
/* We can use integer_zero_node, as we will core dump
|
||||
if this is used anyway. */
|
||||
TREE_PURPOSE (virtuals) = integer_zero_node;
|
||||
TREE_VALUE (virtuals) = fndecl;
|
||||
BF_DELTA (virtuals) = integer_zero_node;
|
||||
BF_FN (virtuals) = fndecl;
|
||||
}
|
||||
}
|
||||
virtuals = TREE_CHAIN (virtuals);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* This file contains the definitions and documentation for the
|
||||
additional tree codes used in the GNU C++ compiler (see tree.def
|
||||
for the standard codes).
|
||||
Copyright (C) 1987,88,90,93,97-8,1999 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987,88,90,93,97-8,1999, 2000 Free Software Foundation, Inc.
|
||||
Hacked by Michael Tiemann (tiemann@cygnus.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -159,12 +159,22 @@ DEFTREECODE (TYPEOF_TYPE, "typeof_type", 't', 0)
|
||||
|
||||
/* A thunk is a stub function.
|
||||
|
||||
Thunks are used to implement multiple inheritance:
|
||||
At run-time, such a thunk subtracts THUNK_DELTA (an int, not a tree)
|
||||
from the this pointer, and then jumps to DECL_INITIAL
|
||||
(which is an ADDR_EXPR whose operand is a FUNCTION_DECL).
|
||||
A THUNK_DECL is an alternate entry point for an ordinary
|
||||
FUNCTION_DECL. It's job is to adjust the `this' poitner before
|
||||
transferring control to the FUNCTION_DECL.
|
||||
|
||||
Other kinds of thunks may be defined later. */
|
||||
A thunk may perform either, or both, of the following operations:
|
||||
|
||||
o Adjust the `this' pointer by a constant offset.
|
||||
o Adjust the `this' pointer by looking up a vcall-offset
|
||||
in the vtable.
|
||||
|
||||
If both operations are performed, then the constant adjument to
|
||||
`this' is performed first.
|
||||
|
||||
The constant adjustment is given by THUNK_DELTA. If the
|
||||
vcall-offset is required, the index into the vtable is given by
|
||||
THUNK_VCALL_OFFSET. */
|
||||
DEFTREECODE (THUNK_DECL, "thunk_decl", 'd', 0)
|
||||
|
||||
/* A using declaration. DECL_INITIAL contains the specified scope.
|
||||
|
@ -115,15 +115,18 @@ Boston, MA 02111-1307, USA. */
|
||||
For a static VAR_DECL, this is DECL_INIT_PRIORITY.
|
||||
|
||||
BINFO_VIRTUALS
|
||||
For a binfo, this is a TREE_LIST. The TREE_PURPOSE of each node
|
||||
For a binfo, this is a TREE_LIST. The BF_DELTA of each node
|
||||
gives the amount by which to adjust the `this' pointer when
|
||||
calling the function. If the method is an overriden version of a
|
||||
base class method, then it is assumed that, prior to adjustment,
|
||||
the this pointer points to an object of the base class.
|
||||
|
||||
The TREE_VALUE is the declaration for the virtual function
|
||||
itself. When CLASSTYPE_COM_INTERFACE_P does not hold, the first
|
||||
entry does not have a TREE_VALUE; it is just an offset.
|
||||
The BF_VCALL_INDEX of each node, if non-NULL, gives the vtable
|
||||
index of the vcall offset for this entry.
|
||||
|
||||
The BF_FN is the declaration for the virtual function itself.
|
||||
When CLASSTYPE_COM_INTERFACE_P does not hold, the first entry
|
||||
does not have a BF_FN; it is just an offset.
|
||||
|
||||
DECL_ARGUMENTS
|
||||
For a VAR_DECL this is DECL_ANON_UNION_ELEMS.
|
||||
@ -1720,6 +1723,18 @@ struct lang_type
|
||||
|
||||
/* Get the value of the top-most type dominating the non-`normal' vfields. */
|
||||
#define VF_DERIVED_VALUE(NODE) (VF_BINFO_VALUE (NODE) ? BINFO_TYPE (VF_BINFO_VALUE (NODE)) : NULL_TREE)
|
||||
|
||||
/* The number of bytes by which to adjust the `this' pointer when
|
||||
calling this virtual function. */
|
||||
#define BF_DELTA(NODE) (TREE_PURPOSE (NODE))
|
||||
|
||||
/* If non-NULL, the vtable index at which to find the vcall offset
|
||||
when calling this virtual function. */
|
||||
#define BF_VCALL_INDEX(NODE) (TREE_TYPE (NODE))
|
||||
|
||||
/* The function to call. */
|
||||
#define BF_FN(NODE) (TREE_VALUE (NODE))
|
||||
|
||||
|
||||
/* Nonzero for TREE_LIST node means that this list of things
|
||||
is a list of parameters, as opposed to a list of expressions. */
|
||||
@ -2789,8 +2804,16 @@ extern int flag_new_for_scope;
|
||||
#define DECL_REALLY_EXTERN(NODE) \
|
||||
(DECL_EXTERNAL (NODE) && ! DECL_NOT_REALLY_EXTERN (NODE))
|
||||
|
||||
/* An integer indicating how many bytes should be subtracted from the
|
||||
`this' pointer when this function is called. */
|
||||
#define THUNK_DELTA(DECL) ((DECL)->decl.frame_size.i)
|
||||
|
||||
/* An integer indicating how many bytes should be subtracted from the
|
||||
vtable for the `this' pointer to find the vcall offset. (The vptr
|
||||
is always located at offset zero from the `this' pointer.) If
|
||||
zero, then there is no vcall offset. */
|
||||
#define THUNK_VCALL_OFFSET(DECL) (DECL_FIELD_SIZE (DECL))
|
||||
|
||||
/* DECL_NEEDED_P holds of a declaration when we need to emit its
|
||||
definition. This is true when the back-end tells us that
|
||||
the symbol has been referenced in the generated code. If, however,
|
||||
@ -3918,7 +3941,7 @@ extern tree build_overload_with_type PARAMS ((tree, tree));
|
||||
extern tree build_destructor_name PARAMS ((tree));
|
||||
extern tree build_opfncall PARAMS ((enum tree_code, int, tree, tree, tree));
|
||||
extern tree hack_identifier PARAMS ((tree, tree));
|
||||
extern tree make_thunk PARAMS ((tree, int));
|
||||
extern tree make_thunk PROTO((tree, int, int));
|
||||
extern void emit_thunk PARAMS ((tree));
|
||||
extern void synthesize_method PARAMS ((tree));
|
||||
extern tree get_id_2 PARAMS ((const char *, tree));
|
||||
|
@ -2008,9 +2008,10 @@ hack_identifier (value, name)
|
||||
|
||||
|
||||
tree
|
||||
make_thunk (function, delta)
|
||||
make_thunk (function, delta, vcall_index)
|
||||
tree function;
|
||||
int delta;
|
||||
int vcall_index;
|
||||
{
|
||||
tree thunk_id;
|
||||
tree thunk;
|
||||
@ -2033,6 +2034,11 @@ make_thunk (function, delta)
|
||||
icat (-delta);
|
||||
OB_PUTC ('_');
|
||||
OB_PUTID (DECL_ASSEMBLER_NAME (func_decl));
|
||||
if (vcall_index)
|
||||
{
|
||||
OB_PUTC ('_');
|
||||
icat (vcall_index);
|
||||
}
|
||||
OB_FINISH ();
|
||||
thunk_id = get_identifier (obstack_base (&scratch_obstack));
|
||||
|
||||
@ -2052,6 +2058,8 @@ make_thunk (function, delta)
|
||||
TREE_SET_CODE (thunk, THUNK_DECL);
|
||||
DECL_INITIAL (thunk) = function;
|
||||
THUNK_DELTA (thunk) = delta;
|
||||
THUNK_VCALL_OFFSET (thunk)
|
||||
= vcall_index * TREE_INT_CST_LOW (TYPE_SIZE (vtable_entry_type));
|
||||
DECL_EXTERNAL (thunk) = 1;
|
||||
DECL_ARTIFICIAL (thunk) = 1;
|
||||
/* So that finish_file can write out any thunks that need to be: */
|
||||
|
Loading…
Reference in New Issue
Block a user