C++ PATCH: run-time initialization of vptrs

Mark Mitchell mark@codesourcery.com
Mon Jan 10 18:44:00 GMT 2000


This patch generalizes the algorithm for initializing vptrs to work
with the new ABI.

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

2000-01-10  Mark Mitchell  <mitchell@dumbledore.codesourcery.com>

	* cp-tree.h (expand_direct_vtbls_init): Remove declaration.
	(initialize_vtbl_ptrs): New function.
	(expand_indirect_vtbls_init): Change prototype.
	(convert_pointer_to_vbase): Declare.
	* init.c (expand_direct_vtbls_init): Remove.
	(dfs_initialize_vtbl_ptrs): New function.
	(initialize_vtbl_ptrs): Likewise.
	(emit_base_init): Use initialize_vtbl_ptrs.
	* search.c (convert_pointer_to_vbase): Make it global.
	(expand_indirect_vtbls_init): Remove vtable initialization code.
	* semantics.c (setup_vtbl_ptr): Use initialize_vtbl_ptrs.

Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.380
diff -c -p -r1.380 cp-tree.h
*** cp-tree.h	2000/01/11 01:55:37	1.380
--- cp-tree.h	2000/01/11 02:39:03
*************** extern tree do_friend				PROTO((tree, tr
*** 3734,3740 ****
  
  /* in init.c */
  extern void init_init_processing		PROTO((void));
- extern void expand_direct_vtbls_init		PROTO((tree, tree, int, int, tree));
  extern tree emit_base_init			PROTO((tree));
  extern void check_base_init			PROTO((tree));
  extern void expand_member_init			PROTO((tree, tree, tree));
--- 3734,3739 ----
*************** extern tree build_vec_delete			PROTO((tr
*** 3757,3762 ****
--- 3756,3762 ----
  extern tree create_temporary_var                PROTO((tree));
  extern void begin_init_stmts                    PROTO((tree *, tree *));
  extern tree finish_init_stmts                   PROTO((tree, tree));
+ extern void initialize_vtbl_ptrs                PROTO((tree, tree));
  
  /* in input.c */
  
*************** extern tree lookup_nested_tag			PROTO((t
*** 3926,3932 ****
  extern tree get_matching_virtual		PROTO((tree, tree, int));
  extern void get_pure_virtuals		        PROTO((tree));
  extern tree init_vbase_pointers			PROTO((tree, tree));
! extern void expand_indirect_vtbls_init		PROTO((tree, tree, tree));
  extern void clear_search_slots			PROTO((tree));
  extern void get_vbase_types			PROTO((tree));
  extern void maybe_suppress_debug_info		PROTO((tree));
--- 3926,3932 ----
  extern tree get_matching_virtual		PROTO((tree, tree, int));
  extern void get_pure_virtuals		        PROTO((tree));
  extern tree init_vbase_pointers			PROTO((tree, tree));
! extern void expand_indirect_vtbls_init		PROTO((tree, tree));
  extern void clear_search_slots			PROTO((tree));
  extern void get_vbase_types			PROTO((tree));
  extern void maybe_suppress_debug_info		PROTO((tree));
*************** extern tree dfs_skip_nonprimary_vbases_m
*** 3955,3960 ****
--- 3955,3961 ----
  extern tree dfs_unmarked_real_bases_queue_p     PROTO((tree, void *));
  extern tree dfs_marked_real_bases_queue_p       PROTO((tree, void *));
  extern void mark_primary_bases                  PROTO((tree));
+ extern tree convert_pointer_to_vbase            PROTO((tree, tree));
  
  /* in semantics.c */
  extern void finish_expr_stmt                    PROTO((tree));
Index: init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.158
diff -c -p -r1.158 init.c
*** init.c	1999/12/31 20:26:07	1.158
--- init.c	2000/01/11 02:39:05
***************
*** 1,5 ****
  /* Handle initialization things in C++.
!    Copyright (C) 1987, 89, 92-98, 1999 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Handle initialization things in C++.
!    Copyright (C) 1987, 89, 92-98, 1999, 2000 Free Software Foundation, Inc.
     Contributed by Michael Tiemann (tiemann@cygnus.com)
  
  This file is part of GNU CC.
*************** static tree initializing_context PROTO((
*** 48,53 ****
--- 48,54 ----
  static tree build_java_class_ref PROTO((tree));
  static void expand_cleanup_for_base PROTO((tree, tree));
  static tree get_temp_regvar PROTO((tree, tree));
+ static tree dfs_initialize_vtbl_ptrs PROTO((tree, void *));
  
  /* Set up local variable for this file.  MUST BE CALLED AFTER
     INIT_DECL_PROCESSING.  */
*************** void init_init_processing ()
*** 77,135 ****
    ggc_add_tree_root (&BI_header_size, 1);
  }
  
! /* Subroutine of emit_base_init.  For BINFO, initialize all the
!    virtual function table pointers, except those that come from
!    virtual base classes.  Initialize binfo's vtable pointer, if
!    INIT_SELF is true.  CAN_ELIDE is true when we know that all virtual
!    function table pointers in all bases have been initialized already,
!    probably because their constructors have just be run.  ADDR is the
!    pointer to the object whos vtables we are going to initialize.
! 
!    REAL_BINFO is usually the same as BINFO, except when addr is not of
!    pointer to the type of the real derived type that we want to
!    initialize for.  This is the case when addr is a pointer to a sub
!    object of a complete object, and we only want to do part of the
!    complete object's initialization of vtable pointers.  This is done
!    for all virtual table pointers in virtual base classes.  REAL_BINFO
!    is used to find the BINFO_VTABLE that we initialize with.  BINFO is
!    used for conversions of addr to subobjects.
  
!    BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo).
  
!    Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE
!    (addr))).  */
  
  void
! expand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)
!      tree real_binfo, binfo, addr;
!      int init_self, can_elide;
  {
!   tree real_binfos = BINFO_BASETYPES (real_binfo);
!   tree binfos = BINFO_BASETYPES (binfo);
!   int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;
  
!   for (i = 0; i < n_baselinks; i++)
!     {
!       tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
!       tree base_binfo = TREE_VEC_ELT (binfos, i);
!       int is_not_base_vtable
! 	= i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
!       if (! TREE_VIA_VIRTUAL (real_base_binfo))
! 	expand_direct_vtbls_init (real_base_binfo, base_binfo,
! 				  is_not_base_vtable, can_elide, addr);
!     }
! #if 0
!   /* Before turning this on, make sure it is correct.  */
!   if (can_elide && ! BINFO_MODIFIED (binfo))
!     return;
! #endif
!   /* Should we use something besides CLASSTYPE_VFIELDS? */
!   if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))
!     {
!       tree base_ptr = convert_pointer_to_real (binfo, addr);
!       expand_virtual_init (real_binfo, base_ptr);
!     }
  }
  
  /* 348 - 351 */
  /* Subroutine of emit_base_init.  */
--- 78,132 ----
    ggc_add_tree_root (&BI_header_size, 1);
  }
  
! /* Called from initialize_vtbl_ptrs via dfs_walk.  */
  
! static tree
! dfs_initialize_vtbl_ptrs (binfo, data)
!      tree binfo;
!      void *data;
! {
!   if (!BINFO_PRIMARY_MARKED_P (binfo) 
!       && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo)))
!     {
!       tree base_ptr = TREE_VALUE ((tree) data);
! 
!       if (TREE_VIA_VIRTUAL (binfo))
! 	base_ptr = convert_pointer_to_vbase (BINFO_TYPE (binfo),
! 					     base_ptr);
!       else
! 	base_ptr 
! 	  = build_vbase_path (PLUS_EXPR, 
! 			      build_pointer_type (BINFO_TYPE (binfo)),
! 			      base_ptr,
! 			      binfo,
! 			      /*nonnull=*/1);
! 
!       expand_virtual_init (binfo, base_ptr);
!     }
! 
!   SET_BINFO_MARKED (binfo);
! 
!   return NULL_TREE;
! }
  
! /* Initialize all the vtable pointers for the hierarchy dominated by
!    TYPE. */
  
  void
! initialize_vtbl_ptrs (type, addr)
!      tree type;
!      tree addr;
  {
!   tree list = build_tree_list (type, addr);
  
!   dfs_walk (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, 
! 	    dfs_unmarked_real_bases_queue_p, list);
!   dfs_walk (TYPE_BINFO (type), dfs_unmark,
! 	    dfs_marked_real_bases_queue_p, type);
!   if (TYPE_USES_VIRTUAL_BASECLASSES (type))
!     expand_indirect_vtbls_init (TYPE_BINFO (type), addr);
  }
+ 
  
  /* 348 - 351 */
  /* Subroutine of emit_base_init.  */
*************** emit_base_init (t)
*** 546,560 ****
        expand_cleanup_for_base (base_binfo, NULL_TREE);
        rbase_init_list = TREE_CHAIN (rbase_init_list);
      }
- 
-   /* Initialize all the virtual function table fields that
-      do come from virtual base classes.  */
-   if (TYPE_USES_VIRTUAL_BASECLASSES (t))
-     expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);
  
!   /* Initialize all the virtual function table fields that
!      do not come from virtual base classes.  */
!   expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);
  
    for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
      {
--- 543,551 ----
        expand_cleanup_for_base (base_binfo, NULL_TREE);
        rbase_init_list = TREE_CHAIN (rbase_init_list);
      }
  
!   /* Initialize the vtable pointers for the class.  */
!   initialize_vtbl_ptrs (t, current_class_ptr);
  
    for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
      {
Index: search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.143
diff -c -p -r1.143 search.c
*** search.c	2000/01/11 01:55:37	1.143
--- search.c	2000/01/11 02:39:07
*************** static struct search_level *search_stack
*** 77,83 ****
  
  static tree next_baselink PROTO((tree));
  static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
- static tree convert_pointer_to_vbase PROTO((tree, tree));
  static tree lookup_field_1 PROTO((tree, tree));
  static tree convert_pointer_to_single_level PROTO((tree, tree));
  static int lookup_fnfields_here PROTO((tree, tree));
--- 77,82 ----
*************** get_vbase (parent, binfo)
*** 249,255 ****
     EXPR is a non-null POINTER_TYPE to RECORD_TYPE.  We also know that
     the type of what expr points to has a virtual base of type TYPE.  */
  
! static tree
  convert_pointer_to_vbase (type, expr)
       tree type;
       tree expr;
--- 248,254 ----
     EXPR is a non-null POINTER_TYPE to RECORD_TYPE.  We also know that
     the type of what expr points to has a virtual base of type TYPE.  */
  
! tree
  convert_pointer_to_vbase (type, expr)
       tree type;
       tree expr;
*************** fixup_all_virtual_upcast_offsets (type, 
*** 3004,3012 ****
     sub-object we are initializing.  */
  
  void
! expand_indirect_vtbls_init (binfo, true_exp, decl_ptr)
       tree binfo;
!      tree true_exp, decl_ptr;
  {
    tree type = BINFO_TYPE (binfo);
  
--- 3003,3011 ----
     sub-object we are initializing.  */
  
  void
! expand_indirect_vtbls_init (binfo, decl_ptr)
       tree binfo;
!      tree decl_ptr;
  {
    tree type = BINFO_TYPE (binfo);
  
*************** expand_indirect_vtbls_init (binfo, true_
*** 3025,3053 ****
      {
        tree vbases = CLASSTYPE_VBASECLASSES (type);
        struct vbase_info vi;
!       vi.decl_ptr = (true_exp ? build_unary_op (ADDR_EXPR, true_exp, 0) 
! 		     : decl_ptr);
        vi.vbase_types = vbases;
  
        dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
! 
!       /* Initialized with vtables of type TYPE.  */
!       for (; vbases; vbases = TREE_CHAIN (vbases))
! 	{
! 	  tree addr;
! 
! 	  addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vi.decl_ptr);
! 
! 	  /* Do all vtables from this virtual base.  */
! 	  /* This assumes that virtual bases can never serve as parent
! 	     binfos.  (in the CLASSTYPE_VFIELD_PARENT sense)  */
! 	  expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
! 				    1, 0, addr);
! 	}
! 
!       fixup_all_virtual_upcast_offsets (type,
! 					vi.decl_ptr);
! 
        dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
      }
  }
--- 3024,3034 ----
      {
        tree vbases = CLASSTYPE_VBASECLASSES (type);
        struct vbase_info vi;
!       vi.decl_ptr = decl_ptr;
        vi.vbase_types = vbases;
  
        dfs_walk (binfo, dfs_find_vbases, unmarked_new_vtablep, &vi);
!       fixup_all_virtual_upcast_offsets (type, vi.decl_ptr);
        dfs_walk (binfo, dfs_clear_vbase_slots, marked_new_vtablep, 0);
      }
  }
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.120
diff -c -p -r1.120 semantics.c
*** semantics.c	1999/12/26 15:28:18	1.120
--- semantics.c	2000/01/11 02:39:08
***************
*** 3,9 ****
     building RTL.  These routines are used both during actual parsing
     and during the instantiation of template functions. 
  
!    Copyright (C) 1998, 1999 Free Software Foundation, Inc.
     Written by Mark Mitchell (mmitchell@usa.net) based on code found
     formerly in parse.y and pt.c.  
  
--- 3,9 ----
     building RTL.  These routines are used both during actual parsing
     and during the instantiation of template functions. 
  
!    Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
     Written by Mark Mitchell (mmitchell@usa.net) based on code found
     formerly in parse.y and pt.c.  
  
*************** setup_vtbl_ptr ()
*** 1245,1251 ****
    else if (DECL_DESTRUCTOR_P (current_function_decl)
  	   && !processing_template_decl)
      {
-       tree binfo = TYPE_BINFO (current_class_type);
        tree if_stmt;
        tree compound_stmt;
        int saved_cfnd;
--- 1245,1250 ----
*************** setup_vtbl_ptr ()
*** 1279,1289 ****
        /* Make all virtual function table pointers in non-virtual base
  	 classes point to CURRENT_CLASS_TYPE's virtual function
  	 tables.  */
!       expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
! 
!       if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
! 	expand_indirect_vtbls_init (binfo, current_class_ref, 
! 				    current_class_ptr);
  
        finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
        finish_then_clause (if_stmt);
--- 1278,1285 ----
        /* Make all virtual function table pointers in non-virtual base
  	 classes point to CURRENT_CLASS_TYPE's virtual function
  	 tables.  */
!       initialize_vtbl_ptrs (current_class_type,
! 			    current_class_ptr);
  
        finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
        finish_then_clause (if_stmt);


More information about the Gcc-patches mailing list