C++ PATCH: More vcall offset preparation
Mark Mitchell
mark@codesourcery.com
Fri Jan 28 19:59:00 GMT 2000
Here are some more changes to pave the way for the vcall-offset stuff
required by the new ABI.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.246
diff -c -p -r1.246 class.c
*** class.c 2000/01/26 20:51:33 1.246
--- class.c 2000/01/29 03:56:13
*************** static class_stack_node_t current_class_
*** 75,81 ****
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 get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
--- 75,81 ----
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, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_derived_offset PARAMS ((tree, tree));
static tree get_basefndecls PARAMS ((tree, tree));
*************** static void prepare_fresh_vtable PARAMS
*** 85,92 ****
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 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));
--- 85,91 ----
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, 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));
*************** static tree fixed_type_or_null PARAMS ((
*** 114,120 ****
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));
--- 113,118 ----
*************** build_vbase_path (code, type, expr, path
*** 683,705 ****
/* 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. */
static tree
! build_vtable_entry (delta, pfn)
! tree delta, pfn;
{
if (flag_vtable_thunks)
{
! HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);
! if (idelta && ! DECL_PURE_VIRTUAL_P (TREE_OPERAND (pfn, 0)))
{
! pfn = build1 (ADDR_EXPR, vtable_entry_type,
! make_thunk (pfn, idelta));
TREE_READONLY (pfn) = 1;
TREE_CONSTANT (pfn) = 1;
}
--- 681,717 ----
/* Virtual function things. */
! /* 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, 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;
! 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 = make_thunk (pfn, idelta, ivindex);
! pfn = build1 (ADDR_EXPR, vtable_entry_type, pfn);
TREE_READONLY (pfn) = 1;
TREE_CONSTANT (pfn) = 1;
}
*************** build_vtable_entry (delta, pfn)
*** 716,721 ****
--- 728,736 ----
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. */
*************** build_vtable_entry (delta, pfn)
*** 740,764 ****
}
}
- /* 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
--- 755,760 ----
*************** set_rtti_entry (virtuals, offset, type)
*** 981,987 ****
if (flag_vtable_thunks)
{
/* The first slot holds the offset. */
! TREE_PURPOSE (virtuals) = offset;
/* The next node holds the function. */
virtuals = TREE_CHAIN (virtuals);
--- 977,984 ----
if (flag_vtable_thunks)
{
/* The first slot holds the offset. */
! BF_DELTA (virtuals) = offset;
! BF_VCALL_INDEX (virtuals) = integer_zero_node;
/* The next node holds the function. */
virtuals = TREE_CHAIN (virtuals);
*************** set_rtti_entry (virtuals, offset, type)
*** 989,996 ****
}
/* This slot holds the function to call. */
! TREE_PURPOSE (virtuals) = offset;
! TREE_VALUE (virtuals) = fn;
}
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
--- 986,994 ----
}
/* This slot holds the function to call. */
! BF_DELTA (virtuals) = offset;
! BF_VCALL_INDEX (virtuals) = integer_zero_node;
! BF_FN (virtuals) = fn;
}
/* Get the VAR_DECL of the vtable for TYPE. TYPE need not be polymorphic,
*************** prepare_fresh_vtable (binfo, for_type)
*** 1260,1301 ****
SET_BINFO_NEW_VTABLE_MARKED (binfo);
}
! /* Change the offset for the FNDECL entry to NEW_OFFSET. Also update
! DECL_VINDEX (FNDECL). */
static void
! modify_vtable_entry (old_entry_in_list, new_offset, fndecl)
! tree old_entry_in_list, new_offset, fndecl;
{
! 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);
! }
! }
! /* Access the virtual function table entry N. VIRTUALS is the virtual
! function table's initializer. */
! static tree
! get_vtable_entry_n (virtuals, n)
! tree virtuals;
! unsigned HOST_WIDE_INT n;
! {
! while (n > 0)
! {
! --n;
! virtuals = TREE_CHAIN (virtuals);
}
- return virtuals;
}
/* Call this function whenever its known that a vtable for T is going
--- 1258,1328 ----
SET_BINFO_NEW_VTABLE_MARKED (binfo);
}
! /* 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 (t, binfo, fndecl, v)
! tree t;
! tree binfo;
! tree fndecl;
! tree v;
{
! 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);
! 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);
! }
}
}
/* Call this function whenever its known that a vtable for T is going
*************** add_virtual_function (new_virtuals_p, ov
*** 1337,1350 ****
tree fndecl;
tree t; /* Structure type. */
{
/* 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)
{
/* FNDECL is a new virtual function; it doesn't override any
virtual function in a base class. */
--- 1364,1383 ----
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. */
! 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. */
*************** add_virtual_function (new_virtuals_p, ov
*** 1359,1373 ****
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);
}
extern struct obstack *current_obstack;
--- 1392,1406 ----
DECL_VIRTUAL_CONTEXT (fndecl) = t;
/* Save the state we've computed on the NEW_VIRTUALS list. */
! 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;
*************** build_vtbl_initializer (binfo, t)
*** 2612,2618 ****
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);
/* Even in this case, the second entry (the tdesc pointer) is
--- 2645,2650 ----
*************** build_vtbl_initializer (binfo, t)
*** 2625,2637 ****
while (v)
{
tree delta;
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);
my_friendly_assert (TREE_CODE (delta) == INTEGER_CST, 19990727);
my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 19990727);
--- 2657,2671 ----
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 = 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);
*************** build_vtbl_initializer (binfo, t)
*** 2641,2647 ****
fn = abort_fndecl;
/* Package up that information for the vtable. */
! init = build_vtable_entry_for_fn (delta, fn);
/* And add it to the chain of initializers. */
inits = tree_cons (NULL_TREE, init, inits);
--- 2675,2681 ----
fn = abort_fndecl;
/* Package up that information for the vtable. */
! init = build_vtable_entry (delta, vcall_index, fn);
/* And add it to the chain of initializers. */
inits = tree_cons (NULL_TREE, init, inits);
*************** modify_one_vtable (binfo, t, fndecl)
*** 2908,2918 ****
if (fndecl == NULL_TREE)
return;
! virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
!
! while (virtuals)
{
! tree current_fndecl = TREE_VALUE (virtuals);
/* We should never have an instance of __pure_virtual on the
BINFO_VIRTUALS list. If we do, then we will never notice
--- 2942,2952 ----
if (fndecl == NULL_TREE)
return;
! for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
! virtuals;
! virtuals = TREE_CHAIN (virtuals), ++n)
{
! 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
*************** modify_one_vtable (binfo, t, fndecl)
*** 2922,2968 ****
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);
}
}
--- 2956,2962 ----
19990727);
if (current_fndecl && overrides (fndecl, current_fndecl))
! modify_vtable_entry (t, binfo, fndecl, virtuals);
}
}
*************** dfs_fixup_vtable_deltas (binfo, data)
*** 3083,3141 ****
if (TREE_VIA_VIRTUAL (binfo))
return NULL_TREE;
}
-
- virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
! while (virtuals)
{
! tree fndecl = TREE_VALUE (virtuals);
! tree delta = TREE_PURPOSE (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);
}
return NULL_TREE;
--- 3077,3091 ----
if (TREE_VIA_VIRTUAL (binfo))
return NULL_TREE;
}
! for (virtuals = skip_rtti_stuff (binfo, BINFO_TYPE (binfo), &n);
! virtuals;
! virtuals = TREE_CHAIN (virtuals), ++n)
{
! tree fndecl = BF_FN (virtuals);
if (fndecl)
! modify_vtable_entry (t, binfo, fndecl, virtuals);
}
return NULL_TREE;
*************** override_one_vtable (binfo, old, t)
*** 3206,3213 ****
while (orig_virtuals)
{
! tree fndecl = TREE_VALUE (virtuals);
! tree old_fndecl = TREE_VALUE (old_virtuals);
/* First check to see if they are the same. */
if (DECL_ASSEMBLER_NAME (fndecl) == DECL_ASSEMBLER_NAME (old_fndecl))
--- 3156,3163 ----
while (orig_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))
*************** override_one_vtable (binfo, old, t)
*** 3260,3266 ****
}
{
/* This MUST be overridden, or the class is ill-formed. */
! tree fndecl = TREE_VALUE (virtuals);
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
--- 3210,3216 ----
}
{
/* This MUST be overridden, or the class is ill-formed. */
! tree fndecl = BF_FN (virtuals);
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
*************** override_one_vtable (binfo, old, t)
*** 3271,3278 ****
/* 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;
}
}
virtuals = TREE_CHAIN (virtuals);
--- 3221,3228 ----
/* We can use integer_zero_node, as we will core dump
if this is used anyway. */
! BF_DELTA (virtuals) = integer_zero_node;
! BF_FN (virtuals) = fndecl;
}
}
virtuals = TREE_CHAIN (virtuals);
Index: cp-tree.def
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.def,v
retrieving revision 1.44
diff -c -p -r1.44 cp-tree.def
*** cp-tree.def 1999/12/15 09:18:21 1.44
--- cp-tree.def 2000/01/29 03:56:14
***************
*** 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.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
--- 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, 2000 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
*************** DEFTREECODE (TYPEOF_TYPE, "typeof_type",
*** 159,170 ****
/* 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).
!
! Other kinds of thunks may be defined later. */
DEFTREECODE (THUNK_DECL, "thunk_decl", 'd', 0)
/* A using declaration. DECL_INITIAL contains the specified scope.
--- 159,180 ----
/* A thunk is a stub function.
! 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.
!
! 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.
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.395
diff -c -p -r1.395 cp-tree.h
*** cp-tree.h 2000/01/26 20:51:33 1.395
--- cp-tree.h 2000/01/29 03:56:17
*************** Boston, MA 02111-1307, USA. */
*** 115,130 ****
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
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.
DECL_ARGUMENTS
For a VAR_DECL this is DECL_ANON_UNION_ELEMS.
--- 115,133 ----
For a static VAR_DECL, this is DECL_INIT_PRIORITY.
BINFO_VIRTUALS
! 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 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.
*************** struct lang_type
*** 1715,1720 ****
--- 1718,1735 ----
/* 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. */
*************** extern int flag_new_for_scope;
*** 2784,2791 ****
--- 2799,2814 ----
#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,
*************** extern tree build_overload_with_type PA
*** 3913,3919 ****
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 void emit_thunk PARAMS ((tree));
extern void synthesize_method PARAMS ((tree));
extern tree get_id_2 PARAMS ((const char *, tree));
--- 3936,3942 ----
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 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));
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.133
diff -c -p -r1.133 method.c
*** method.c 2000/01/26 20:51:34 1.133
--- method.c 2000/01/29 03:56:18
*************** hack_identifier (value, name)
*** 2008,2016 ****
tree
! make_thunk (function, delta)
tree function;
int delta;
{
tree thunk_id;
tree thunk;
--- 2008,2017 ----
tree
! make_thunk (function, delta, vcall_index)
tree function;
int delta;
+ int vcall_index;
{
tree thunk_id;
tree thunk;
*************** make_thunk (function, delta)
*** 2033,2038 ****
--- 2034,2044 ----
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));
*************** make_thunk (function, delta)
*** 2052,2057 ****
--- 2058,2065 ----
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: */
More information about the Gcc-patches
mailing list