diff options
author | Mark Mitchell <mark@codesourcery.com> | 2000-01-29 03:59:09 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2000-01-29 03:59:09 +0000 |
commit | c0bbf652c53cf976d4318b2228fb96148b16b8ae (patch) | |
tree | 3e1741ec7085c29d211f549e709d89cdd7289c08 | |
parent | 4fda2521e9a1b2062c07df7f26c8b49adf036833 (diff) | |
download | gcc-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/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/cp/class.c | 314 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 22 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 33 | ||||
-rw-r--r-- | gcc/cp/method.c | 10 |
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: */ |