mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-25 01:29:27 +08:00
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:
parent
90e021a061
commit
483ab821df
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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 */
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 *));
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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. */
|
||||
|
@ -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 */
|
||||
|
@ -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.
|
||||
|
@ -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. */
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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) == '_')
|
||||
|
@ -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. */
|
||||
|
@ -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 *));
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
|
41
gcc/testsuite/g++.dg/inherit/thunk1.C
Normal file
41
gcc/testsuite/g++.dg/inherit/thunk1.C
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user