This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

C++ PATCH: Generate VTTs



This patch causes the compiler to generate VTTs under the new ABI.
These are the things that will be used in the new ABI to avoid the
infamous "vtable-thunks bug".  That work isn't yet complete -- now we
have the data structures but the constructors and destructors haven't
been modified to take advantage of them.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-05-21  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (SET_BINFO_NEW_VTABLE_MARKED): Add sanity checks.
	(VTT_NAME_PREFIX): New macro.
	(CTOR_VTBL_NAME_PREFIX): Likewise.
	(get_ctor_vtbl_name): New function.
	* class.c (get_vtable_name): Simplify.
	(get_vtt_name): New function.
	(get_vtable_decl): Don't set IDENTIFIER_GLOBAL_VALUE.
	(dfs_mark_primary_bases): Update the CLASSTYPE_VBASECLASSES list
	when a virtual base becomes primary.
	(finish_struct_1): Set CLASSTYPE_VFIELDS a little earlier.  Build
	VTTs.
	(finish_vtbls): Adjust calls to accumulate_vtbl_inits to pass in
	additional parameters.
	(dfs_finish_vtbls): Don't clear BINFO_NEW_VTABLE_MARKED.
	(initialize_array): New function.
	(build_vtt): Likewise.
	(build_vtt_inits): Likewise.
	(dfs_build_vtt_inits): Likewise.
	(dfs_fixup_binfo_vtbls): Likewise.
	(build_ctor_vtbl_group): Likewise.
	(initialize_vtable): Use initialize_array.
	(accumulate_vtbl_inits): Reimplement to handle construction
	vtables.
	(dfs_accumulate_vtbl_inits): Likewise.
	(bulid_vtbl_initializer): Adjust parameter name.
	* method.c (build_typename_overload): Remove #if 0'd code.
	(get_ctor_vtbl_name): New function.
	* search.c (dfs_walk_real): Use BINFO_N_BASETYPES.
	(init_vbase_pointers): Don't mess with the TREE_CHAIN of a binfo.

Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.303
diff -c -p -r1.303 class.c
*** class.c	2000/05/19 23:06:54	1.303
--- class.c	2000/05/22 01:07:01
*************** static tree get_basefndecls PARAMS ((tre
*** 93,99 ****
  static int build_primary_vtable PARAMS ((tree, tree));
  static int build_secondary_vtable PARAMS ((tree, tree));
  static tree dfs_finish_vtbls PARAMS ((tree, void *));
! static tree dfs_accumulate_vtbl_inits PARAMS ((tree, void *));
  static void finish_vtbls PARAMS ((tree));
  static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
  static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
--- 93,100 ----
  static int build_primary_vtable PARAMS ((tree, tree));
  static int build_secondary_vtable PARAMS ((tree, tree));
  static tree dfs_finish_vtbls PARAMS ((tree, void *));
! static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
! 					       tree));
  static void finish_vtbls PARAMS ((tree));
  static void modify_vtable_entry PARAMS ((tree, tree, tree, tree, tree *));
  static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
*************** static void dump_class_hierarchy_r PARAM
*** 157,162 ****
--- 158,164 ----
  extern void dump_class_hierarchy PARAMS ((tree));
  static tree build_vtable PARAMS ((tree, tree, tree));
  static void initialize_vtable PARAMS ((tree, tree));
+ static void initialize_array PARAMS ((tree, tree));
  static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
  						   tree, tree,
  						   varray_type));
*************** static tree dfs_search_base_offsets PARA
*** 166,172 ****
  static int layout_conflict_p PARAMS ((tree, varray_type));
  static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
  static void layout_empty_base PARAMS ((tree, tree, varray_type));
! static void accumulate_vtbl_inits PARAMS ((tree, tree));
  static void set_vindex PARAMS ((tree, tree, int *));
  static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
  static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, 
--- 168,174 ----
  static int layout_conflict_p PARAMS ((tree, varray_type));
  static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
  static void layout_empty_base PARAMS ((tree, tree, varray_type));
! static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
  static void set_vindex PARAMS ((tree, tree, int *));
  static tree build_rtti_vtbl_entries PARAMS ((tree, tree));
  static void build_vcall_and_vbase_vtbl_entries PARAMS ((tree, 
*************** static void clone_constructors_and_destr
*** 177,182 ****
--- 179,189 ----
  static tree build_clone PARAMS ((tree, tree));
  static void update_vtable_entry_for_fn PARAMS ((tree, tree, tree, tree *));
  static tree copy_virtuals PARAMS ((tree));
+ static void build_ctor_vtbl_group PARAMS ((tree, tree));
+ static void build_vtt PARAMS ((tree));
+ static tree *build_vtt_inits PARAMS ((tree, tree, tree *));
+ static tree dfs_build_vtt_inits PARAMS ((tree, void *));
+ static tree dfs_fixup_binfo_vtbls PARAMS ((tree, void *));
  
  /* Variables shared between class.c and call.c.  */
  
*************** static tree
*** 621,642 ****
  get_vtable_name (type)
       tree type;
  {
!   tree type_id = build_typename_overload (type);
!   char *buf = (char *) alloca (strlen (VTABLE_NAME_PREFIX)
! 			       + IDENTIFIER_LENGTH (type_id) + 2);
!   const char *ptr = IDENTIFIER_POINTER (type_id);
!   int i;
!   for (i = 0; ptr[i] == OPERATOR_TYPENAME_FORMAT[i]; i++) ;
! #if 0
!   /* We don't take off the numbers; build_secondary_vtable uses the
!      DECL_ASSEMBLER_NAME for the type, which includes the number
!      in `3foo'.  If we were to pull them off here, we'd end up with
!      something like `_vt.foo.3bar', instead of a uniform definition.  */
!   while (ptr[i] >= '0' && ptr[i] <= '9')
!     i += 1;
! #endif
!   sprintf (buf, "%s%s", VTABLE_NAME_PREFIX, ptr+i);
!   return get_identifier (buf);
  }
  
  /* Return the offset to the main vtable for a given base BINFO.  */
--- 628,646 ----
  get_vtable_name (type)
       tree type;
  {
!   return build_overload_with_type (get_identifier (VTABLE_NAME_PREFIX),
! 				   type);
! }
! 
! /* Return an IDENTIFIER_NODE for the name of the virtual table table
!    for TYPE.  */
! 
! static tree
! get_vtt_name (type)
!      tree type;
! {
!   return build_overload_with_type (get_identifier (VTT_NAME_PREFIX),
! 				   type);
  }
  
  /* Return the offset to the main vtable for a given base BINFO.  */
*************** get_vtable_decl (type, complete)
*** 727,733 ****
    
    decl = build_vtable (type, name, void_type_node);
    decl = pushdecl_top_level (decl);
!   SET_IDENTIFIER_GLOBAL_VALUE (name, decl);
    
    /* At one time the vtable info was grabbed 2 words at a time.  This
       fails on sparc unless you have 8-byte alignment.  (tiemann) */
--- 731,738 ----
    
    decl = build_vtable (type, name, void_type_node);
    decl = pushdecl_top_level (decl);
!   my_friendly_assert (IDENTIFIER_GLOBAL_VALUE (name) == decl,
! 		      20000517);
    
    /* At one time the vtable info was grabbed 2 words at a time.  This
       fails on sparc unless you have 8-byte alignment.  (tiemann) */
*************** dfs_mark_primary_bases (binfo, data)
*** 1692,1706 ****
    else
      {
        tree shared_binfo;
  
!       shared_binfo 
! 	= binfo_for_vbase (BINFO_TYPE (base_binfo), (tree) data);
  
        /* If this virtual base is not already primary somewhere else in
  	 the hiearchy, then we'll be using this copy.  */
        if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
  	{
! 	  BINFO_VBASE_PRIMARY_P (shared_binfo) = 1;
  	  BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
  	}
      }
--- 1697,1719 ----
    else
      {
        tree shared_binfo;
+       tree type;
  
!       type = (tree) data;
!       shared_binfo = binfo_for_vbase (BINFO_TYPE (base_binfo), type);
  
        /* If this virtual base is not already primary somewhere else in
  	 the hiearchy, then we'll be using this copy.  */
        if (!BINFO_VBASE_PRIMARY_P (shared_binfo))
  	{
! 	  /* Make sure the CLASSTYPE_VBASECLASSES list contains the
! 	     primary copy; it's the one that really exists.  */
! 	  if (base_binfo != shared_binfo)
! 	    TREE_VALUE (purpose_member (BINFO_TYPE (base_binfo),
! 					CLASSTYPE_VBASECLASSES (type)))
! 	      = base_binfo;
! 
! 	  BINFO_VBASE_PRIMARY_P (base_binfo) = 1;
  	  BINFO_PRIMARY_MARKED_P (base_binfo) = 1;
  	}
      }
*************** finish_struct_1 (t)
*** 4900,4905 ****
--- 4913,4924 ----
    overridden_virtuals 
      = modify_all_vtables (t, &vfuns, nreverse (overridden_virtuals));
  
+   /* If we created a new vtbl pointer for this class, add it to the
+      list.  */
+   if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
+     CLASSTYPE_VFIELDS (t) 
+       = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
+ 
    /* If necessary, create the primary vtable for this class.  */
    if (new_virtuals
        || overridden_virtuals
*************** finish_struct_1 (t)
*** 4962,4973 ****
  	= chainon (TYPE_BINFO_VIRTUALS (t), overridden_virtuals);
      }
  
-   /* If we created a new vtbl pointer for this class, add it to the
-      list.  */
-   if (TYPE_VFIELD (t) && !CLASSTYPE_HAS_PRIMARY_BASE_P (t))
-     CLASSTYPE_VFIELDS (t) 
-       = chainon (CLASSTYPE_VFIELDS (t), build_tree_list (NULL_TREE, t));
- 
    finish_struct_bits (t);
  
    /* Complete the rtl for any static member objects of the type we're
--- 4981,4986 ----
*************** finish_struct_1 (t)
*** 5020,5025 ****
--- 5033,5040 ----
    /* Make the rtl for any new vtables we have created, and unmark
       the base types we marked.  */
    finish_vtbls (t);
+   /* Build the VTT for T.  */
+   build_vtt (t);
  
    if (TYPE_VFIELD (t))
      {
*************** finish_vtbls (t)
*** 6373,6388 ****
  	 first, followed by the non-virtual secondary vtables in
  	 inheritance graph order.  */
        list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
!       TREE_TYPE (list) = t;
!       accumulate_vtbl_inits (TYPE_BINFO (t), list);
        /* Then come the virtual bases, also in inheritance graph
  	 order.  */
        for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
  	{
  	  if (!TREE_VIA_VIRTUAL (vbase))
  	    continue;
! 	  accumulate_vtbl_inits (binfo_for_vbase (BINFO_TYPE (vbase), t),
! 				 list);
  	}
  
        if (TYPE_BINFO_VTABLE (t))
--- 6388,6403 ----
  	 first, followed by the non-virtual secondary vtables in
  	 inheritance graph order.  */
        list = build_tree_list (TYPE_BINFO_VTABLE (t), NULL_TREE);
!       accumulate_vtbl_inits (TYPE_BINFO (t), TYPE_BINFO (t),
! 			     TYPE_BINFO (t), t, list);
        /* Then come the virtual bases, also in inheritance graph
  	 order.  */
        for (vbase = TYPE_BINFO (t); vbase; vbase = TREE_CHAIN (vbase))
  	{
  	  if (!TREE_VIA_VIRTUAL (vbase))
  	    continue;
! 
! 	  accumulate_vtbl_inits (vbase, vbase, TYPE_BINFO (t), t, list);
  	}
  
        if (TYPE_BINFO_VTABLE (t))
*************** dfs_finish_vtbls (binfo, data)
*** 6406,6419 ****
  {
    tree t = (tree) data;
  
!   if (!BINFO_PRIMARY_MARKED_P (binfo)
!       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
!       && BINFO_NEW_VTABLE_MARKED (binfo, t))
      initialize_vtable (binfo, 
  		       build_vtbl_initializer (binfo, binfo, t, 
  					       TYPE_BINFO (t), NULL));
  
-   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
    SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
--- 6421,6431 ----
  {
    tree t = (tree) data;
  
!   if (BINFO_NEW_VTABLE_MARKED (binfo, t))
      initialize_vtable (binfo, 
  		       build_vtbl_initializer (binfo, binfo, t, 
  					       TYPE_BINFO (t), NULL));
  
    SET_BINFO_MARKED (binfo);
  
    return NULL_TREE;
*************** initialize_vtable (binfo, inits)
*** 6426,6521 ****
       tree binfo;
       tree inits;
  {
-   tree context;
    tree decl;
  
    layout_vtable_decl (binfo, list_length (inits));
    decl = get_vtbl_decl_for_binfo (binfo);
    context = DECL_CONTEXT (decl);
!   DECL_CONTEXT (decl) = 0;
    DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
    cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
    DECL_CONTEXT (decl) = context;
  }
  
! /* Add the vtbl initializers for BINFO (and its non-primary,
!    non-virtual bases) to the list of INITS.  */
  
  static void
! accumulate_vtbl_inits (binfo, inits)
       tree binfo;
!      tree inits;
  {
!   /* Walk the BINFO and its bases.  We walk in preorder so that as we
!      initialize each vtable we can figure out at what offset the
!      secondary vtable lies from the primary vtable.  */
    dfs_walk_real (binfo,
! 		 dfs_accumulate_vtbl_inits,
  		 NULL,
! 		 dfs_skip_vbases,
! 		 inits);
  }
  
! /* Called from finish_vtbls via dfs_walk when using the new ABI.
!    Accumulates the vtable initializers for all of the vtables into
!    TREE_VALUE (DATA).  */
  
  static tree
! dfs_accumulate_vtbl_inits (binfo, data)
       tree binfo;
       void *data;
  {
!   tree l;
    tree t;
  
    l = (tree) data;
!   t = TREE_TYPE (l);
  
!   if (!BINFO_PRIMARY_MARKED_P (binfo)
!       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))
!       && BINFO_NEW_VTABLE_MARKED (binfo, t))
      {
!       tree inits;
        tree vtbl;
        tree index;
        int non_fn_entries;
  
        /* Compute the initializer for this vtable.  */
!       inits = build_vtbl_initializer (binfo, binfo, t, TYPE_BINFO (t), 
  				      &non_fn_entries);
  
!       /* Set BINFO_VTABLE to the address where the VPTR should point.  */
        vtbl = TREE_PURPOSE (l);
        vtbl = build1 (ADDR_EXPR, 
! 		     build_pointer_type (TREE_TYPE (vtbl)),
  		     vtbl);
        index = size_binop (PLUS_EXPR,
  			  size_int (non_fn_entries),
  			  size_int (list_length (TREE_VALUE (l))));
!       BINFO_VTABLE (binfo)
! 	= build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl,
! 		 size_binop (MULT_EXPR,
! 			     TYPE_SIZE_UNIT (TREE_TYPE (vtbl)),
! 			     index));
! 
!       /* Add the initializers for this vtable to the initializers for
! 	 the other vtables we've already got.  */
!       TREE_VALUE (l) = chainon (TREE_VALUE (l), inits);
      }
  
!   CLEAR_BINFO_NEW_VTABLE_MARKED (binfo, t);
! 
!   return NULL_TREE;
  }
  
  /* Construct the initializer for BINFOs virtual function table.  BINFO
     is part of the hierarchy dominated by T.  If we're building a
!    construction vtable, the ORIGINAL_BINFO is the binfo we should use
!    to find the actual function pointers to put in the vtable.
!    Otherwise, ORIGINAL_BINFO should be the same as BINFO.  The
!    RTTI_DOMINATOR is the BINFO that should be indicated by the RTTI
!    information in the vtable; it will be a base class of T, rather
!    than T itself, if we are building a construction vtable.
  
     The value returned is a TREE_LIST suitable for wrapping in a
     CONSTRUCTOR to use as the DECL_INITIAL for a vtable.  If
--- 6438,6809 ----
       tree binfo;
       tree inits;
  {
    tree decl;
  
    layout_vtable_decl (binfo, list_length (inits));
    decl = get_vtbl_decl_for_binfo (binfo);
+   initialize_array (decl, inits);
+ }
+ 
+ /* Initialize DECL (a declaration for a namespace-scope array) with
+    the INITS.  */
+ 
+ static void
+ initialize_array (decl, inits)
+   tree decl;
+   tree inits;
+ {
+   tree context;
+ 
    context = DECL_CONTEXT (decl);
!   DECL_CONTEXT (decl) = NULL_TREE;
    DECL_INITIAL (decl) = build_nt (CONSTRUCTOR, NULL_TREE, inits);
    cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0);
    DECL_CONTEXT (decl) = context;
  }
  
! /* Build the VTT (virtual table table) for T.  */
  
  static void
! build_vtt (t)
!      tree t;
! {
!   tree inits;
!   tree type;
!   tree vtt;
! 
!   /* Under the old ABI, we don't use VTTs.  */
!   if (!flag_new_abi)
!     return;
! 
!   /* Build up the initializers for the VTT.  */
!   inits = NULL_TREE;
!   build_vtt_inits (TYPE_BINFO (t), t, &inits);
! 
!   /* If we didn't need a VTT, we're done.  */
!   if (!inits)
!     return;
! 
!   /* Figure out the type of the VTT.  */
!   type = build_index_type (size_int (list_length (inits)));
!   type = build_cplus_array_type (const_ptr_type_node, type);
! 				 
!   /* Now, build the VTT object itself.  */
!   vtt = build_vtable (t, get_vtt_name (t), type);
!   pushdecl_top_level (vtt);
!   initialize_array (vtt, inits);
! }
! 
! /* Recursively build the VTT-initializer for BINFO (which is in the
!    hierarchy dominated by T).  INITS points to the end of the
!    initializer list to date.  */
! 
! static tree *
! build_vtt_inits (binfo, t, inits)
       tree binfo;
!      tree t;
!      tree *inits;
  {
!   int i;
!   tree b;
!   tree init;
!   tree secondary_vptrs;
!   int ctor_vtbl_p;
! 
!   /* We only need VTTs for subobjects with virtual bases.  */
!   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
!     return inits;
! 
!   /* We need to use a construction vtable if this is not the primary
!      VTT.  */
!   ctor_vtbl_p = !same_type_p (TREE_TYPE (binfo), t);
!   if (ctor_vtbl_p)
!     build_ctor_vtbl_group (binfo, t);
! 
!   /* Add the address of the primary vtable for the complete object.  */
!   init = BINFO_VTABLE (binfo);
!   if (TREE_CODE (init) == TREE_LIST)
!     init = TREE_PURPOSE (init);
!   *inits = build_tree_list (NULL_TREE, init);
!   inits = &TREE_CHAIN (*inits);
! 
!   /* Recursively add the secondary VTTs for non-virtual bases.  */
!   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
!     {
!       b = BINFO_BASETYPE (binfo, i);
!       if (!TREE_VIA_VIRTUAL (b))
! 	inits = build_vtt_inits (BINFO_BASETYPE (binfo, i), t, inits);
!     }
! 
!   /* Add secondary virtual pointers for all subobjects of BINFO with
!      either virtual bases or virtual functions overridden along a
!      virtual path between the declaration and D, except subobjects
!      that are non-virtual primary bases.  */
!   secondary_vptrs = build_tree_list (BINFO_TYPE (binfo), NULL_TREE);
    dfs_walk_real (binfo,
! 		 dfs_build_vtt_inits,
  		 NULL,
! 		 dfs_unmarked_real_bases_queue_p,
! 		 secondary_vptrs);
!   dfs_walk (binfo, dfs_fixup_binfo_vtbls, dfs_marked_real_bases_queue_p,
! 	    BINFO_TYPE (binfo));
! 
!   /* The secondary vptrs come back in reverse order.  After we reverse
!      them, and add the INITS, the last init will be the first element
!      of the chain.  */
!   secondary_vptrs = TREE_VALUE (secondary_vptrs);
!   if (secondary_vptrs)
!     {
!       *inits = nreverse (secondary_vptrs);
!       inits = &TREE_CHAIN (secondary_vptrs);
!       my_friendly_assert (*inits == NULL_TREE, 20000517);
!     }
! 
!   /* Add the secondary VTTs for virtual bases.  */
!   for (b = TYPE_BINFO (BINFO_TYPE (binfo)); b; b = TREE_CHAIN (b))
!     {
!       tree vbase;
! 
!       if (!TREE_VIA_VIRTUAL (b))
! 	continue;
! 
!       vbase = binfo_for_vbase (BINFO_TYPE (b), t);
!       inits = build_vtt_inits (vbase, t, inits);
!     }
! 
!   return inits;
  }
  
! /* Called from build_vtt_inits via dfs_walk.  */
  
  static tree
! dfs_build_vtt_inits (binfo, data)
       tree binfo;
       void *data;
  {
!   tree l; 
    tree t;
+   tree init;
  
    l = (tree) data;
!   t = TREE_PURPOSE (l);
! 
!   SET_BINFO_MARKED (binfo);
  
!   /* We don't care about bases that don't have vtables.  */
!   if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
!     return NULL_TREE;
! 
!   /* We're only interested in proper subobjects of T.  */
!   if (same_type_p (BINFO_TYPE (binfo), t))
!     return NULL_TREE;
! 
!   /* We're not interested in non-virtual primary bases.  */
!   if (!TREE_VIA_VIRTUAL (binfo) && BINFO_PRIMARY_MARKED_P (binfo))
!     return NULL_TREE;
! 
!   /* If BINFO doesn't have virtual bases, then we have to look to see
!      whether or not any virtual functions were overidden along a
!      virtual path between the declaration and T.  */
!   if (!TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
!     /* FIXME: Implement this.  */
!     ;
! 
!   /* Add the initializer for this secondary vptr.  */
!   init = BINFO_VTABLE (binfo);
!   if (TREE_CODE (init) == TREE_LIST)
!     init = TREE_PURPOSE (init);
! 
!   TREE_VALUE (l) = tree_cons (NULL_TREE, init, TREE_VALUE (l));
!   
!   return NULL_TREE;
! }
! 
! /* Called from build_vtt_inits via dfs_walk.  */
! 
! static tree
! dfs_fixup_binfo_vtbls (binfo, data)
!      tree binfo;
!      void *data ATTRIBUTE_UNUSED;
! {
!   CLEAR_BINFO_MARKED (binfo);
! 
!   /* We don't care about bases that don't have vtables.  */
!   if (!TYPE_VFIELD (BINFO_TYPE (binfo)))
!     return NULL_TREE;
! 
!   /* If we scribbled the construction vtable vptr into BINFO, clear it
!      out now.  */
!   if (TREE_CODE (BINFO_VTABLE (binfo)) == TREE_LIST)
!     BINFO_VTABLE (binfo) = TREE_VALUE (BINFO_VTABLE (binfo));
! 
!   return NULL_TREE;
! }
! 
! /* Build the construction vtable group for BINFO which is in the
!    hierarchy dominated by T.  */
! 
! static void
! build_ctor_vtbl_group (binfo, t)
!      tree binfo;
!      tree t;
! {
!   tree list;
!   tree type;
!   tree vtbl;
!   tree inits;
!   tree id;
! 
!   /* See if we've already create this construction vtable group.  */
!   id = get_ctor_vtbl_name (t, binfo);
!   if (IDENTIFIER_GLOBAL_VALUE (id))
!     return;
! 
!   /* Build a version of VTBL (with the wrong type) for use in
!      constructing the addresses of secondary vtables in the
!      construction vtable group.  */
!   vtbl = build_vtable (BINFO_TYPE (binfo), id, vtable_entry_type);
!   list = build_tree_list (vtbl, NULL_TREE);
!   accumulate_vtbl_inits (binfo, TYPE_BINFO (TREE_TYPE (binfo)),
! 			 binfo, t, list);
! 
!   /* Figure out the type of the construction vtable.  */
!   type = build_index_type (size_int (list_length (inits)));
!   type = build_cplus_array_type (vtable_entry_type, type);
!   TREE_TYPE (vtbl) = type;
! 
!   /* Initialize the construction vtable.  */
!   pushdecl_top_level (vtbl);
!   initialize_array (vtbl, inits);
! }
! 
! /* Add the vtbl initializers for BINFO (and its non-primary,
!    non-virtual bases) to the list of INITS.  BINFO is in the hierarchy
!    dominated by T.  ORIG_BINFO must have the same type as BINFO, but
!    may be different from BINFO if we are building a construction
!    vtable.  RTTI_BINFO gives the object that should be used as the
!    complete object for BINFO.  */
! 
! static void
! accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, inits)
!      tree binfo;
!      tree orig_binfo;
!      tree rtti_binfo;
!      tree t;
!      tree inits;
! {
!   int i;
!   int ctor_vtbl_p;
! 
!   my_friendly_assert (same_type_p (BINFO_TYPE (binfo),
! 				   BINFO_TYPE (orig_binfo)),
! 		      20000517);
! 
!   /* This is a construction vtable if the RTTI type is not the most
!      derived type in the hierarchy.  */
!   ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
! 
!   /* If we're building a construction vtable, we're not interested in
!      subobjects that don't require construction vtables.  */
!   if (ctor_vtbl_p 
!       && !TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))
!     return;
! 
!   /* Build the initializers for the BINFO-in-T vtable.  */
!   TREE_VALUE (inits) 
!     = chainon (TREE_VALUE (inits),
! 	       dfs_accumulate_vtbl_inits (binfo, orig_binfo,
! 					  rtti_binfo, t, inits));
! 		      
!   /* Walk the BINFO and its bases.  We walk in preorder so that as we
!      initialize each vtable we can figure out at what offset the
!      secondary vtable lies from the primary vtable.  We can't use
!      dfs_walk here because we need to iterate through bases of BINFO
!      and RTTI_BINFO simultaneously.  */
!   for (i = 0; i < BINFO_N_BASETYPES (binfo); ++i)
      {
!       tree base_binfo;
! 
!       base_binfo = BINFO_BASETYPE (binfo, i);
!       /* Skip virtual bases.  */
!       if (TREE_VIA_VIRTUAL (base_binfo))
! 	continue;
!       accumulate_vtbl_inits (base_binfo,
! 			     BINFO_BASETYPE (orig_binfo, i),
! 			     rtti_binfo,
! 			     t,
! 			     inits);
!     }
! }
! 
! /* Called from finish_vtbls via dfs_walk when using the new ABI.
!    Accumulates the vtable initializers for all of the vtables into
!    TREE_VALUE (DATA).  Returns the initializers for the BINFO vtable.  */
! 
! static tree
! dfs_accumulate_vtbl_inits (binfo, orig_binfo, rtti_binfo, t, l)
!      tree binfo;
!      tree orig_binfo;
!      tree rtti_binfo;
!      tree t;
!      tree l;
! {
!   tree inits = NULL_TREE;
!   int ctor_vtbl_p;
! 
!   /* This is a construction vtable if the RTTI type is not the most
!      derived type in the hierarchy.  */
!   ctor_vtbl_p = !same_type_p (BINFO_TYPE (rtti_binfo), t);
! 
!   if (BINFO_NEW_VTABLE_MARKED (binfo, t)
!       /* We need a new vtable, even for a primary base, when we're
! 	 building a construction vtable.  */
!       || (ctor_vtbl_p && orig_binfo == rtti_binfo))
!     {
        tree vtbl;
        tree index;
        int non_fn_entries;
  
        /* Compute the initializer for this vtable.  */
!       inits = build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo,
  				      &non_fn_entries);
  
!       /* Figure out the position to which the VPTR should point.  */
        vtbl = TREE_PURPOSE (l);
        vtbl = build1 (ADDR_EXPR, 
! 		     vtbl_ptr_type_node,
  		     vtbl);
        index = size_binop (PLUS_EXPR,
  			  size_int (non_fn_entries),
  			  size_int (list_length (TREE_VALUE (l))));
!       index = size_binop (MULT_EXPR,
! 			  TYPE_SIZE_UNIT (vtable_entry_type),
! 			  index);
!       vtbl = build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, index);
!       TREE_CONSTANT (vtbl) = 1;
! 
!       /* For an ordinary vtable, set BINFO_VTABLE.  */
!       if (!ctor_vtbl_p)
! 	BINFO_VTABLE (binfo) = vtbl;
!       /* For a construction vtable, we can't overwrite BINFO_VTABLE.
! 	 So, we make a TREE_LIST.  Later, dfs_fixup_binfo_vtbls will
! 	 straighten this out.  */
!       else
! 	BINFO_VTABLE (binfo) = build_tree_list (vtbl,
! 						BINFO_VTABLE (binfo));
      }
  
!   return inits;
  }
  
  /* Construct the initializer for BINFOs virtual function table.  BINFO
     is part of the hierarchy dominated by T.  If we're building a
!    construction vtable, the ORIG_BINFO is the binfo we should use to
!    find the actual function pointers to put in the vtable.  Otherwise,
!    ORIG_BINFO should be the same as BINFO.  The RTTI_DOMINATOR is the
!    BINFO that should be indicated by the RTTI information in the
!    vtable; it will be a base class of T, rather than T itself, if we
!    are building a construction vtable.
  
     The value returned is a TREE_LIST suitable for wrapping in a
     CONSTRUCTOR to use as the DECL_INITIAL for a vtable.  If
*************** dfs_accumulate_vtbl_inits (binfo, data)
*** 6523,6532 ****
     number of non-function entries in the vtable.  */
  
  static tree
! build_vtbl_initializer (binfo, original_binfo, t, rtti_binfo,
! 			non_fn_entries_p)
       tree binfo;
!      tree original_binfo;
       tree t;
       tree rtti_binfo;
       int *non_fn_entries_p;
--- 6811,6819 ----
     number of non-function entries in the vtable.  */
  
  static tree
! build_vtbl_initializer (binfo, orig_binfo, t, rtti_binfo, non_fn_entries_p)
       tree binfo;
!      tree orig_binfo;
       tree t;
       tree rtti_binfo;
       int *non_fn_entries_p;
*************** build_vtbl_initializer (binfo, original_
*** 6563,6569 ****
    /* Go through all the ordinary virtual functions, building up
       initializers.  */
    vfun_inits = NULL_TREE;
!   for (v = BINFO_VIRTUALS (original_binfo); v; v = TREE_CHAIN (v))
      {
        tree delta;
        tree vcall_index;
--- 6850,6856 ----
    /* Go through all the ordinary virtual functions, building up
       initializers.  */
    vfun_inits = NULL_TREE;
!   for (v = BINFO_VIRTUALS (orig_binfo); v; v = TREE_CHAIN (v))
      {
        tree delta;
        tree vcall_index;
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.456
diff -c -p -r1.456 cp-tree.h
*** cp-tree.h	2000/05/21 17:01:21	1.456
--- cp-tree.h	2000/05/22 01:07:05
*************** struct lang_type
*** 1597,1603 ****
  /* A chain of BINFOs for the direct and indirect virtual base classes
     that this type uses in a post-order depth-first left-to-right
     order.  (In other words, these bases appear in the order that they
!    should be initialized.)  */
  #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
  
  /* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
--- 1597,1607 ----
  /* A chain of BINFOs for the direct and indirect virtual base classes
     that this type uses in a post-order depth-first left-to-right
     order.  (In other words, these bases appear in the order that they
!    should be initialized.)  If a virtual base is primary, then the
!    primary copy will appear on this list.  Thus, the BINFOs on this
!    list are all "real"; they are the same BINFOs that will be
!    encountered when using dfs_unmarked_real_bases_queue_p and related
!    functions.  */
  #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
  
  /* For a non-virtual BINFO, the BINFO itself; for a virtual BINFO, the
*************** struct lang_type
*** 1721,1728 ****
     B is part of the hierarchy dominated by C.  */
  #define BINFO_NEW_VTABLE_MARKED(B, C) \
    (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
! #define SET_BINFO_NEW_VTABLE_MARKED(B, C) \
!   (BINFO_NEW_VTABLE_MARKED (B, C) = 1)
  #define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
    (BINFO_NEW_VTABLE_MARKED (B, C) = 0)
  
--- 1725,1739 ----
     B is part of the hierarchy dominated by C.  */
  #define BINFO_NEW_VTABLE_MARKED(B, C) \
    (TREE_LANG_FLAG_4 (CANONICAL_BINFO (B, C)))
! 
! /* Any subobject that needs a new vtable must have a vptr and must not
!    be a primary base (since it would then use the vtable from a
!    derived class.)  */
! #define SET_BINFO_NEW_VTABLE_MARKED(B, C)		       		 \
!   (BINFO_NEW_VTABLE_MARKED (B, C) = 1,					 \
!    my_friendly_assert (!BINFO_PRIMARY_MARKED_P (B), 20000517),		 \
!    my_friendly_assert (CLASSTYPE_VFIELDS (BINFO_TYPE (B)) != NULL_TREE,  \
! 		       20000517))
  #define CLEAR_BINFO_NEW_VTABLE_MARKED(B, C) \
    (BINFO_NEW_VTABLE_MARKED (B, C) = 0)
  
*************** extern tree original_function_name;
*** 3438,3443 ****
--- 3449,3463 ----
  
  #define EXCEPTION_CLEANUP_NAME 	"exception cleanup"
  
+ /* The name used as a prefix for VTTs.  When the new ABI mangling
+    scheme is implemented, this should be removed.  */
+ 
+ #define VTT_NAME_PREFIX "__vtt_"
+ 
+ /* The name used as a prefix for construction vtables.  */
+ 
+ #define CTOR_VTBL_NAME_PREFIX "__ctorvt_"
+ 
  #define THIS_NAME_P(ID_NODE) (strcmp(IDENTIFIER_POINTER (ID_NODE), "this") == 0)
  
  #if !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL)
*************** extern void emit_thunk				PARAMS ((tree)
*** 4187,4192 ****
--- 4207,4213 ----
  extern void synthesize_method			PARAMS ((tree));
  extern tree get_id_2				PARAMS ((const char *, tree));
  extern tree implicitly_declare_fn               PARAMS ((special_function_kind, tree, int));
+ extern tree get_ctor_vtbl_name                  PARAMS ((tree, tree));
  
  /* In optimize.c */
  extern void optimize_function                   PARAMS ((tree));
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.155
diff -c -p -r1.155 method.c
*** method.c	2000/05/19 23:06:55	1.155
--- method.c	2000/05/22 01:07:06
*************** build_typename_overload (type)
*** 1766,1774 ****
    build_mangled_name (type, 0, 1);
    id = get_identifier (obstack_base (&scratch_obstack));
    IDENTIFIER_OPNAME_P (id) = 1;
- #if 0
-   IDENTIFIER_GLOBAL_VALUE (id) = TYPE_MAIN_DECL (type);
- #endif
    TREE_TYPE (id) = type;
    end_squangling ();
    return id;
--- 1766,1771 ----
*************** get_id_2 (name, name2)
*** 1797,1802 ****
--- 1794,1821 ----
    OB_PUTCP (name);
    OB_PUTID (name2);
    OB_FINISH ();
+   return get_identifier (obstack_base (&scratch_obstack));
+ }
+ 
+ /* Returns the name of a construction vtable group.  TYPE is the most
+    derived class in the hierarhcy.  BINFO is the most derived class in
+    the construction vtable group.  */
+ 
+ tree
+ get_ctor_vtbl_name (type, binfo)
+      tree type;
+      tree binfo;
+ {
+   start_squangling ();
+   OB_INIT ();
+   OB_PUTCP (CTOR_VTBL_NAME_PREFIX);
+   build_mangled_name (type, 0, 0);
+   OB_PUTC ('_');
+   build_mangled_name (BINFO_TYPE (binfo), 0, 0);
+   OB_PUTC ('_');
+   build_overload_int (BINFO_OFFSET (binfo), mf_none);
+   OB_FINISH ();
+   end_squangling ();
    return get_identifier (obstack_base (&scratch_obstack));
  }
  
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.179
diff -c -p -r1.179 search.c
*** search.c	2000/05/21 17:01:22	1.179
--- search.c	2000/05/22 01:07:08
*************** dfs_walk_real (binfo, prefn, postfn, qfn
*** 1859,1865 ****
  
    /* Process the basetypes.  */
    binfos = BINFO_BASETYPES (binfo);
!   n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0;
    for (i = 0; i < n_baselinks; i++)
      {
        tree base_binfo = TREE_VEC_ELT (binfos, i);
--- 1859,1865 ----
  
    /* Process the basetypes.  */
    binfos = BINFO_BASETYPES (binfo);
!   n_baselinks = BINFO_N_BASETYPES (binfo);
    for (i = 0; i < n_baselinks; i++)
      {
        tree base_binfo = TREE_VEC_ELT (binfos, i);
*************** init_vbase_pointers (type, decl_ptr)
*** 2521,2527 ****
        vi.inits = NULL_TREE;
  
        /* Build up a list of the initializers.  */
-       TREE_CHAIN (binfo) = decl_ptr;
        dfs_walk_real (binfo, 
  		     dfs_init_vbase_pointers, 0,
  		     unmarked_vtable_pathp,
--- 2521,2526 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]