C++ PATCH: Vcall offset thunks with ellipsis

Mark Mitchell mark@codesourcery.com
Fri Oct 18 16:41:00 GMT 2002


This patch implements support for virtual fuction thunks where the
thunked-to function has an ellipsis and a vcall offset adjustment is
required in the thunk.  (Before now, we just issued a "sorry"
message.)  

At the same time, I moved ASM_OUTPUT_MI_THUNK into the target hooks
structure.  Right now, only x86 has support for the new variety of
thunk; port maintainers will have to add these bits for their
architectures to fix the bug in the attached test case.  (Which, I
just realized, needs a DejaGNU comment so it does not run on non-x86
targets; I'll fix that right away.)

Some day, we will have real alternate entry point support, and then
this thunk stuff can go away -- but that doesn't look immediate.

Bootstrapped and tested on i686-pc-linux-gnu, and by building a cross
compiler to at least one target for each architecture that defined
ASM_OUTPUT_MI_THUK.  Applied on the mainline.  Technically, this is a
2.95.x regression, but I'm not going to put the patch there; this is a
definite corner case, ad the patch is too risky.

If I managed to introduce any build failures, let me know!

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

2002-10-18  Mark Mitchell  <mark@codesourcery.com>

	* target-def.h (TARGET_ASM_OUTPUT_MI_THUNK): Default to NULL.
	(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Likewise.
	(TARGET_ASM_OUT): Add them.
	* target.h (asm_out): Add output_mi_thunk and
	output_mi_vcall_thunk.
	* config/alpha/alpha.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/arm/arm-protos.h (arm_output_mi_thunk): Declare.
	* config/arm/arm.c (arm_output_mi_thunk): Define.
	* config/arm/arm.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/cris/cris.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/frv/frv.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/i386/i386-protos.h (x86_output_mi_thunk): Adjust
	prototype.
	(x86_output_mi_vcall_thunk): Declare.
	* config/i386/i386.c (override_options): Clear
	output_mi_vcall_thunk in 64-bit mode.
	(ix86_fntype_regparm): New function.
	(ix86_return_pops_args): Use it.
	(ia32_this_parameter): New function.
	(x86_output_mi_vcall_thunk): New function.
	(x86_output_mi_thunk): Use it
	* config/i386/unix.h (TARGET_ASM_OUTPUT_MI_THUNK): Adjust.
	(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Define.
	* config/i960/i960-protos.h (i960_output_mi_thunk): Declare.
	* config/i960/i960.c (i960_output_mi_thunk): New function.
	* config/i960/i960.h (ASM_OUTPUT_MI_THUNK): Adjust.
	* config/ia64/ia64-protos.h (ia64_output_mi_thunk): Declare.
	* config/ia64/ia64.c (ia64_output_mi_thunk): Define.
	* config/ia64/ia64.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/m68k/m68k-protos.h (m68k_output_mi_thunk): New function.
	* config/m68k/linux.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/m68k/netbsd-elf.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/mmix/mmix.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/pa/pa.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/rs6000/sysv4.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/s390/s390-protos.h (s390_output_mi_thunk): Declare.
	* config/s390/s390.c (s390_output_mi_thunk): Define.
	* config/s390/s390.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/sparc/sparc.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/stormy16/stormy16.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* config/vax/vax-protos.h (vax_output_mi_thunk): Declare.
	* config/vax/vax.c (vax_output_mi_thunk): Define.
	* config/vax/vax.h (ASM_OUTPUT_MI_THUNK): Rename to ...
	(TARGET_ASM_OUTPUT_MI_THUNK): ... this.
	* doc/tm.texi: Adjust documentation.
	
2002-10-18  Mark Mitchell  <mark@codesourcery.com>

	* Make-lang.in (method.o): Depend on TARGET_H.
	* method.c (target.h): Include it.
	(use_thunk): Use target hooks.  Use vcall thunks, if available.

Index: target-def.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target-def.h,v
retrieving revision 1.34
diff -c -p -r1.34 target-def.h
*** target-def.h	13 Sep 2002 03:44:53 -0000	1.34
--- target-def.h	18 Oct 2002 23:32:07 -0000
*************** Foundation, 59 Temple Place - Suite 330,
*** 103,108 ****
--- 103,116 ----
  # endif
  #endif
  
+ #ifndef TARGET_ASM_OUTPUT_MI_THUNK
+ #define TARGET_ASM_OUTPUT_MI_THUNK NULL
+ #endif
+ 
+ #ifndef TARGET_ASM_OUTPUT_MI_VCALL_THUNK
+ #define TARGET_ASM_OUTPUT_MI_VCALL_THUNK NULL
+ #endif
+ 
  #if defined(TARGET_ASM_CONSTRUCTOR) && defined(TARGET_ASM_DESTRUCTOR)
  #define TARGET_HAVE_CTORS_DTORS true
  #else
*************** Foundation, 59 Temple Place - Suite 330,
*** 173,179 ****
  			TARGET_ASM_SELECT_RTX_SECTION,		\
  			TARGET_ASM_UNIQUE_SECTION,		\
  			TARGET_ASM_CONSTRUCTOR,			\
! 			TARGET_ASM_DESTRUCTOR}
  
  /* Scheduler hooks.  All of these default to null pointers, which
     haifa-sched.c looks for and handles.  */
--- 181,189 ----
  			TARGET_ASM_SELECT_RTX_SECTION,		\
  			TARGET_ASM_UNIQUE_SECTION,		\
  			TARGET_ASM_CONSTRUCTOR,			\
! 			TARGET_ASM_DESTRUCTOR,                  \
!                         TARGET_ASM_OUTPUT_MI_THUNK,             \
!                         TARGET_ASM_OUTPUT_MI_VCALL_THUNK }
  
  /* Scheduler hooks.  All of these default to null pointers, which
     haifa-sched.c looks for and handles.  */
Index: target.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/target.h,v
retrieving revision 1.37
diff -c -p -r1.37 target.h
*** target.h	27 Sep 2002 12:48:03 -0000	1.37
--- target.h	18 Oct 2002 23:32:07 -0000
*************** struct gcc_target
*** 119,124 ****
--- 119,131 ----
  
      /* Output a destructor for a symbol with a given priority.  */
      void (* destructor) PARAMS ((rtx, int));
+ 
+     /* Output the assembler code for a thunk function.  */
+     void (* output_mi_thunk) PARAMS ((FILE *, tree, int, tree));
+ 
+     /* Output the assembler code for a thunk function with a vcall
+        offset.  */
+     void (* output_mi_vcall_thunk) PARAMS ((FILE *, tree, int, int, tree));
    } asm_out;
  
    /* Functions relating to instruction scheduling.  */
Index: config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.182
diff -c -p -r1.182 alpha.h
*** config/alpha/alpha.h	24 Sep 2002 12:48:50 -0000	1.182
--- config/alpha/alpha.h	18 Oct 2002 23:32:08 -0000
*************** do {							\
*** 2141,2145 ****
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
!   alpha_output_mi_thunk_osf (FILE, THUNK_FNDECL, DELTA, FUNCTION)
--- 2141,2144 ----
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf
Index: config/arm/arm-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.32
diff -c -p -r1.32 arm-protos.h
*** config/arm/arm-protos.h	6 Sep 2002 14:54:48 -0000	1.32
--- config/arm/arm-protos.h	18 Oct 2002 23:32:08 -0000
***************
*** 1,5 ****
  /* Prototypes for exported functions defined in arm.c and pe.c
!    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
     Contributed by Richard Earnshaw (rearnsha@arm.com)
     Minor hacks by Nick Clifton (nickc@cygnus.com)
  
--- 1,5 ----
  /* Prototypes for exported functions defined in arm.c and pe.c
!    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
     Contributed by Richard Earnshaw (rearnsha@arm.com)
     Minor hacks by Nick Clifton (nickc@cygnus.com)
  
*************** extern int  arm_dllexport_p 		PARAMS ((t
*** 194,199 ****
--- 194,200 ----
  extern int  arm_dllimport_p 		PARAMS ((tree));
  extern void arm_mark_dllexport 		PARAMS ((tree));
  extern void arm_mark_dllimport 		PARAMS ((tree));
+ extern void arm_output_mi_thunk         PARAMS ((FILE *, tree, int, tree));
  #endif
  
  extern void arm_init_builtins		PARAMS ((void));
Index: config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.234
diff -c -p -r1.234 arm.c
*** config/arm/arm.c	28 Sep 2002 15:29:36 -0000	1.234
--- config/arm/arm.c	18 Oct 2002 23:32:10 -0000
*************** arm_encode_section_info (decl, first)
*** 11130,11132 ****
--- 11130,11167 ----
      }
  }
  #endif /* !ARM_PE */
+ 
+ void
+ arm_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
+      int delta;
+      tree function;
+ {
+   int mi_delta = delta;
+   const char *const mi_op = mi_delta < 0 ? "sub" : "add";
+   int shift = 0;
+   int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)))
+                     ? 1 : 0);
+   if (mi_delta < 0)
+     mi_delta = - mi_delta;
+   while (mi_delta != 0)
+     {
+       if ((mi_delta & (3 << shift)) == 0)
+         shift += 2;
+       else
+         {
+           asm_fprintf (file, "\t%s\t%r, %r, #%d\n",
+                        mi_op, this_regno, this_regno,
+                        mi_delta & (0xff << shift));
+           mi_delta &= ~(0xff << shift);
+           shift += 8;
+         }
+     }
+   fputs ("\tb\t", file);
+   assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
+   if (NEED_PLT_RELOC)
+     fputs ("(PLT)", file);
+   fputc ('\n', file);
+ }
+ 
Index: config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.164
diff -c -p -r1.164 arm.h
*** config/arm/arm.h	30 Sep 2002 11:18:38 -0000	1.164
--- config/arm/arm.h	18 Oct 2002 23:32:11 -0000
*************** extern int making_const_table;
*** 2697,2732 ****
       
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)		\
!   do										\
!     {										\
!       int mi_delta = (DELTA);							\
!       const char *const mi_op = mi_delta < 0 ? "sub" : "add";			\
!       int shift = 0;								\
!       int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION)))	\
! 		        ? 1 : 0);						\
!       if (mi_delta < 0)								\
!         mi_delta = - mi_delta;							\
!       while (mi_delta != 0)							\
!         {									\
!           if ((mi_delta & (3 << shift)) == 0)					\
! 	    shift += 2;								\
!           else									\
! 	    {									\
! 	      asm_fprintf (FILE, "\t%s\t%r, %r, #%d\n",				\
! 		           mi_op, this_regno, this_regno,			\
! 		           mi_delta & (0xff << shift));				\
! 	      mi_delta &= ~(0xff << shift);					\
! 	      shift += 8;							\
! 	    }									\
!         }									\
!       fputs ("\tb\t", FILE);							\
!       assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));		\
!       if (NEED_PLT_RELOC)							\
!         fputs ("(PLT)", FILE);							\
!       fputc ('\n', FILE);							\
!     }										\
!   while (0)
  
  /* A C expression whose value is RTL representing the value of the return
     address for the frame COUNT steps up from the current frame.  */
--- 2697,2703 ----
       
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK arm_output_mi_thunk
  
  /* A C expression whose value is RTL representing the value of the return
     address for the frame COUNT steps up from the current frame.  */
Index: config/cris/cris.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/cris/cris.h,v
retrieving revision 1.40
diff -c -p -r1.40 cris.h
*** config/cris/cris.h	17 Sep 2002 23:10:04 -0000	1.40
--- config/cris/cris.h	18 Oct 2002 23:32:11 -0000
*************** struct cum_args {int regs;};
*** 1013,1020 ****
  #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) \
    cris_eligible_for_epilogue_delay (INSN)
  
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
!  cris_asm_output_mi_thunk(FILE, THUNK_FNDECL, DELTA, FUNCTION)
  
  
  /* Node: Profiling */
--- 1013,1019 ----
  #define ELIGIBLE_FOR_EPILOGUE_DELAY(INSN, N) \
    cris_eligible_for_epilogue_delay (INSN)
  
! #define TARGET_ASM_OUTPUT_MI_THUNK cris_asm_output_mi_thunk
  
  
  /* Node: Profiling */
Index: config/frv/frv.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/frv/frv.h,v
retrieving revision 1.10
diff -c -p -r1.10 frv.h
*** config/frv/frv.h	24 Sep 2002 12:48:53 -0000	1.10
--- config/frv/frv.h	18 Oct 2002 23:32:12 -0000
*************** struct machine_function GTY(())
*** 2110,2117 ****
     frontend will generate a less efficient heavyweight thunk that calls
     FUNCTION instead of jumping to it.  The generic approach does not support
     varargs.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
! frv_asm_output_mi_thunk (FILE, THUNK_FNDECL, (long)DELTA, FUNCTION)
  
  
  /* Generating Code for Profiling.  */
--- 2110,2116 ----
     frontend will generate a less efficient heavyweight thunk that calls
     FUNCTION instead of jumping to it.  The generic approach does not support
     varargs.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk
  
  
  /* Generating Code for Profiling.  */
Index: config/i386/i386-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-protos.h,v
retrieving revision 1.80
diff -c -p -r1.80 i386-protos.h
*** config/i386/i386-protos.h	15 Sep 2002 21:47:42 -0000	1.80
--- config/i386/i386-protos.h	18 Oct 2002 23:32:12 -0000
*************** extern tree ix86_handle_shared_attribute
*** 211,217 ****
  extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
  							int));
  extern void i386_pe_asm_named_section PARAMS ((const char *, unsigned int));
! extern void x86_output_mi_thunk PARAMS ((FILE *, int, tree));
  extern int x86_field_alignment PARAMS ((tree, int));
  #endif
  
--- 211,218 ----
  extern unsigned int i386_pe_section_type_flags PARAMS ((tree, const char *,
  							int));
  extern void i386_pe_asm_named_section PARAMS ((const char *, unsigned int));
! extern void x86_output_mi_thunk PARAMS ((FILE *, tree, int, tree));
! extern void x86_output_mi_vcall_thunk PARAMS ((FILE *, tree, int, int, tree));
  extern int x86_field_alignment PARAMS ((tree, int));
  #endif
  
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.473
diff -c -p -r1.473 i386.c
*** config/i386/i386.c	18 Oct 2002 23:00:50 -0000	1.473
--- config/i386/i386.c	18 Oct 2002 23:32:15 -0000
*************** static int ix86_variable_issue PARAMS ((
*** 750,755 ****
--- 750,756 ----
  static int ia32_use_dfa_pipeline_interface PARAMS ((void));
  static int ia32_multipass_dfa_lookahead PARAMS ((void));
  static void ix86_init_mmx_sse_builtins PARAMS ((void));
+ static rtx ia32_this_parameter PARAMS ((tree));
  
  struct ix86_address
  {
*************** static unsigned int ix86_select_alt_pic_
*** 788,793 ****
--- 789,795 ----
  static int ix86_save_reg PARAMS ((unsigned int, int));
  static void ix86_compute_frame_layout PARAMS ((struct ix86_frame *));
  static int ix86_comp_type_attributes PARAMS ((tree, tree));
+ static int ix86_fntype_regparm PARAMS ((tree));
  const struct attribute_spec ix86_attribute_table[];
  static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
  static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
*************** override_options ()
*** 1295,1300 ****
--- 1297,1306 ----
      internal_label_prefix_len = p - internal_label_prefix;
      *p = '\0';
    }
+ 
+   /* In 64-bit mode, we do not have support for vcall thunks.  */
+   if (TARGET_64BIT)
+     targetm.asm_out.output_mi_vcall_thunk = NULL;
  }
  
  void
*************** ix86_comp_type_attributes (type1, type2)
*** 1431,1436 ****
--- 1437,1457 ----
    return 1;
  }
  
+ /* Return the regparm value for a fuctio with the indicated TYPE.  */
+ 
+ static int
+ ix86_fntype_regparm (type)
+      tree type;
+ {
+   tree attr;
+ 
+   attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+   if (attr)
+     return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+   else
+     return ix86_regparm;
+ }
+ 
  /* Value is the number of bytes of arguments automatically
     popped when returning from a subroutine call.
     FUNDECL is the declaration node of the function (as a tree),
*************** ix86_return_pops_args (fundecl, funtype,
*** 1474,1488 ****
    if (aggregate_value_p (TREE_TYPE (funtype))
        && !TARGET_64BIT)
      {
!       int nregs = ix86_regparm;
! 
!       if (funtype)
! 	{
! 	  tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (funtype));
! 
! 	  if (attr)
! 	    nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
! 	}
  
        if (!nregs)
  	return GET_MODE_SIZE (Pmode);
--- 1495,1501 ----
    if (aggregate_value_p (TREE_TYPE (funtype))
        && !TARGET_64BIT)
      {
!       int nregs = ix86_fntype_regparm (funtype);
  
        if (!nregs)
  	return GET_MODE_SIZE (Pmode);
*************** x86_order_regs_for_local_alloc ()
*** 13860,13886 ****
       reg_alloc_order [pos++] = 0;
  }
  
  void
! x86_output_mi_thunk (file, delta, function)
       FILE *file;
       int delta;
       tree function;
  {
-   tree parm;
    rtx xops[3];
  
-   if (ix86_regparm > 0)
-     parm = TYPE_ARG_TYPES (TREE_TYPE (function));
-   else
-     parm = NULL_TREE;
-   for (; parm; parm = TREE_CHAIN (parm))
-     if (TREE_VALUE (parm) == void_type_node)
-       break;
- 
-   xops[0] = GEN_INT (delta);
    if (TARGET_64BIT)
      {
        int n = aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) != 0;
        xops[1] = gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
        output_asm_insn ("add{q} {%0, %1|%1, %0}", xops);
        if (flag_pic)
--- 13873,13923 ----
       reg_alloc_order [pos++] = 0;
  }
  
+ /* Returns an expression indicating where the this parameter is
+    located on entry to the FUNCTION.  */
+ 
+ static rtx
+ ia32_this_parameter (function)
+      tree function;
+ {
+   tree type = TREE_TYPE (function);
+ 
+   if (ix86_fntype_regparm (type) > 0)
+     {
+       tree parm;
+ 
+       parm = TYPE_ARG_TYPES (type);
+       /* Figure out whether or not the function has a variable number of
+ 	 arguments.  */
+       for (; parm; parm = TREE_CHAIN (parm))\
+ 	if (TREE_VALUE (parm) == void_type_node)
+ 	  break;
+       /* If not, the this parameter is in %eax.  */
+       if (parm)
+ 	return gen_rtx_REG (SImode, 0);
+     }
+ 
+   if (aggregate_value_p (TREE_TYPE (type)))
+     return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
+   else
+     return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
+ }
+ 
+ 
  void
! x86_output_mi_vcall_thunk (file, thunk, delta, vcall_index, function)
       FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
       int delta;
+      int vcall_index;
       tree function;
  {
    rtx xops[3];
  
    if (TARGET_64BIT)
      {
        int n = aggregate_value_p (TREE_TYPE (TREE_TYPE (function))) != 0;
+       xops[0] = GEN_INT (delta);
        xops[1] = gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
        output_asm_insn ("add{q} {%0, %1|%1, %0}", xops);
        if (flag_pic)
*************** x86_output_mi_thunk (file, delta, functi
*** 13898,13910 ****
      }
    else
      {
!       if (parm)
! 	xops[1] = gen_rtx_REG (SImode, 0);
!       else if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
! 	xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
!       else
! 	xops[1] = gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
!       output_asm_insn ("add{l} {%0, %1|%1, %0}", xops);
  
        if (flag_pic)
  	{
--- 13935,13983 ----
      }
    else
      {
!       /* Adjust the this parameter by a fixed constant.  */
!       if (delta)
! 	{
! 	  xops[0] = GEN_INT (delta);
! 	  xops[1] = ia32_this_parameter (function);
! 	  output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
! 	}
! 
!       /* Adjust the this parameter by a value stored in the vtable.  */
!       if (vcall_index)
! 	{
! 	  rtx this_parm;
! 
! 	  /* Put the this parameter into %eax.  */
! 	  this_parm = ia32_this_parameter (function);
! 	  if (!REG_P (this_parm))
! 	    {
! 	      xops[0] = this_parm;
! 	      xops[1] = gen_rtx_REG (Pmode, 0);
! 	      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
! 	    }
! 	  /* Load the virtual table pointer into %edx.  */
! 	  if (ix86_fntype_regparm (TREE_TYPE (function)) > 2)
! 	    error ("virtual function `%D' cannot have more than two register parameters",
! 		   function);
! 	  xops[0] = gen_rtx_MEM (Pmode, 
! 				 gen_rtx_REG (Pmode, 0));
! 	  xops[1] = gen_rtx_REG (Pmode, 1);
! 	  output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
! 	  /* Adjust the this parameter.  */
! 	  xops[0] = gen_rtx_MEM (SImode, 
! 				 plus_constant (gen_rtx_REG (Pmode, 1), 
! 						vcall_index));
! 	  xops[1] = gen_rtx_REG (Pmode, 0);
! 	  output_asm_insn ("add{l}\t{%0, %1|%1, %0}", xops);
! 	  /* Put the this parameter back where it came from.  */
! 	  if (!REG_P (this_parm))
! 	    {
! 	      xops[0] = gen_rtx_REG (Pmode, 0);
! 	      xops[1] = ia32_this_parameter (function);
! 	      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
! 	    }
! 	}
  
        if (flag_pic)
  	{
*************** x86_output_mi_thunk (file, delta, functi
*** 13928,13938 ****
  	}
        else
  	{
! 	  fprintf (file, "\tjmp ");
  	  assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
  	  fprintf (file, "\n");
  	}
      }
  }
  
  int
--- 14001,14022 ----
  	}
        else
  	{
! 	  fprintf (file, "\tjmp\t");
  	  assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
  	  fprintf (file, "\n");
  	}
      }
+ }
+ 
+ void
+ x86_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk;
+      int delta;
+      tree function;
+ {
+   x86_output_mi_vcall_thunk (file, thunk, delta, /*vcall_index=*/0, 
+ 			     function);
  }
  
  int
Index: config/i386/unix.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/unix.h,v
retrieving revision 1.22
diff -c -p -r1.22 unix.h
*** config/i386/unix.h	31 Jul 2002 23:18:44 -0000	1.22
--- config/i386/unix.h	18 Oct 2002 23:32:15 -0000
***************
*** 1,5 ****
  /* Definitions for Unix assembler syntax for the Intel 80386.
!    Copyright (C) 1988, 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
--- 1,5 ----
  /* Definitions for Unix assembler syntax for the Intel 80386.
!    Copyright (C) 1988, 1994, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
*************** Boston, MA 02111-1307, USA.  */
*** 68,72 ****
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
!     x86_output_mi_thunk (FILE, DELTA, FUNCTION);
--- 68,72 ----
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
! #define TARGET_ASM_OUTPUT_MI_VCALL_THUNK x86_output_mi_vcall_thunk
Index: config/i960/i960-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i960/i960-protos.h,v
retrieving revision 1.7
diff -c -p -r1.7 i960-protos.h
*** config/i960/i960-protos.h	16 Jul 2002 20:58:59 -0000	1.7
--- config/i960/i960-protos.h	18 Oct 2002 23:32:15 -0000
*************** extern void i960_setup_incoming_varargs 
*** 86,91 ****
--- 86,92 ----
  extern tree i960_build_va_list PARAMS ((void));
  extern int i960_final_reg_parm_stack_space PARAMS ((int, tree));
  extern int i960_reg_parm_stack_space PARAMS ((tree));
+ extern void i960_output_mi_thunk PARAMS ((FILE *, tree, int, tree));
  #endif /* TREE_CODE */
  
  extern int process_pragma PARAMS ((int(*)(void), void(*)(int), const char *));
Index: config/i960/i960.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i960/i960.c,v
retrieving revision 1.45
diff -c -p -r1.45 i960.c
*** config/i960/i960.c	16 Oct 2002 00:40:31 -0000	1.45
--- config/i960/i960.c	18 Oct 2002 23:32:15 -0000
*************** i960_scan_opcode (p)
*** 2824,2826 ****
--- 2824,2848 ----
        break;
      }
  }
+ 
+ void
+ i960_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
+      int delta;
+      tree function;
+ {
+   int d = delta;
+   if (d < 0 && d > -32)							
+     fprintf (file, "\tsubo %d,g0,g0\n", -d);				
+   else if (d > 0 && d < 32)						
+     fprintf (file, "\taddo %d,g0,g0\n", d);				
+   else									
+     {									
+       fprintf (file, "\tldconst %d,r5\n", d);				
+       fprintf (file, "\taddo r5,g0,g0\n");				
+     }									
+   fprintf (file, "\tbx ");						
+   assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));	
+   fprintf (file, "\n");							
+ }
Index: config/i960/i960.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i960/i960.h,v
retrieving revision 1.66
diff -c -p -r1.66 i960.h
*** config/i960/i960.h	7 Oct 2002 08:54:09 -0000	1.66
--- config/i960/i960.h	18 Oct 2002 23:32:16 -0000
*************** extern int rtx_equal_function_value_matt
*** 1466,1484 ****
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)	\
! do {									\
!   int d = (DELTA);							\
!   if (d < 0 && d > -32)							\
!     fprintf (FILE, "\tsubo %d,g0,g0\n", -d);				\
!   else if (d > 0 && d < 32)						\
!     fprintf (FILE, "\taddo %d,g0,g0\n", d);				\
!   else									\
!     {									\
!       fprintf (FILE, "\tldconst %d,r5\n", d);				\
!       fprintf (FILE, "\taddo r5,g0,g0\n");				\
!     }									\
!   fprintf (FILE, "\tbx ");						\
!   assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
!   fprintf (FILE, "\n");							\
! } while (0);
--- 1466,1469 ----
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK i960_output_mi_thunk
Index: config/ia64/ia64-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64-protos.h,v
retrieving revision 1.46
diff -c -p -r1.46 ia64-protos.h
*** config/ia64/ia64-protos.h	9 Sep 2002 22:03:31 -0000	1.46
--- config/ia64/ia64-protos.h	18 Oct 2002 23:32:16 -0000
***************
*** 1,5 ****
  /* Definitions of target machine for GNU compiler for IA-64.
!    Copyright (C) 1999, 2000 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
--- 1,5 ----
  /* Definitions of target machine for GNU compiler for IA-64.
!    Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
*************** extern int ia64_function_arg_pass_by_ref
*** 121,126 ****
--- 121,127 ----
  						       tree, int));
  extern int ia64_return_in_memory PARAMS((tree));
  extern void ia64_asm_output_external PARAMS((FILE *, tree, const char *));
+ extern void ia64_output_mi_thunk PARAMS((FILE *, tree, int, tree));
  #endif /* TREE_CODE */
  
  extern int ia64_register_move_cost PARAMS((enum machine_mode, enum reg_class,
Index: config/ia64/ia64.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.c,v
retrieving revision 1.188
diff -c -p -r1.188 ia64.c
*** config/ia64/ia64.c	29 Sep 2002 19:55:08 -0000	1.188
--- config/ia64/ia64.c	18 Oct 2002 23:32:17 -0000
*************** ia64_aix_select_rtx_section (mode, x, al
*** 8159,8162 ****
--- 8159,8197 ----
    flag_pic = save_pic;
  }
  
+ void
+ ia64_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
+      int delta;
+      tree function;
+ {
+   if (CONST_OK_FOR_I (delta))						
+     {									
+       fprintf (file, "\tadds r32 = ");					
+       fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));			
+       fprintf (file, ", r32\n");					
+     }									
+   else									
+     {									
+       if (CONST_OK_FOR_J (delta))					
+         {								
+           fprintf (file, "\taddl r2 = ");				
+           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));		
+           fprintf (file, ", r0\n");					
+         }								
+       else								
+         {								
+ 	  fprintf (file, "\tmovl r2 = ");				
+ 	  fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));		
+ 	  fprintf (file, "\n");						
+         }								
+       fprintf (file, "\t;;\n");						
+       fprintf (file, "\tadd r32 = r2, r32\n");				
+     }									
+   fprintf (file, "\tbr ");						
+   assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));	
+   fprintf (file, "\n");							
+ }
+ 
  #include "gt-ia64.h"
Index: config/ia64/ia64.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/ia64/ia64.h,v
retrieving revision 1.130
diff -c -p -r1.130 ia64.h
*** config/ia64/ia64.h	24 Sep 2002 12:48:56 -0000	1.130
--- config/ia64/ia64.h	18 Oct 2002 23:32:18 -0000
*************** do {									\
*** 1431,1465 ****
  /* A C compound statement that outputs the assembler code for a thunk function,
     used to implement C++ virtual function calls with multiple inheritance.  */
  
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
! do {									\
!   if (CONST_OK_FOR_I (DELTA))						\
!     {									\
!       fprintf (FILE, "\tadds r32 = ");					\
!       fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));			\
!       fprintf (FILE, ", r32\n");					\
!     }									\
!   else									\
!     {									\
!       if (CONST_OK_FOR_J (DELTA))					\
!         {								\
!           fprintf (FILE, "\taddl r2 = ");				\
!           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));		\
!           fprintf (FILE, ", r0\n");					\
!         }								\
!       else								\
!         {								\
! 	  fprintf (FILE, "\tmovl r2 = ");				\
! 	  fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));		\
! 	  fprintf (FILE, "\n");						\
!         }								\
!       fprintf (FILE, "\t;;\n");						\
!       fprintf (FILE, "\tadd r32 = r2, r32\n");				\
!     }									\
!   fprintf (FILE, "\tbr ");						\
!   assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
!   fprintf (FILE, "\n");							\
! } while (0)
  
  /* Output part N of a function descriptor for DECL.  For ia64, both
     words are emitted with a single relocation, so ignore N > 0.  */
--- 1431,1437 ----
  /* A C compound statement that outputs the assembler code for a thunk function,
     used to implement C++ virtual function calls with multiple inheritance.  */
  
! #define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
  
  /* Output part N of a function descriptor for DECL.  For ia64, both
     words are emitted with a single relocation, so ignore N > 0.  */
Index: config/m68k/linux.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68k/linux.h,v
retrieving revision 1.23
diff -c -p -r1.23 linux.h
*** config/m68k/linux.h	4 Oct 2002 02:19:40 -0000	1.23
--- config/m68k/linux.h	18 Oct 2002 23:32:18 -0000
*************** do {									\
*** 357,381 ****
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)	\
! do {									\
!   if (DELTA > 0 && DELTA <= 8)						\
!     asm_fprintf (FILE, "\taddq.l %I%d,4(%Rsp)\n", DELTA);		\
!   else if (DELTA < 0 && DELTA >= -8)					\
!     asm_fprintf (FILE, "\tsubq.l %I%d,4(%Rsp)\n", -DELTA);		\
!   else									\
!     asm_fprintf (FILE, "\tadd.l %I%d,4(%Rsp)\n", DELTA);		\
! 									\
!   if (flag_pic)								\
!     {									\
!       fprintf (FILE, "\tbra.l ");					\
!       assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
!       fprintf (FILE, "@PLTPC\n");					\
!     }									\
!   else									\
!     {									\
!       fprintf (FILE, "\tjmp ");						\
!       assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
!       fprintf (FILE, "\n");						\
!     }									\
! } while (0)
--- 357,360 ----
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
Index: config/m68k/m68k-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68k/m68k-protos.h,v
retrieving revision 1.4
diff -c -p -r1.4 m68k-protos.h
*** config/m68k/m68k-protos.h	6 Jul 2001 18:40:13 -0000	1.4
--- config/m68k/m68k-protos.h	18 Oct 2002 23:32:18 -0000
***************
*** 1,5 ****
  /* Definitions of target machine for GNU compiler.  Sun 68000/68020 version.
!    Copyright (C) 2000 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
--- 1,5 ----
  /* Definitions of target machine for GNU compiler.  Sun 68000/68020 version.
!    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
*************** extern int memory_src_operand PARAMS ((r
*** 63,68 ****
--- 63,72 ----
  extern int pcrel_address PARAMS ((rtx, enum machine_mode));
  extern rtx legitimize_pic_address PARAMS ((rtx, enum machine_mode, rtx));
  #endif /* RTX_CODE */
+ 
+ #ifdef TREE_CODE
+ extern void m68k_output_mi_thunk PARAMS ((FILE *, tree, int, tree));
+ #endif /* TREE_CODE */
  
  extern int flags_in_68881 PARAMS ((void));
  extern int use_return_insn PARAMS ((void));
Index: config/m68k/m68k.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68k/m68k.c,v
retrieving revision 1.69
diff -c -p -r1.69 m68k.c
*** config/m68k/m68k.c	4 Oct 2002 02:19:40 -0000	1.69
--- config/m68k/m68k.c	18 Oct 2002 23:32:19 -0000
*************** m68k_svr3_asm_out_constructor (symbol, p
*** 3835,3837 ****
--- 3835,3865 ----
    output_asm_insn (output_move_simode (xop), xop);
  }
  #endif
+ 
+ void
+ m68k_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
+      int delta;
+      tree function;
+ {
+   if (delta > 0 && delta <= 8)						
+     asm_fprintf (file, "\taddq.l %I%d,4(%Rsp)\n", delta);		
+   else if (delta < 0 && delta >= -8)					
+     asm_fprintf (file, "\tsubq.l %I%d,4(%Rsp)\n", -delta);		
+   else									
+     asm_fprintf (file, "\tadd.l %I%d,4(%Rsp)\n", delta);		
+ 									
+   if (flag_pic)								
+     {									
+       fprintf (file, "\tbra.l ");					
+       assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));	
+       fprintf (file, "@PLTPC\n");					
+     }									
+   else									
+     {									
+       fprintf (file, "\tjmp ");						
+       assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));	
+       fprintf (file, "\n");						
+     }									
+ }
Index: config/m68k/netbsd-elf.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/m68k/netbsd-elf.h,v
retrieving revision 1.7
diff -c -p -r1.7 netbsd-elf.h
*** config/m68k/netbsd-elf.h	4 Oct 2002 02:19:40 -0000	1.7
--- config/m68k/netbsd-elf.h	18 Oct 2002 23:32:19 -0000
*************** while (0)
*** 425,455 ****
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
  
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)	\
! do									\
!   {									\
!     if (DELTA > 0 && DELTA <= 8)					\
!       asm_fprintf (FILE, "\taddq.l %I%d,4(%Rsp)\n", DELTA);		\
!     else if (DELTA < 0 && DELTA >= -8)					\
!       asm_fprintf (FILE, "\tsubq.l %I%d,4(%Rsp)\n", -DELTA);		\
!     else								\
!       asm_fprintf (FILE, "\tadd.l %I%d,4(%Rsp)\n", DELTA);		\
! 									\
!     if (flag_pic)							\
!       {									\
! 	fprintf (FILE, "\tbra.l ");					\
! 	assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
! 	fprintf (FILE, "@PLTPC\n");					\
!       }									\
!     else								\
!       {									\
! 	fprintf (FILE, "\tjmp ");					\
! 	assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
! 	fprintf (FILE, "\n");						\
!       }									\
!   }									\
! while (0)
! 
  
  /* Output assembler code for a block containing the constant parts
     of a trampoline, leaving space for the variable parts.  */
--- 425,431 ----
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
  
! #define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk
  
  /* Output assembler code for a block containing the constant parts
     of a trampoline, leaving space for the variable parts.  */
Index: config/mmix/mmix.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mmix/mmix.h,v
retrieving revision 1.42
diff -c -p -r1.42 mmix.h
*** config/mmix/mmix.h	24 Sep 2002 12:49:00 -0000	1.42
--- config/mmix/mmix.h	18 Oct 2002 23:32:19 -0000
*************** typedef struct { int regs; int lib; } CU
*** 795,802 ****
  #define EPILOGUE_USES(REGNO) \
   ((REGNO) == MMIX_INCOMING_RETURN_ADDRESS_REGNUM)
  
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)	\
!  mmix_asm_output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
  
  
  /* Node: Profiling */
--- 795,801 ----
  #define EPILOGUE_USES(REGNO) \
   ((REGNO) == MMIX_INCOMING_RETURN_ADDRESS_REGNUM)
  
! #define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk
  
  
  /* Node: Profiling */
Index: config/pa/pa.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/pa/pa.h,v
retrieving revision 1.171
diff -c -p -r1.171 pa.h
*** config/pa/pa.h	3 Oct 2002 21:46:59 -0000	1.171
--- config/pa/pa.h	18 Oct 2002 23:32:19 -0000
*************** extern GTY(()) rtx hppa_compare_op0;
*** 897,904 ****
  extern GTY(()) rtx hppa_compare_op1;
  extern enum cmp_type hppa_branch_type;
  
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
!   pa_asm_output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
  
  /* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
     as assembly via FUNCTION_PROFILER.  Just output a local label.
--- 897,903 ----
  extern GTY(()) rtx hppa_compare_op1;
  extern enum cmp_type hppa_branch_type;
  
! #define TARGET_ASM_OUTPUT_MI_THUNK pa_asm_output_mi_thunk
  
  /* On HPPA, we emit profiling code as rtl via PROFILE_HOOK rather than
     as assembly via FUNCTION_PROFILER.  Just output a local label.
Index: config/rs6000/sysv4.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/sysv4.h,v
retrieving revision 1.110
diff -c -p -r1.110 sysv4.h
*** config/rs6000/sysv4.h	20 Sep 2002 23:47:00 -0000	1.110
--- config/rs6000/sysv4.h	18 Oct 2002 23:32:20 -0000
*************** extern int rs6000_pic_labelno;
*** 667,674 ****
      FUNCTION instead of jumping to it.  The generic approach does not support
      varargs.  */
  
! #define	ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
!   output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
  
  /* The USER_LABEL_PREFIX stuff is affected by the -fleading-underscore
     flag.  The LOCAL_LABEL_PREFIX variable is used by dbxelf.h.  */
--- 667,673 ----
      FUNCTION instead of jumping to it.  The generic approach does not support
      varargs.  */
  
! #define	TARGET_ASM_OUTPUT_MI_THUNK output_mi_thunk
  
  /* The USER_LABEL_PREFIX stuff is affected by the -fleading-underscore
     flag.  The LOCAL_LABEL_PREFIX variable is used by dbxelf.h.  */
Index: config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.15
diff -c -p -r1.15 s390-protos.h
*** config/s390/s390-protos.h	24 Sep 2002 16:05:49 -0000	1.15
--- config/s390/s390-protos.h	18 Oct 2002 23:32:20 -0000
***************
*** 1,5 ****
  /* Definitions of target machine for GNU compiler, for IBM S/390.
!    Copyright (C) 2000 Free Software Foundation, Inc.
     Contributed by Hartmut Penner (hpenner@de.ibm.com)
  
  This file is part of GNU CC.
--- 1,5 ----
  /* Definitions of target machine for GNU compiler, for IBM S/390.
!    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
     Contributed by Hartmut Penner (hpenner@de.ibm.com)
  
  This file is part of GNU CC.
*************** extern tree s390_build_va_list PARAMS ((
*** 86,91 ****
--- 86,92 ----
  extern rtx s390_function_arg PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int));
  extern void s390_va_start PARAMS ((tree, rtx));
  extern rtx s390_va_arg PARAMS ((tree, tree));
+ extern void s390_output_mi_thunk PARAMS ((FILE *, tree, int, tree));
  #endif /* RTX_CODE */
  #endif /* TREE_CODE */
  
Index: config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.58
diff -c -p -r1.58 s390.c
*** config/s390/s390.c	16 Oct 2002 19:09:25 -0000	1.58
--- config/s390/s390.c	18 Oct 2002 23:32:21 -0000
*************** s390_encode_section_info (decl, first)
*** 5582,5584 ****
--- 5582,5659 ----
  	}
      }
  }
+ 
+ void
+ s390_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
+      int delta;
+      tree function;
+ {
+   if (TARGET_64BIT)                                                           
+     {                                                                         
+       if (flag_pic)                                                           
+         {                                                                     
+           fprintf (file, "\tlarl  1,0f\n");                                   
+           fprintf (file, "\tagf   %d,0(1)\n",                                 
+                    aggregate_value_p (TREE_TYPE                               
+                                       (TREE_TYPE (function))) ? 3 :2 );       
+           fprintf (file, "\tlarl  1,");                                       
+           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));      
+           fprintf (file, "@GOTENT\n");                                        
+           fprintf (file, "\tlg    1,0(1)\n");                                 
+           fprintf (file, "\tbr    1\n");                                      
+           fprintf (file, "0:\t.long  ");	                              
+           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));                   
+           fprintf (file, "\n");			                              
+         }                                                                     
+       else                                                                    
+         {                                                                     
+           fprintf (file, "\tlarl  1,0f\n");                                   
+           fprintf (file, "\tagf   %d,0(1)\n",                                 
+           aggregate_value_p (TREE_TYPE                                        
+                              (TREE_TYPE (function))) ? 3 :2 );                
+           fprintf (file, "\tjg  ");                                           
+           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));      
+           fprintf (file, "\n");                                               
+           fprintf (file, "0:\t.long  ");		                      
+           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));                   
+           fprintf (file, "\n");			                              
+         }                                                                     
+     }                                                                         
+   else                                                                        
+     {                                                                         
+       if (flag_pic)                                                           
+         {                                                                     
+           fprintf (file, "\tbras  1,0f\n");                                   
+           fprintf (file, "\t.long _GLOBAL_OFFSET_TABLE_-.\n");                
+           fprintf (file, "\t.long  ");                                        
+           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));      
+           fprintf (file, "@GOT\n");                                           
+           fprintf (file, "\t.long  ");		                              
+           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));                   
+           fprintf (file, "\n");			                              
+           fprintf (file, "0:\tal  %d,8(1)\n",                                 
+                    aggregate_value_p (TREE_TYPE                               
+                                       (TREE_TYPE (function))) ? 3 : 2 );      
+           fprintf (file, "\tl     0,4(1)\n");                                 
+           fprintf (file, "\tal    1,0(1)\n");                                 
+           fprintf (file, "\talr   1,0\n");                                    
+           fprintf (file, "\tl     1,0(1)\n");                                 
+           fprintf (file, "\tbr    1\n");                                      
+         } else {                                                              
+           fprintf (file, "\tbras  1,0f\n");                                   
+           fprintf (file, "\t.long  ");                                        
+           assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));      
+           fprintf (file, "-.\n");                                             
+           fprintf (file, "\t.long  ");		                              
+           fprintf (file, HOST_WIDE_INT_PRINT_DEC, (delta));                   
+           fprintf (file, "\n");			                              
+           fprintf (file, "0:\tal  %d,4(1)\n",                                 
+                    aggregate_value_p (TREE_TYPE                               
+                                       (TREE_TYPE (function))) ? 3 : 2 );      
+           fprintf (file, "\tal    1,0(1)\n");                                 
+           fprintf (file, "\tbr    1\n");                                      
+        }                                                                      
+     }                                                                         
+ }
Index: config/s390/s390.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.h,v
retrieving revision 1.45
diff -c -p -r1.45 s390.h
*** config/s390/s390.h	16 Oct 2002 19:09:25 -0000	1.45
--- config/s390/s390.h	18 Oct 2002 23:32:21 -0000
*************** CUMULATIVE_ARGS;
*** 856,931 ****
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)              \
! do {                                                                          \
!   if (TARGET_64BIT)                                                           \
!     {                                                                         \
!       if (flag_pic)                                                           \
!         {                                                                     \
!           fprintf (FILE, "\tlarl  1,0f\n");                                   \
!           fprintf (FILE, "\tagf   %d,0(1)\n",                                 \
!                    aggregate_value_p (TREE_TYPE                               \
!                                       (TREE_TYPE (FUNCTION))) ? 3 :2 );       \
!           fprintf (FILE, "\tlarl  1,");                                       \
!           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
!           fprintf (FILE, "@GOTENT\n");                                        \
!           fprintf (FILE, "\tlg    1,0(1)\n");                                 \
!           fprintf (FILE, "\tbr    1\n");                                      \
!           fprintf (FILE, "0:\t.long  ");	                              \
!           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
!           fprintf (FILE, "\n");			                              \
!         }                                                                     \
!       else                                                                    \
!         {                                                                     \
!           fprintf (FILE, "\tlarl  1,0f\n");                                   \
!           fprintf (FILE, "\tagf   %d,0(1)\n",                                 \
!           aggregate_value_p (TREE_TYPE                                        \
!                              (TREE_TYPE (FUNCTION))) ? 3 :2 );                \
!           fprintf (FILE, "\tjg  ");                                           \
!           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
!           fprintf (FILE, "\n");                                               \
!           fprintf (FILE, "0:\t.long  ");		                      \
!           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
!           fprintf (FILE, "\n");			                              \
!         }                                                                     \
!     }                                                                         \
!   else                                                                        \
!     {                                                                         \
!       if (flag_pic)                                                           \
!         {                                                                     \
!           fprintf (FILE, "\tbras  1,0f\n");                                   \
!           fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_-.\n");                \
!           fprintf (FILE, "\t.long  ");                                        \
!           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
!           fprintf (FILE, "@GOT\n");                                           \
!           fprintf (FILE, "\t.long  ");		                              \
!           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
!           fprintf (FILE, "\n");			                              \
!           fprintf (FILE, "0:\tal  %d,8(1)\n",                                 \
!                    aggregate_value_p (TREE_TYPE                               \
!                                       (TREE_TYPE (FUNCTION))) ? 3 : 2 );      \
!           fprintf (FILE, "\tl     0,4(1)\n");                                 \
!           fprintf (FILE, "\tal    1,0(1)\n");                                 \
!           fprintf (FILE, "\talr   1,0\n");                                    \
!           fprintf (FILE, "\tl     1,0(1)\n");                                 \
!           fprintf (FILE, "\tbr    1\n");                                      \
!         } else {                                                              \
!           fprintf (FILE, "\tbras  1,0f\n");                                   \
!           fprintf (FILE, "\t.long  ");                                        \
!           assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));      \
!           fprintf (FILE, "-.\n");                                             \
!           fprintf (FILE, "\t.long  ");		                              \
!           fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, (DELTA));                   \
!           fprintf (FILE, "\n");			                              \
!           fprintf (FILE, "0:\tal  %d,4(1)\n",                                 \
!                    aggregate_value_p (TREE_TYPE                               \
!                                       (TREE_TYPE (FUNCTION))) ? 3 : 2 );      \
!           fprintf (FILE, "\tal    1,0(1)\n");                                 \
!           fprintf (FILE, "\tbr    1\n");                                      \
!        }                                                                      \
!     }                                                                         \
! } while (0)
! 
  
  /* Addressing modes, and classification of registers for them.  */
  
--- 856,862 ----
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
  
  /* Addressing modes, and classification of registers for them.  */
  
Index: config/sparc/sparc.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.h,v
retrieving revision 1.212
diff -c -p -r1.212 sparc.h
*** config/sparc/sparc.h	24 Sep 2002 12:49:04 -0000	1.212
--- config/sparc/sparc.h	18 Oct 2002 23:32:22 -0000
*************** do {									\
*** 2869,2876 ****
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
!   sparc_output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
  
  #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
    ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
--- 2869,2875 ----
  
  /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
     Used for C++ multiple inheritance.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
  
  #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
    ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')
Index: config/stormy16/stormy16.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/stormy16/stormy16.h,v
retrieving revision 1.62
diff -c -p -r1.62 stormy16.h
*** config/stormy16/stormy16.h	24 Sep 2002 12:49:04 -0000	1.62
--- config/stormy16/stormy16.h	18 Oct 2002 23:32:23 -0000
*************** enum reg_class
*** 1624,1631 ****
     frontend will generate a less efficient heavyweight thunk that calls
     FUNCTION instead of jumping to it.  The generic approach does not support
     varargs.  */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)	\
!   xstormy16_asm_output_mi_thunk (FILE, THUNK_FNDECL, DELTA, FUNCTION)
  
  
  /* Generating Code for Profiling.  */
--- 1624,1630 ----
     frontend will generate a less efficient heavyweight thunk that calls
     FUNCTION instead of jumping to it.  The generic approach does not support
     varargs.  */
! #define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk
  
  
  /* Generating Code for Profiling.  */
Index: config/vax/vax-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/vax/vax-protos.h,v
retrieving revision 1.5
diff -c -p -r1.5 vax-protos.h
*** config/vax/vax-protos.h	21 Sep 2002 16:10:36 -0000	1.5
--- config/vax/vax-protos.h	18 Oct 2002 23:32:23 -0000
***************
*** 1,5 ****
  /* Definitions of target machine for GNU compiler.  VAX version.
!    Copyright (C) 2000 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
--- 1,5 ----
  /* Definitions of target machine for GNU compiler.  VAX version.
!    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
  
  This file is part of GNU CC.
  
*************** extern int check_float_value PARAMS ((en
*** 36,41 ****
--- 36,42 ----
  
  #ifdef TREE_CODE
  extern void vms_check_external PARAMS ((tree, const char *, int));
+ extern void vax_output_mi_thunk PARAMS ((FILE *, tree, int, tree));
  #endif /* TREE_CODE */
  
  extern void vms_flush_pending_externals PARAMS ((FILE *));
Index: config/vax/vax.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/vax/vax.c,v
retrieving revision 1.35
diff -c -p -r1.35 vax.c
*** config/vax/vax.c	4 Oct 2002 05:23:12 -0000	1.35
--- config/vax/vax.c	18 Oct 2002 23:32:23 -0000
*************** reg_was_0_p (insn, op)
*** 992,994 ****
--- 992,1008 ----
  	  /* Make sure the reg hasn't been clobbered.  */
  	  && ! reg_set_between_p (op, XEXP (link, 0), insn));
  }
+ 
+ void
+ vax_output_mi_thunk (file, thunk, delta, function)
+      FILE *file;
+      tree thunk ATTRIBUTE_UNUSED;
+      int delta;
+      tree function;
+ {
+   fprintf (file, "\t.word 0x0ffc\n");					
+   asm_fprintf (file, "\taddl2 $%d,4(%Rap)\n", delta);			
+   fprintf (file, "\tjmp ");						
+   assemble_name (file,  XSTR (XEXP (DECL_RTL (function), 0), 0));	
+   fprintf (file, "+2\n");						
+ }
Index: config/vax/vax.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/vax/vax.h,v
retrieving revision 1.52
diff -c -p -r1.52 vax.h
*** config/vax/vax.h	16 Oct 2002 00:40:35 -0000	1.52
--- config/vax/vax.h	18 Oct 2002 23:32:23 -0000
*************** enum reg_class { NO_REGS, ALL_REGS, LIM_
*** 1161,1174 ****
  	addl2	$DELTA, 4(ap)	#adjust first argument
  	jmp	FUNCTION+2	#jump beyond FUNCTION's entry mask
   */
! #define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION)	\
! do {									\
!   fprintf (FILE, "\t.word 0x0ffc\n");					\
!   asm_fprintf (FILE, "\taddl2 $%d,4(%Rap)\n", DELTA);			\
!   fprintf (FILE, "\tjmp ");						\
!   assemble_name (FILE,  XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0));	\
!   fprintf (FILE, "+2\n");						\
! } while (0)
  
  /* Print an instruction operand X on file FILE.
     CODE is the code from the %-spec that requested printing this operand;
--- 1161,1167 ----
  	addl2	$DELTA, 4(ap)	#adjust first argument
  	jmp	FUNCTION+2	#jump beyond FUNCTION's entry mask
   */
! #define ASM_OUTPUT_MI_THUNK vax_output_mi_thunk
  
  /* Print an instruction operand X on file FILE.
     CODE is the code from the %-spec that requested printing this operand;
Index: cp/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Make-lang.in,v
retrieving revision 1.124
diff -c -p -r1.124 Make-lang.in
*** cp/Make-lang.in	17 Sep 2002 07:09:49 -0000	1.124
--- cp/Make-lang.in	18 Oct 2002 23:32:27 -0000
*************** cp/friend.o: cp/friend.c $(CXX_TREE_H) f
*** 246,252 ****
  cp/init.o: cp/init.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
    $(GGC_H) except.h
  cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
!   $(TM_P_H)
  cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
  cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
  cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
--- 246,252 ----
  cp/init.o: cp/init.c $(CXX_TREE_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
    $(GGC_H) except.h
  cp/method.o: cp/method.c $(CXX_TREE_H) toplev.h $(GGC_H) $(RTL_H) $(EXPR_H) \
!   $(TM_P_H) $(TARGET_H)
  cp/cvt.o: cp/cvt.c $(CXX_TREE_H) cp/decl.h flags.h toplev.h convert.h
  cp/search.o: cp/search.c $(CXX_TREE_H) stack.h flags.h toplev.h $(RTL_H)
  cp/tree.o: cp/tree.c $(CXX_TREE_H) flags.h toplev.h $(GGC_H) $(RTL_H) \
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.233
diff -c -p -r1.233 method.c
*** cp/method.c	16 Oct 2002 18:58:35 -0000	1.233
--- cp/method.c	18 Oct 2002 23:32:27 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 34,39 ****
--- 34,40 ----
  #include "toplev.h"
  #include "ggc.h"
  #include "tm_p.h"
+ #include "target.h"
  
  /* Various flags to control the mangling process.  */
  
*************** use_thunk (thunk_fndecl, emit_p)
*** 408,415 ****
    BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) 
      = DECL_ARGUMENTS (thunk_fndecl);
  
! #ifdef ASM_OUTPUT_MI_THUNK
!   if (!vcall_offset)
      {
        const char *fnname;
        current_function_decl = thunk_fndecl;
--- 409,416 ----
    BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) 
      = DECL_ARGUMENTS (thunk_fndecl);
  
!   if (targetm.asm_out.output_mi_vcall_thunk
!       || (targetm.asm_out.output_mi_thunk && !vcall_offset))
      {
        const char *fnname;
        current_function_decl = thunk_fndecl;
*************** use_thunk (thunk_fndecl, emit_p)
*** 419,436 ****
        init_function_start (thunk_fndecl, input_filename, lineno);
        current_function_is_thunk = 1;
        assemble_start_function (thunk_fndecl, fnname);
!       ASM_OUTPUT_MI_THUNK (asm_out_file, thunk_fndecl, delta, function);
        assemble_end_function (thunk_fndecl, fnname);
        current_function_decl = 0;
        cfun = 0;
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
      }
    else
- #endif /* ASM_OUTPUT_MI_THUNK */
      {
!       /* If we don't have the necessary macro for efficient thunks, generate
! 	 a thunk function that just makes a call to the real function.
! 	 Unfortunately, this doesn't work for varargs.  */
  
        tree a, t;
  
--- 420,448 ----
        init_function_start (thunk_fndecl, input_filename, lineno);
        current_function_is_thunk = 1;
        assemble_start_function (thunk_fndecl, fnname);
!       if (targetm.asm_out.output_mi_vcall_thunk)
! 	{
! 	  int vcall_value = (vcall_offset
! 			     ? tree_low_cst (vcall_offset, /*pos=*/0)
! 			     : 0);
! 	  targetm.asm_out.output_mi_vcall_thunk (asm_out_file, 
! 						 thunk_fndecl, delta, 
! 						 vcall_value,
! 						 function);
! 	}
!       else
! 	targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, 
! 					 delta, function);
        assemble_end_function (thunk_fndecl, fnname);
        current_function_decl = 0;
        cfun = 0;
        TREE_ASM_WRITTEN (thunk_fndecl) = 1;
      }
    else
      {
!       /* If we don't have the necessary code for efficient thunks,
! 	 generate a thunk function that just makes a call to the real
! 	 function.  Unfortunately, this doesn't work for varargs.  */
  
        tree a, t;
  
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.177
diff -c -p -r1.177 tm.texi
*** doc/tm.texi	16 Oct 2002 00:40:38 -0000	1.177
--- doc/tm.texi	18 Oct 2002 23:32:30 -0000
*************** outputting the insns in this list, usual
*** 4151,4159 ****
  You need not define this macro if you did not define
  @code{DELAY_SLOTS_FOR_EPILOGUE}.
  
! @findex ASM_OUTPUT_MI_THUNK
! @item ASM_OUTPUT_MI_THUNK (@var{file}, @var{thunk_fndecl}, @var{delta}, @var{function})
! A C compound statement that outputs the assembler code for a thunk
  function, used to implement C++ virtual function calls with multiple
  inheritance.  The thunk acts as a wrapper around a virtual function,
  adjusting the implicit object parameter before handing control off to
--- 4151,4161 ----
  You need not define this macro if you did not define
  @code{DELAY_SLOTS_FOR_EPILOGUE}.
  
! @end table
! 
! @findex TARGET_ASM_OUTPUT_MI_THUNK
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, int @var{delta}, tree @var{function})
! A function that outputs the assembler code for a thunk
  function, used to implement C++ virtual function calls with multiple
  inheritance.  The thunk acts as a wrapper around a virtual function,
  adjusting the implicit object parameter before handing control off to
*************** If you do not define this macro, the tar
*** 4184,4190 ****
  front end will generate a less efficient heavyweight thunk that calls
  @var{function} instead of jumping to it.  The generic approach does
  not support varargs.
! @end table
  
  @node Profiling
  @subsection Generating Code for Profiling
--- 4186,4209 ----
  front end will generate a less efficient heavyweight thunk that calls
  @var{function} instead of jumping to it.  The generic approach does
  not support varargs.
! @end deftypefn
! 
! @findex TARGET_ASM_OUTPUT_MI_VCALL_THUNK
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_VCALL_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, int @var{delta}, int @var{vcall_offset}, tree @var{function})
! A function like @code{TARGET_ASM_OUTPUT_MI_THUNK}, except that if
! @var{vcall_offset} is non-zero, an additional adjustment should be made
! after adding @code{delta}.  In particular, if @var{p} is the
! adjusted pointer, the following adjustment should be made:
! 
! @example
! p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]
! @end example
! 
! @noindent
! If this function is defined, it will always be used in place of
! @code{TARGET_ASM_OUTPUT_MI_THUNK}.
! 
! @end deftypefn
  
  @node Profiling
  @subsection Generating Code for Profiling
Index: testsuite/g++.dg/inherit/thunk1.C
===================================================================
RCS file: testsuite/g++.dg/inherit/thunk1.C
diff -N testsuite/g++.dg/inherit/thunk1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/inherit/thunk1.C	18 Oct 2002 23:32:31 -0000
***************
*** 0 ****
--- 1,41 ----
+ // { dg-do run }
+ 
+ #include <stdarg.h>
+ 
+ extern "C" void abort ();
+ 
+ struct A {
+   virtual void f (int, ...) {}
+   int i;
+ };
+ 
+ struct B : virtual public A {
+ };
+ 
+ struct C : public B {
+   C ();
+   virtual void f (int, ...);
+ };
+ 
+ extern C* cp;
+ 
+ C::C () { cp = this; }
+ 
+ void C::f (int i, ...) {
+   if (this != cp)
+     abort ();
+   va_list ap;
+   if (i != 3)
+     abort ();
+   va_start (ap, i);
+   if (va_arg (ap, int) != 7)
+     abort ();
+   va_end (ap);
+ }
+ 
+ C* cp = new C;
+ 
+ int main () 
+ {
+   cp->f (3, 7);
+ }



More information about the Gcc-patches mailing list