]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
cp-tree.h (num_extra_vtbl_entries): New function.
authorMark Mitchell <mark@codesourcery.com>
Sun, 16 Jan 2000 16:59:44 +0000 (16:59 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 16 Jan 2000 16:59:44 +0000 (16:59 +0000)
* cp-tree.h (num_extra_vtbl_entries): New function.
(size_extra_vtbl_entries): Likewise.
(dfs_vtable_path_unmark): Likewise.
(dfs_vtable_path_unmarked_real_bases_queue_p): Likewise.
(dfs_vtable_path_marked_real_bases_queue_p): Likewise.
* class.c (num_extra_vtbl_entries): New function.
(size_extra_vtbl_entries): Likewise.
(dfs_build_vbase_offset_vtbl_entries): New function.
(build_vbase_offset_vtbl_entries): Likewise.
(build_vtbl_initializer): Use it.
(finish_struct_1): Adjust vtable sizes (using
num_extra_vtbl_entries).
* expr.c (cplus_expand_expr): Assert that the DECL_RTL for a
THUNK_DECL is non-NULL before expanding it.
* init.c (expand_virtual_init): Adjust the vtable pointer by
size_extra_vtbl_entries before storing it.
* search.c (get_shared_vase_if_not_primary): Adjust prototype.
Handle TREE_LIST parameters here, not in the dfs_* functions.
(dfs_unmarked_real_bases_queue_p): Adjust.
(dfs_marked_real_bases_queue_p): Likewise.
(dfs_vtable_path_unmarked_real_bases_queue_p): New function.
(dfs_vtable_path_marked_real_bases_queue_p): New function.
(dfs_vtable_path_unmark): Likewise.

From-SVN: r31439

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/expr.c
gcc/cp/init.c
gcc/cp/search.c

index 372f618a46a776360bc13852dbf174d045db259d..8915d025f3bdf1f2d37a62956aa11d74b4573093 100644 (file)
@@ -1,3 +1,29 @@
+2000-01-15  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.h (num_extra_vtbl_entries): New function.
+       (size_extra_vtbl_entries): Likewise.
+       (dfs_vtable_path_unmark): Likewise.
+       (dfs_vtable_path_unmarked_real_bases_queue_p): Likewise.
+       (dfs_vtable_path_marked_real_bases_queue_p): Likewise.
+       * class.c (num_extra_vtbl_entries): New function.
+       (size_extra_vtbl_entries): Likewise.
+       (dfs_build_vbase_offset_vtbl_entries): New function.
+       (build_vbase_offset_vtbl_entries): Likewise.
+       (build_vtbl_initializer): Use it.
+       (finish_struct_1): Adjust vtable sizes (using
+       num_extra_vtbl_entries).
+       * expr.c (cplus_expand_expr): Assert that the DECL_RTL for a
+       THUNK_DECL is non-NULL before expanding it.
+       * init.c (expand_virtual_init): Adjust the vtable pointer by
+       size_extra_vtbl_entries before storing it.
+       * search.c (get_shared_vase_if_not_primary): Adjust prototype.
+       Handle TREE_LIST parameters here, not in the dfs_* functions.
+       (dfs_unmarked_real_bases_queue_p): Adjust.
+       (dfs_marked_real_bases_queue_p): Likewise.
+       (dfs_vtable_path_unmarked_real_bases_queue_p): New function.
+       (dfs_vtable_path_marked_real_bases_queue_p): New function.
+       (dfs_vtable_path_unmark): Likewise.
+       
 2000-01-14  Mark Mitchell  <mark@codesourcery.com>
 
        * optimize.c (copy_body_r): Clear the operand three of a
index 23cd82c398802033a5e4cf28716ec71715cbf59f..2502b85ec75eef6ed9245ff335e7714f297684f8 100644 (file)
@@ -144,6 +144,8 @@ static void remove_base_field PROTO((tree, tree, tree *));
 static void remove_base_fields PROTO((tree));
 static tree dfs_set_offset_for_shared_vbases PROTO((tree, void *));
 static tree dfs_set_offset_for_unshared_vbases PROTO((tree, void *));
+static tree dfs_build_vbase_offset_vtbl_entries PROTO((tree, void *));
+static tree build_vbase_offset_vtbl_entries PROTO((tree));
 
 /* Variables shared between class.c and call.c.  */
 
@@ -2138,6 +2140,148 @@ duplicate_tag_error (t)
   TYPE_NONCOPIED_PARTS (t) = NULL_TREE;
 }
 
+/* Returns the number of extra entries (at negative indices) required
+   for BINFO's vtable.  */
+
+tree
+num_extra_vtbl_entries (binfo)
+     tree binfo;
+{
+  tree type;
+  int entries;
+
+
+  /* Under the old ABI, there are no entries at negative offsets.  */
+  if (!flag_new_abi)
+    return size_zero_node;
+
+  type = BINFO_TYPE (binfo);
+  entries = 0;
+
+  /* There is an entry for the offset to each virtual base.  */
+  entries += list_length (CLASSTYPE_VBASECLASSES (type));
+
+  return size_int (entries);
+}
+
+/* Returns the offset (in bytes) from the beginning of BINFO's vtable
+   where the vptr should actually point.  */
+
+tree
+size_extra_vtbl_entries (binfo)
+     tree binfo;
+{
+  tree offset;
+
+  offset = size_binop (EXACT_DIV_EXPR,
+                      TYPE_SIZE (vtable_entry_type),
+                      size_int (BITS_PER_UNIT));
+  offset = size_binop (MULT_EXPR, offset, num_extra_vtbl_entries (binfo));
+  return fold (offset);
+}
+
+/* Called from build_vbase_offset_vtbl_entries via dfs_walk.  */
+
+static tree
+dfs_build_vbase_offset_vtbl_entries (binfo, data)
+     tree binfo;
+     void *data;
+{
+  tree list = (tree) data;
+
+  if (TREE_TYPE (list) == binfo)
+    /* The TREE_TYPE of LIST is the base class from which we started
+       walking.  If that BINFO is virtual it's not a virtual baseclass
+       of itself.  */
+    ;
+  else if (TREE_VIA_VIRTUAL (binfo))
+    {
+      tree init;
+
+      init = BINFO_OFFSET (binfo);
+      init = build1 (NOP_EXPR, vtable_entry_type, init);
+      TREE_VALUE (list) = tree_cons (NULL_TREE, init, TREE_VALUE (list));
+    }
+
+  SET_BINFO_VTABLE_PATH_MARKED (binfo);
+  
+  return NULL_TREE;
+}
+
+/* Returns the initializers for the vbase offset entries in the
+   vtable, in reverse order.  */
+
+static tree
+build_vbase_offset_vtbl_entries (binfo)
+     tree binfo;
+{
+  tree type;
+  tree inits;
+  tree init;
+
+  type = BINFO_TYPE (binfo);
+  if (!TYPE_USES_VIRTUAL_BASECLASSES (type))
+    return NULL_TREE;
+
+  inits = NULL_TREE;
+
+  /* Under the new ABI, the vtable contains offsets to all virtual
+     bases.  The ABI specifies different layouts depending on whether
+     or not *all* of the bases of this type are virtual.  */
+  if (CLASSTYPE_N_BASECLASSES (type) 
+      == list_length (CLASSTYPE_VBASECLASSES (type)))
+    {
+      /* In this case, the offsets are allocated from right to left of
+        the declaration order in which the virtual bases appear.  */
+      int i;
+
+      for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
+       {
+         tree vbase = BINFO_BASETYPE (binfo, i);
+         init = BINFO_OFFSET (vbase);
+         init = build1 (NOP_EXPR, vtable_entry_type, init);
+         inits = tree_cons (NULL_TREE, init, inits);
+       }
+    }
+  else
+    {
+      tree list;
+
+      /* While in this case, the offsets are allocated in the reverse
+        order of a depth-first left-to-right traversal of the
+        hierarchy.  We use BINFO_VTABLE_PATH_MARKED because we are
+        ourselves during a dfs_walk, and so BINFO_MARKED is already
+        in use.  */
+      list = build_tree_list (type, NULL_TREE);
+      TREE_TYPE (list) = binfo;
+      dfs_walk (binfo,
+               dfs_build_vbase_offset_vtbl_entries,
+               dfs_vtable_path_unmarked_real_bases_queue_p,
+               list);
+      dfs_walk (binfo,
+               dfs_vtable_path_unmark,
+               dfs_vtable_path_marked_real_bases_queue_p,
+               list);
+      inits = nreverse (TREE_VALUE (list));
+    }
+
+  /* We've now got offsets in the right oder.  However, the offsets
+     we've stored are offsets from the beginning of the complete
+     object, and we need offsets from this BINFO.  */
+  for (init = inits; init; init = TREE_CHAIN (init))
+    {
+      tree exp = TREE_VALUE (init);
+
+      exp = ssize_binop (MINUS_EXPR, exp, BINFO_OFFSET (binfo));
+      exp = build1 (NOP_EXPR, vtable_entry_type, TREE_VALUE (init));
+      exp = fold (exp);
+      TREE_CONSTANT (exp) = 1;
+      TREE_VALUE (init) = exp;
+    }
+
+  return inits;
+}
+
 /* Construct the initializer for BINFOs virtual function table.  */
 
 static tree
@@ -2146,13 +2290,16 @@ build_vtbl_initializer (binfo)
 {
   tree v = BINFO_VIRTUALS (binfo);
   tree inits = NULL_TREE;
+  tree type = BINFO_TYPE (binfo);
+
+  if (flag_new_abi)
+    inits = build_vbase_offset_vtbl_entries (binfo);
 
   /* Process the RTTI stuff at the head of the list.  If we're not
      using vtable thunks, then the RTTI entry is just an ordinary
      function, and we can process it just like the other virtual
      function entries.  */
-  if (!CLASSTYPE_COM_INTERFACE (BINFO_TYPE (binfo))
-      && flag_vtable_thunks)
+  if (!CLASSTYPE_COM_INTERFACE (type) && flag_vtable_thunks)
     {
       tree offset;
       tree init;
@@ -4764,9 +4911,15 @@ finish_struct_1 (t)
   if (has_virtual)
     {
       /* Use size_int so values are memoized in common cases.  */
-      tree itype = build_index_type (size_int (has_virtual));
-      tree atype = build_cplus_array_type (vtable_entry_type, itype);
-
+      tree itype;
+      tree atype;
+
+      itype = size_int (has_virtual);
+      itype = size_binop (PLUS_EXPR, 
+                         itype,
+                         num_extra_vtbl_entries (TYPE_BINFO (t)));
+      atype = build_cplus_array_type (vtable_entry_type, 
+                                     build_index_type (itype));
       layout_type (atype);
 
       /* We may have to grow the vtable.  */
index 8fe8f0b7a2ded790063a67967a577746245b41a4..2101cae0a5f331d6c5c0671f3ad68ca127a7326c 100644 (file)
@@ -3464,6 +3464,8 @@ extern void unreverse_member_declarations       PROTO((tree));
 extern void invalidate_class_lookup_cache       PROTO((void));
 extern void maybe_note_name_used_in_class       PROTO((tree, tree));
 extern void note_name_declared_in_class         PROTO((tree, tree));
+extern tree num_extra_vtbl_entries              PROTO((tree));
+extern tree size_extra_vtbl_entries             PROTO((tree));
 
 /* in cvt.c */
 extern tree convert_to_reference               PROTO((tree, tree, int, int, tree));
@@ -3961,12 +3963,17 @@ extern tree dfs_walk                            PROTO((tree,
                                                       void *));
 extern tree dfs_unmark                          PROTO((tree, void *));
 extern tree dfs_vbase_unmark                    PROTO((tree, void *));
+extern tree dfs_vtable_path_unmark              PROTO((tree, void *));
 extern tree markedp                             PROTO((tree, void *));
 extern tree unmarkedp                           PROTO((tree, void *));
 extern tree dfs_skip_nonprimary_vbases_unmarkedp PROTO((tree, void *));
 extern tree dfs_skip_nonprimary_vbases_markedp  PROTO((tree, void *));
 extern tree dfs_unmarked_real_bases_queue_p     PROTO((tree, void *));
 extern tree dfs_marked_real_bases_queue_p       PROTO((tree, void *));
+extern tree dfs_vtable_path_unmarked_real_bases_queue_p
+                                                PROTO((tree, void *));
+extern tree dfs_vtable_path_marked_real_bases_queue_p
+                                                PROTO((tree, void *));
 extern tree dfs_skip_vbases                     PROTO((tree, void *));
 extern void mark_primary_bases                  PROTO((tree));
 extern tree convert_pointer_to_vbase            PROTO((tree, tree));
index 2ac29f9f2c6379b054df46eee2337df5c528678e..32838f4af8f63e5033875862765949259a26d094 100644 (file)
@@ -1,6 +1,6 @@
 /* Convert language-specific tree expression to rtl instructions,
    for GNU compiler.
-   Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1988, 92-97, 1998, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -131,6 +131,7 @@ cplus_expand_expr (exp, target, tmode, modifier)
       }
 
     case THUNK_DECL:
+      my_friendly_assert (DECL_RTL (exp) != NULL_RTX, 20000115);
       return DECL_RTL (exp);
 
     case THROW_EXPR:
index ed2a3d70a1649861568ea468e5880efbb4268e35..12815e46a9e6f1c48a62f5e38b2df64b05a7b0af 100644 (file)
@@ -648,21 +648,26 @@ expand_virtual_init (binfo, decl)
   tree vtbl, vtbl_ptr;
   tree vtype, vtype_binfo;
 
-  /* This code is crusty.  Should be simple, like:
-     vtbl = BINFO_VTABLE (binfo);
-     */
+  /* Compute the location of the vtable.  */
   vtype = DECL_CONTEXT (TYPE_VFIELD (type));
   vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
   vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (TYPE_VFIELD (type)), binfo));
   assemble_external (vtbl);
   TREE_USED (vtbl) = 1;
   vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
+  /* Under the new ABI, we need to point into the middle of the
+     vtable.  */
+  if (flag_new_abi)
+    vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, 
+                 size_extra_vtbl_entries (binfo));
+
+  /* Compute the location of the vtpr.  */
   decl = convert_pointer_to_real (vtype_binfo, decl);
   vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);
   if (vtbl_ptr == error_mark_node)
     return;
 
-  /* Have to convert VTBL since array sizes may be different.  */
+  /* Assign the vtable to the vptr.  */
   vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
   finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl));
 }
index 1d6efed889d813cae0010c5c99eb402c897e0f23..697bf8b214e59fda0410519e4f291b0501e31d40 100644 (file)
@@ -150,7 +150,7 @@ static void setup_class_bindings PROTO ((tree, int));
 static int template_self_reference_p PROTO ((tree, tree));
 static void fixup_all_virtual_upcast_offsets PROTO ((tree, tree));
 static tree dfs_mark_primary_bases PROTO((tree, void *));
-static tree get_shared_vbase_if_not_primary PROTO((tree, tree));
+static tree get_shared_vbase_if_not_primary PROTO((tree, void *));
 static tree dfs_find_vbase_instance PROTO((tree, void *));
 
 /* Allocate a level of searching.  */
@@ -2240,12 +2240,17 @@ mark_primary_bases (type)
    either a non-virtual base or a primary virtual base.  */
 
 static tree
-get_shared_vbase_if_not_primary (binfo, type)
+get_shared_vbase_if_not_primary (binfo, data)
      tree binfo;
-     tree type;
+     void *data;
 {
   if (TREE_VIA_VIRTUAL (binfo) && !BINFO_PRIMARY_MARKED_P (binfo))
     {
+      tree type = (tree) data;
+
+      if (TREE_CODE (type) == TREE_LIST)
+       type = TREE_PURPOSE (type);
+
       /* This is a non-primary virtual base.  If there is no primary
         version, get the shared version.  */
       binfo = BINFO_FOR_VBASE (BINFO_TYPE (binfo), type);
@@ -2271,11 +2276,7 @@ dfs_unmarked_real_bases_queue_p (binfo, data)
      tree binfo;
      void *data;
 {
-  tree type = (tree) data;
-
-  if (TREE_CODE (type) == TREE_LIST)
-    type = TREE_PURPOSE (type);
-  binfo = get_shared_vbase_if_not_primary (binfo, type); 
+  binfo = get_shared_vbase_if_not_primary (binfo, data); 
   return binfo ? unmarkedp (binfo, NULL) : NULL_TREE;
 }
 
@@ -2287,14 +2288,34 @@ dfs_marked_real_bases_queue_p (binfo, data)
      tree binfo;
      void *data;
 {
-  tree type = (tree) data;
-
-  if (TREE_CODE (type) == TREE_LIST)
-    type = TREE_PURPOSE (type);
-  binfo = get_shared_vbase_if_not_primary (binfo, type);
+  binfo = get_shared_vbase_if_not_primary (binfo, data); 
   return binfo ? markedp (binfo, NULL) : NULL_TREE;
 }
 
+/* Like dfs_unmarked_real_bases_queue_p but walks only into things
+   that are not BINFO_VTABLE_PATH_MARKED.  */
+
+tree
+dfs_vtable_path_unmarked_real_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
+{
+  binfo = get_shared_vbase_if_not_primary (binfo, data); 
+  return binfo ? unmarked_vtable_pathp (binfo, NULL): NULL_TREE;
+}
+
+/* Like dfs_unmarked_real_bases_queue_p but walks only into things
+   that are BINFO_VTABLE_PATH_MARKED.  */
+
+tree
+dfs_vtable_path_marked_real_bases_queue_p (binfo, data)
+     tree binfo;
+     void *data;
+{
+  binfo = get_shared_vbase_if_not_primary (binfo, data); 
+  return binfo ? marked_vtable_pathp (binfo, NULL): NULL_TREE;
+}
+
 /* A queue function that skips all virtual bases (and their 
    bases).  */
 
@@ -2546,15 +2567,22 @@ dfs_vbase_unmark (binfo, data)
   return dfs_unmark (binfo, data);
 }
 
+/* Clear BINFO_VTABLE_PATH_MARKED.  */
+
+tree
+dfs_vtable_path_unmark (binfo, data)
+     tree binfo;
+     void *data ATTRIBUTE_UNUSED;
+{ 
+  CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); 
+  return NULL_TREE;
+}
+
 #if 0
 static void
 dfs_mark_vtable_path (binfo) tree binfo;
 { SET_BINFO_VTABLE_PATH_MARKED (binfo); }
 
-static void
-dfs_unmark_vtable_path (binfo) tree binfo;
-{ CLEAR_BINFO_VTABLE_PATH_MARKED (binfo); }
-
 static void
 dfs_mark_new_vtable (binfo) tree binfo;
 { SET_BINFO_NEW_VTABLE_MARKED (binfo); }