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