aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2000-01-29 03:59:09 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2000-01-29 03:59:09 +0000
commitc0bbf652c53cf976d4318b2228fb96148b16b8ae (patch)
tree3e1741ec7085c29d211f549e709d89cdd7289c08
parent4fda2521e9a1b2062c07df7f26c8b49adf036833 (diff)
downloadgcc-c0bbf652c53cf976d4318b2228fb96148b16b8ae.zip
gcc-c0bbf652c53cf976d4318b2228fb96148b16b8ae.tar.gz
gcc-c0bbf652c53cf976d4318b2228fb96148b16b8ae.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/class.c314
-rw-r--r--gcc/cp/cp-tree.def22
-rw-r--r--gcc/cp/cp-tree.h33
-rw-r--r--gcc/cp/method.c10
5 files changed, 209 insertions, 194 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a316529..b742854 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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).
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 7872845..416f2b7 100644
--- a/gcc/cp/class.c
+++ b/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);
-
- /* Update the entry. */
- TREE_PURPOSE (old_entry_in_list) = new_offset;
- TREE_VALUE (old_entry_in_list) = 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);
- }
-}
+ tree base_offset, offset;
+ tree context = DECL_CLASS_CONTEXT (fndecl);
+ tree vfield = TYPE_VFIELD (t);
+ tree this_offset;
+ tree vcall_index;
+
+ offset = get_class_offset (context, t, binfo, fndecl);
+
+ /* 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)))
+ {
+ tree base_fndecl;
+
+ /* 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);
-/* Access the virtual function table entry N. VIRTUALS is the virtual
- function table's initializer. */
+ base_fndecl = BF_FN (v);
+ BF_DELTA (v) = this_offset;
+ BF_VCALL_INDEX (v) = vcall_index;
+ BF_FN (v) = fndecl;
-static tree
-get_vtable_entry_n (virtuals, n)
- tree virtuals;
- unsigned HOST_WIDE_INT n;
-{
- while (n > 0)
- {
- --n;
- virtuals = TREE_CHAIN (virtuals);
+ /* 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);
- }
- 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);
+ 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;
+ }
}
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);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 70a41b5..a57742c 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 299414a..d7aabbe 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index b43cc60..406a156 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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: */