]> gcc.gnu.org Git - gcc.git/commitdiff
cp-tree.def (THUNK_DECL): Discuss vcall indices.
authorMark Mitchell <mark@codesourcery.com>
Sat, 29 Jan 2000 03:59:09 +0000 (03:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sat, 29 Jan 2000 03:59:09 +0000 (03:59 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/method.c

index a316529bddc66bd53d351ab3e71230a91b32e326..b742854e73fe71f079b8f9d3b48ca3f674385de4 100644 (file)
@@ -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).
index 7872845d8c6603a5b13a4f2d15d22142e9c6951c..416f2b7cafd8ee87f93a5feaa7f874ca3585a1f2 100644 (file)
@@ -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)
 \f
 /* 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;
+    }
 }
 \f
 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);
index 70a41b5aafa4c8095fb6c53117a1f32f57725dc7..a57742ce7896418673b739f2182f2c3c1d07b9b8 100644 (file)
@@ -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.  
index 299414a73253492094c5d3b2cb0f3ae2aab3056f..d7aabbefc6af8dfc596d68fab4f427f505d283f8 100644 (file)
@@ -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))
+
 \f
 /* 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));
index b43cc60f4691154b4d2a9447be591ae58f74e1f9..406a156cce418710348d69f71d1931e42d38abfa 100644 (file)
@@ -2008,9 +2008,10 @@ hack_identifier (value, name)
 
 \f
 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: */
This page took 0.11159 seconds and 5 git commands to generate.