target-def.h (TARGET_ASM_OUTPUT_MI_THUNK): Default to NULL.

* 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.

From-SVN: r58293
This commit is contained in:
Mark Mitchell 2002-10-18 23:35:40 +00:00 committed by Mark Mitchell
parent 90e021a061
commit 483ab821df
38 changed files with 527 additions and 269 deletions

View File

@ -1,3 +1,64 @@
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 Jason Thorpe <thorpej@wasabisystems.com>
* config/netbsd.h (NETBSD_ENABLE_EXECUTE_STACK): Define

View File

@ -2141,5 +2141,4 @@ do { \
/* 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)
#define TARGET_ASM_OUTPUT_MI_THUNK alpha_output_mi_thunk_osf

View File

@ -1,5 +1,5 @@
/* Prototypes for exported functions defined in arm.c and pe.c
Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
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)
@ -194,6 +194,7 @@ extern int arm_dllexport_p PARAMS ((tree));
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));

View File

@ -11130,3 +11130,38 @@ arm_encode_section_info (decl, first)
}
}
#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);
}

View File

@ -2697,36 +2697,7 @@ extern int making_const_table;
/* 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)
#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. */

View File

@ -1013,8 +1013,7 @@ struct cum_args {int regs;};
#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)
#define TARGET_ASM_OUTPUT_MI_THUNK cris_asm_output_mi_thunk
/* Node: Profiling */

View File

@ -2110,8 +2110,7 @@ struct machine_function GTY(())
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)
#define TARGET_ASM_OUTPUT_MI_THUNK frv_asm_output_mi_thunk
/* Generating Code for Profiling. */

View File

@ -211,7 +211,8 @@ extern tree ix86_handle_shared_attribute PARAMS ((tree *, tree, tree, int, bool
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 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

View File

@ -750,6 +750,7 @@ static int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
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
{
@ -788,6 +789,7 @@ static unsigned int ix86_select_alt_pic_regnum PARAMS ((void));
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 *));
@ -1295,6 +1297,10 @@ override_options ()
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
@ -1431,6 +1437,21 @@ ix86_comp_type_attributes (type1, type2)
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),
@ -1474,15 +1495,7 @@ ix86_return_pops_args (fundecl, funtype, size)
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)));
}
int nregs = ix86_fntype_regparm (funtype);
if (!nregs)
return GET_MODE_SIZE (Pmode);
@ -13860,27 +13873,51 @@ x86_order_regs_for_local_alloc ()
reg_alloc_order [pos++] = 0;
}
void
x86_output_mi_thunk (file, delta, function)
FILE *file;
int delta;
/* 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;
{
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[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)
@ -13898,13 +13935,49 @@ x86_output_mi_thunk (file, delta, function)
}
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);
/* 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)
{
@ -13928,13 +14001,24 @@ x86_output_mi_thunk (file, delta, function)
}
else
{
fprintf (file, "\tjmp ");
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
x86_field_alignment (field, computed)
tree field;

View File

@ -1,5 +1,5 @@
/* Definitions for Unix assembler syntax for the Intel 80386.
Copyright (C) 1988, 1994, 1999, 2000, 2001 Free Software Foundation, Inc.
Copyright (C) 1988, 1994, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -68,5 +68,5 @@ Boston, MA 02111-1307, USA. */
/* 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);
#define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk
#define TARGET_ASM_OUTPUT_MI_VCALL_THUNK x86_output_mi_vcall_thunk

View File

@ -86,6 +86,7 @@ extern void i960_setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *, enum machine
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 *));

View File

@ -2824,3 +2824,25 @@ i960_scan_opcode (p)
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");
}

View File

@ -1466,19 +1466,4 @@ extern int rtx_equal_function_value_matters;
/* 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);
#define ASM_OUTPUT_MI_THUNK i960_output_mi_thunk

View File

@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler for IA-64.
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -121,6 +121,7 @@ extern int ia64_function_arg_pass_by_reference PARAMS((CUMULATIVE_ARGS *,
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,

View File

@ -8159,4 +8159,39 @@ ia64_aix_select_rtx_section (mode, x, align)
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"

View File

@ -1431,35 +1431,7 @@ do { \
/* 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)
#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. */

View File

@ -357,25 +357,4 @@ do { \
/* 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)
#define TARGET_ASM_OUTPUT_MI_THUNK m68k_output_mi_thunk

View File

@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. Sun 68000/68020 version.
Copyright (C) 2000 Free Software Foundation, Inc.
Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -64,6 +64,10 @@ 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));
extern void override_options PARAMS ((void));

View File

@ -3835,3 +3835,31 @@ m68k_svr3_asm_out_constructor (symbol, priority)
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");
}
}

View File

@ -425,31 +425,7 @@ while (0)
/* 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)
#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. */

View File

@ -795,8 +795,7 @@ typedef struct { int regs; int lib; } CUMULATIVE_ARGS;
#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)
#define TARGET_ASM_OUTPUT_MI_THUNK mmix_asm_output_mi_thunk
/* Node: Profiling */

View File

@ -897,8 +897,7 @@ extern GTY(()) rtx hppa_compare_op0;
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)
#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.

View File

@ -667,8 +667,7 @@ extern int rs6000_pic_labelno;
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)
#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. */

View File

@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM S/390.
Copyright (C) 2000 Free Software Foundation, Inc.
Copyright (C) 2000, 2002 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com)
This file is part of GNU CC.
@ -86,6 +86,7 @@ extern tree s390_build_va_list PARAMS ((void));
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 */

View File

@ -5582,3 +5582,78 @@ s390_encode_section_info (decl, first)
}
}
}
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");
}
}
}

View File

@ -856,76 +856,7 @@ CUMULATIVE_ARGS;
/* 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)
#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
/* Addressing modes, and classification of registers for them. */

View File

@ -2869,8 +2869,7 @@ do { \
/* 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 TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' || (CHAR) == '(' || (CHAR) == '_')

View File

@ -1624,8 +1624,7 @@ enum reg_class
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)
#define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk
/* Generating Code for Profiling. */

View File

@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler. VAX version.
Copyright (C) 2000 Free Software Foundation, Inc.
Copyright (C) 2000, 2002 Free Software Foundation, Inc.
This file is part of GNU CC.
@ -36,6 +36,7 @@ extern int check_float_value PARAMS ((enum machine_mode, REAL_VALUE_TYPE *, int)
#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 *));

View File

@ -992,3 +992,17 @@ reg_was_0_p (insn, op)
/* 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");
}

View File

@ -1161,14 +1161,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
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)
#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;

View File

@ -1,3 +1,9 @@
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.
2002-10-18 Mark Mitchell <mark@codesourcery.com>
* class.c (base_derived_from): Make sure return value is a bool.

View File

@ -246,7 +246,7 @@ cp/friend.o: cp/friend.c $(CXX_TREE_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
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)
$(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) \

View File

@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "ggc.h"
#include "tm_p.h"
#include "target.h"
/* Various flags to control the mangling process. */
@ -408,8 +409,8 @@ use_thunk (thunk_fndecl, emit_p)
BLOCK_VARS (DECL_INITIAL (thunk_fndecl))
= DECL_ARGUMENTS (thunk_fndecl);
#ifdef ASM_OUTPUT_MI_THUNK
if (!vcall_offset)
if (targetm.asm_out.output_mi_vcall_thunk
|| (targetm.asm_out.output_mi_thunk && !vcall_offset))
{
const char *fnname;
current_function_decl = thunk_fndecl;
@ -419,18 +420,29 @@ use_thunk (thunk_fndecl, emit_p)
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);
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
#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. */
/* 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;

View File

@ -4151,9 +4151,11 @@ outputting the insns in this list, usually by calling
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
@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
@ -4184,7 +4186,24 @@ If you do not define this macro, the target-independent code in the C++
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
@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

View File

@ -103,6 +103,14 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# 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
@ -173,7 +181,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_ASM_SELECT_RTX_SECTION, \
TARGET_ASM_UNIQUE_SECTION, \
TARGET_ASM_CONSTRUCTOR, \
TARGET_ASM_DESTRUCTOR}
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. */

View File

@ -119,6 +119,13 @@ struct gcc_target
/* 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. */

View File

@ -0,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);
}