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]

Re: C++ PATCH: Remove THUNK_DECLs


>>>>> "Jason" == Jason Merrill <jason@cygnus.com> writes:

    Jason> I don't think this is safe.  The reason for using a
    Jason> THUNK_DECL in the first place was because we wanted to
    Jason> store information in it that is wrong for a FUNCTION_DECL:

Here's a patch that should avoid the DECL_SAVED_INSNS and DECL_INITIAL
overlaps which were by far the most troubling.  (See an earlier post
on DECL_FRAME_SIZE for why that one doesn't worry me.)  It follows
both of your excellent suggestions: use DECL_LANG_SPECIFIC for this
stuff, and make generic thunks into something that looks like an
ordinary function before giving it to the back-end.

Thanks for pointing out the dangers, and for suggesting fixes.

Tested (both -fnew-abi and not) on i686-pc-linux-gnu.

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

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

	* cp-tree.h (DELTA_FROM_VTABLE_ENTRY): Remove.
	(SET_FNADDR_FROM_VTABLE_ENTRY): Likewise.
	(lang_decl_flags): Add vcall_offset.
	(THUNK_VCALL_OFFSET): Use it.
	* decl.c (lang_mark_tree): Don't mark DECL_ACCESS for a thunk.
	* method.c (make_thunk): Create the lang_decl here, not in
	emit_thunk.
	(emit_thunk): Make generic thunks into ordinary functions once
	they have been fed to expand_body.
	* semantics.c (expand_body): Set current_function_is_thunk here.

Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.450
diff -c -p -r1.450 cp-tree.h
*** cp-tree.h	2000/05/04 14:54:17	1.450
--- cp-tree.h	2000/05/05 03:05:44
*************** enum languages { lang_c, lang_cplusplus,
*** 1294,1306 ****
    ((CP_TYPE_QUALS (NODE) & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE))	\
     == TYPE_QUAL_CONST)
  
- #define DELTA_FROM_VTABLE_ENTRY(ENTRY)				\
-   (!flag_vtable_thunks ?					\
-      TREE_VALUE (CONSTRUCTOR_ELTS (ENTRY))			\
-    : !DECL_THUNK_P (TREE_OPERAND ((ENTRY), 0)) 			\
-    ? integer_zero_node						\
-    : build_int_2 (THUNK_DELTA (TREE_OPERAND ((ENTRY), 0)), 0))
- 
  /* Virtual function addresses can be gotten from a virtual function
     table entry using this macro.  */
  #define FNADDR_FROM_VTABLE_ENTRY(ENTRY)					\
--- 1294,1299 ----
*************** enum languages { lang_c, lang_cplusplus,
*** 1310,1317 ****
     ? (ENTRY)								\
     : DECL_INITIAL (TREE_OPERAND ((ENTRY), 0)))
  
- #define SET_FNADDR_FROM_VTABLE_ENTRY(ENTRY,VALUE) \
-   (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (ENTRY)))) = (VALUE))
  #define FUNCTION_ARG_CHAIN(NODE) (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (NODE))))
  #define PROMOTES_TO_AGGR_TYPE(NODE,CODE)	\
    (((CODE) == TREE_CODE (NODE)			\
--- 1303,1308 ----
*************** struct lang_decl_flags
*** 1900,1905 ****
--- 1891,1900 ----
      /* In a namespace-scope FUNCTION_DECL, this is
         GLOBAL_INIT_PRIORITY.  */
      int init_priority;
+ 
+     /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
+        THUNK_VCALL_OFFSET.  */
+     HOST_WIDE_INT vcall_offset;
    } u2;
  };
  
*************** extern int flag_new_for_scope;
*** 3039,3045 ****
     vtable for the `this' pointer to find the vcall offset.  (The vptr
     is always located at offset zero from the f `this' pointer.)  If
     zero, then there is no vcall offset.  */
! #define THUNK_VCALL_OFFSET(DECL) (DECL_CHECK (DECL)->decl.u2.i)
  
  /* DECL_NEEDED_P holds of a declaration when we need to emit its
     definition.  This is true when the back-end tells us that
--- 3034,3041 ----
     vtable for the `this' pointer to find the vcall offset.  (The vptr
     is always located at offset zero from the f `this' pointer.)  If
     zero, then there is no vcall offset.  */
! #define THUNK_VCALL_OFFSET(DECL) \
!   (DECL_LANG_SPECIFIC (DECL)->decl_flags.u2.vcall_offset)
  
  /* DECL_NEEDED_P holds of a declaration when we need to emit its
     definition.  This is true when the back-end tells us that
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.601
diff -c -p -r1.601 decl.c
*** decl.c	2000/05/03 22:25:20	1.601
--- decl.c	2000/05/05 03:05:53
*************** lang_mark_tree (t)
*** 14731,14737 ****
        if (ld)
  	{
  	  ggc_mark (ld);
! 	  if (!DECL_GLOBAL_CTOR_P (t) && !DECL_GLOBAL_DTOR_P (t))
  	    ggc_mark_tree (ld->decl_flags.u2.access);
  	  ggc_mark_tree (ld->decl_flags.context);
  	  if (TREE_CODE (t) != NAMESPACE_DECL)
--- 14731,14739 ----
        if (ld)
  	{
  	  ggc_mark (ld);
! 	  if (!DECL_GLOBAL_CTOR_P (t) 
! 	      && !DECL_GLOBAL_DTOR_P (t)
! 	      && !DECL_THUNK_P (t))
  	    ggc_mark_tree (ld->decl_flags.u2.access);
  	  ggc_mark_tree (ld->decl_flags.context);
  	  if (TREE_CODE (t) != NAMESPACE_DECL)
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.153
diff -c -p -r1.153 method.c
*** method.c	2000/05/03 22:25:20	1.153
--- method.c	2000/05/05 03:05:57
*************** make_thunk (function, delta, vcall_index
*** 2055,2060 ****
--- 2055,2063 ----
    if (thunk == NULL_TREE)
      {
        thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl));
+       DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl);
+       copy_lang_decl (func_decl);
+       DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
        TREE_READONLY (thunk) = TREE_READONLY (func_decl);
        TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl);
        comdat_linkage (thunk);
*************** make_thunk (function, delta, vcall_index
*** 2063,2074 ****
        THUNK_DELTA (thunk) = delta;
        THUNK_VCALL_OFFSET (thunk) 
  	= vcall_index * int_size_in_bytes (vtable_entry_type);
        DECL_EXTERNAL (thunk) = 1;
        DECL_ARTIFICIAL (thunk) = 1;
-       DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl);
        /* Even if this thunk is a member of a local class, we don't
  	 need a static chain.  */
        DECL_NO_STATIC_CHAIN (thunk) = 1;
        /* So that finish_file can write out any thunks that need to be: */
        pushdecl_top_level (thunk);
      }
--- 2066,2087 ----
        THUNK_DELTA (thunk) = delta;
        THUNK_VCALL_OFFSET (thunk) 
  	= vcall_index * int_size_in_bytes (vtable_entry_type);
+       /* The thunk itself is not a constructor or destructor, even if
+        the thing it is thunking to is.  */
+       DECL_INTERFACE_KNOWN (thunk) = 1;
+       DECL_NOT_REALLY_EXTERN (thunk) = 1;
+       DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
+       DECL_DESTRUCTOR_P (thunk) = 0;
+       DECL_CONSTRUCTOR_P (thunk) = 0;
        DECL_EXTERNAL (thunk) = 1;
        DECL_ARTIFICIAL (thunk) = 1;
        /* Even if this thunk is a member of a local class, we don't
  	 need a static chain.  */
        DECL_NO_STATIC_CHAIN (thunk) = 1;
+       /* The THUNK is not a pending inline, even if the FUNC_DECL is.  */
+       DECL_PENDING_INLINE_P (thunk) = 0;
+       /* Nor has it been deferred.  */
+       DECL_DEFERRED_FN (thunk) = 0;
        /* So that finish_file can write out any thunks that need to be: */
        pushdecl_top_level (thunk);
      }
*************** void
*** 2081,2095 ****
  emit_thunk (thunk_fndecl)
       tree thunk_fndecl;
  {
!   tree fnaddr = DECL_INITIAL (thunk_fndecl);
!   tree function = TREE_OPERAND (fnaddr, 0);
!   int delta = THUNK_DELTA (thunk_fndecl);
!   int vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
  
    if (TREE_ASM_WRITTEN (thunk_fndecl))
      return;
  
!   TREE_ASM_WRITTEN (thunk_fndecl) = 1;
  
    TREE_ADDRESSABLE (function) = 1;
    mark_used (function);
--- 2094,2118 ----
  emit_thunk (thunk_fndecl)
       tree thunk_fndecl;
  {
!   tree fnaddr;
!   tree function;
!   int delta;
!   int vcall_offset;
  
    if (TREE_ASM_WRITTEN (thunk_fndecl))
      return;
  
!   if (TREE_CODE (DECL_INITIAL (thunk_fndecl)) != ADDR_EXPR)
!     /* We already turned this thunk into an ordinary function.
!        There's no need to process this thunk again.  (We can't just
!        clear DECL_THUNK_P because that will confuse
!        FNADDR_FROM_VTABLE_ENTRY and friends.)  */
!     return;
! 
!   fnaddr = DECL_INITIAL (thunk_fndecl);
!   function = TREE_OPERAND (fnaddr, 0);
!   delta = THUNK_DELTA (thunk_fndecl);
!   vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl);
  
    TREE_ADDRESSABLE (function) = 1;
    mark_used (function);
*************** emit_thunk (thunk_fndecl)
*** 2097,2104 ****
    if (current_function_decl)
      abort ();
  
  #ifdef ASM_OUTPUT_MI_THUNK
!   if (!flag_syntax_only && vcall_offset == 0)
      {
        const char *fnname;
        current_function_decl = thunk_fndecl;
--- 2120,2133 ----
    if (current_function_decl)
      abort ();
  
+   if (flag_syntax_only)
+     {
+       TREE_ASM_WRITTEN (thunk_fndecl) = 1;
+       return;
+     }
+ 
  #ifdef ASM_OUTPUT_MI_THUNK
!   if (vcall_offset == 0)
      {
        const char *fnname;
        current_function_decl = thunk_fndecl;
*************** emit_thunk (thunk_fndecl)
*** 2115,2120 ****
--- 2144,2150 ----
        assemble_end_function (thunk_fndecl, fnname);
        current_function_decl = 0;
        cfun = 0;
+       TREE_ASM_WRITTEN (thunk_fndecl) = 1;
      }
    else
  #endif /* ASM_OUTPUT_MI_THUNK */
*************** emit_thunk (thunk_fndecl)
*** 2141,2161 ****
      a = nreverse (t);
      DECL_ARGUMENTS (thunk_fndecl) = a;
      DECL_RESULT (thunk_fndecl) = NULL_TREE;
-     DECL_LANG_SPECIFIC (thunk_fndecl) = DECL_LANG_SPECIFIC (function);
-     copy_lang_decl (thunk_fndecl);
-     DECL_INTERFACE_KNOWN (thunk_fndecl) = 1;
-     DECL_NOT_REALLY_EXTERN (thunk_fndecl) = 1;
-     DECL_SAVED_FUNCTION_DATA (thunk_fndecl) = NULL;
  
-     /* The thunk itself is not a constructor or destructor, even if
-        the thing it is thunking to is.  */
-     DECL_DESTRUCTOR_P (thunk_fndecl) = 0;
-     DECL_CONSTRUCTOR_P (thunk_fndecl) = 0;
- 
      push_to_top_level ();
      start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
      store_parm_decls ();
-     current_function_is_thunk = 1;
  
      /* Adjust the this pointer by the constant.  */
      t = ssize_int (delta);
--- 2171,2180 ----
*************** emit_thunk (thunk_fndecl)
*** 2199,2217 ****
        finish_expr_stmt (t);
  
      /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
!        clear this here.  */
!     DECL_INITIAL (thunk_fndecl) = NULL_TREE;
      DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
      BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) 
        = DECL_ARGUMENTS (thunk_fndecl);
      expand_body (finish_function (0));
-     /* Restore the DECL_INITIAL for the THUNK_DECL.  */
-     DECL_INITIAL (thunk_fndecl) = fnaddr;
      pop_from_top_level ();
- 
-     /* Don't let the backend defer this function.  */
-     if (DECL_DEFER_OUTPUT (thunk_fndecl))
-       output_inline_function (thunk_fndecl);
    }
  }
  
--- 2218,2229 ----
        finish_expr_stmt (t);
  
      /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
!        create one.  */
      DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
      BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) 
        = DECL_ARGUMENTS (thunk_fndecl);
      expand_body (finish_function (0));
      pop_from_top_level ();
    }
  }
  
Index: semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.138
diff -c -p -r1.138 semantics.c
*** semantics.c	2000/04/11 20:16:36	1.138
--- semantics.c	2000/05/05 03:06:01
*************** expand_body (fn)
*** 2775,2780 ****
--- 2775,2781 ----
  
    start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
    store_parm_decls ();
+   current_function_is_thunk = DECL_THUNK_P (fn);
  
    /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
       any of the other magic variables we set up when starting a

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