Commit b9bf58e5 by Eric Botcazou Committed by Eric Botcazou

re PR target/14454 (virtual function with vararg won't compile)

	PR target/14454
	* config/sparc/sparc.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Set to
	sparc_can_output_mi_thunk.
	(sparc_output_mi_thunk): Simplify handling of delta offset.  Add
	handling of vcall offset.
	(sparc_can_output_mi_thunk): New predicate.
	* doc/tm.texi (TARGET_ASM_OUTPUT_MI_THUNK): Document VCALL_OFFSET.
	(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Delete.
	(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New target hook.

	* config/sparc/sparc.c (emit_and_preserve): Preserve stack alignment.

	* config/sparc/sparc.md (movdi): Remove redundant test.

From-SVN: r88985
parent 2a10039c
2004-10-13 Eric Botcazou <ebotcazou@libertysurf.fr>
PR target/14454
* config/sparc/sparc.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Set to
sparc_can_output_mi_thunk.
(sparc_output_mi_thunk): Simplify handling of delta offset. Add
handling of vcall offset.
(sparc_can_output_mi_thunk): New predicate.
* doc/tm.texi (TARGET_ASM_OUTPUT_MI_THUNK): Document VCALL_OFFSET.
(TARGET_ASM_OUTPUT_MI_VCALL_THUNK): Delete.
(TARGET_ASM_CAN_OUTPUT_MI_THUNK): New target hook.
* config/sparc/sparc.c (emit_and_preserve): Preserve stack alignment.
* config/sparc/sparc.md (movdi): Remove redundant test.
2004-10-13 Paolo Bonzini <bonzini@gnu.org> 2004-10-13 Paolo Bonzini <bonzini@gnu.org>
* tree-dump.c (dump_options): Remove TDF_TREE, TDF_RTL, * tree-dump.c (dump_options): Remove TDF_TREE, TDF_RTL,
......
...@@ -334,6 +334,8 @@ static bool sparc_function_ok_for_sibcall (tree, tree); ...@@ -334,6 +334,8 @@ static bool sparc_function_ok_for_sibcall (tree, tree);
static void sparc_init_libfuncs (void); static void sparc_init_libfuncs (void);
static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree); HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static struct machine_function * sparc_init_machine_status (void); static struct machine_function * sparc_init_machine_status (void);
static bool sparc_cannot_force_const_mem (rtx); static bool sparc_cannot_force_const_mem (rtx);
static rtx sparc_tls_get_addr (void); static rtx sparc_tls_get_addr (void);
...@@ -425,7 +427,7 @@ enum processor_type sparc_cpu; ...@@ -425,7 +427,7 @@ enum processor_type sparc_cpu;
#undef TARGET_ASM_OUTPUT_MI_THUNK #undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk #define TARGET_ASM_OUTPUT_MI_THUNK sparc_output_mi_thunk
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall #define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
#undef TARGET_RTX_COSTS #undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs #define TARGET_RTX_COSTS sparc_rtx_costs
...@@ -8511,23 +8513,25 @@ emit_and_preserve (rtx seq, rtx reg) ...@@ -8511,23 +8513,25 @@ emit_and_preserve (rtx seq, rtx reg)
rtx slot = gen_rtx_MEM (word_mode, rtx slot = gen_rtx_MEM (word_mode,
plus_constant (stack_pointer_rtx, SPARC_STACK_BIAS)); plus_constant (stack_pointer_rtx, SPARC_STACK_BIAS));
emit_stack_pointer_decrement (GEN_INT (UNITS_PER_WORD)); emit_stack_pointer_decrement (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT));
emit_insn (gen_rtx_SET (VOIDmode, slot, reg)); emit_insn (gen_rtx_SET (VOIDmode, slot, reg));
emit_insn (seq); emit_insn (seq);
emit_insn (gen_rtx_SET (VOIDmode, reg, slot)); emit_insn (gen_rtx_SET (VOIDmode, reg, slot));
emit_stack_pointer_increment (GEN_INT (UNITS_PER_WORD)); emit_stack_pointer_increment (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT));
} }
/* Output code to add DELTA to the first argument, and then jump to FUNCTION. /* Output the assembler code for a thunk function. THUNK_DECL is the
Used for C++ multiple inheritance. */ declaration for the thunk function itself, FUNCTION is the decl for
the target function. DELTA is an immediate constant offset to be
added to THIS. If VCALL_OFFSET is nonzero, the word at address
(*THIS + VCALL_OFFSET) should be additionally added to THIS. */
static void static void
sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta, HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function) tree function)
{ {
rtx this, insn, funexp, delta_rtx; rtx this, insn, funexp;
unsigned int int_arg_first; unsigned int int_arg_first;
reload_completed = 1; reload_completed = 1;
...@@ -8566,27 +8570,73 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, ...@@ -8566,27 +8570,73 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Add DELTA. When possible use a plain add, otherwise load it into /* Add DELTA. When possible use a plain add, otherwise load it into
a register first. */ a register first. */
delta_rtx = GEN_INT (delta); if (delta)
if (!SPARC_SIMM13_P (delta))
{ {
rtx delta_rtx = GEN_INT (delta);
if (! SPARC_SIMM13_P (delta))
{
rtx scratch = gen_rtx_REG (Pmode, 1);
emit_move_insn (scratch, delta_rtx);
delta_rtx = scratch;
}
/* THIS += DELTA. */
emit_insn (gen_add2_insn (this, delta_rtx));
}
/* Add the word at address (*THIS + VCALL_OFFSET). */
if (vcall_offset)
{
rtx vcall_offset_rtx = GEN_INT (vcall_offset);
rtx scratch = gen_rtx_REG (Pmode, 1); rtx scratch = gen_rtx_REG (Pmode, 1);
if (input_operand (delta_rtx, GET_MODE (scratch))) if (vcall_offset >= 0)
emit_insn (gen_rtx_SET (VOIDmode, scratch, delta_rtx)); abort ();
/* SCRATCH = *THIS. */
emit_move_insn (scratch, gen_rtx_MEM (Pmode, this));
/* Prepare for adding VCALL_OFFSET. The difficulty is that we
may not have any available scratch register at this point. */
if (SPARC_SIMM13_P (vcall_offset))
;
/* This is the case if ARCH64 (unless -ffixed-g5 is passed). */
else if (! fixed_regs[5]
/* The below sequence is made up of at least 2 insns,
while the default method may need only one. */
&& vcall_offset < -8192)
{
rtx scratch2 = gen_rtx_REG (Pmode, 5);
emit_move_insn (scratch2, vcall_offset_rtx);
vcall_offset_rtx = scratch2;
}
else else
{ {
if (TARGET_ARCH64) rtx increment = GEN_INT (-4096);
sparc_emit_set_const64 (scratch, delta_rtx);
else /* VCALL_OFFSET is a negative number whose typical range can be
sparc_emit_set_const32 (scratch, delta_rtx); estimated as -32768..0 in 32-bit mode. In almost all cases
it is therefore cheaper to emit multiple add insns than
spilling and loading the constant into a register (at least
6 insns). */
while (! SPARC_SIMM13_P (vcall_offset))
{
emit_insn (gen_add2_insn (scratch, increment));
vcall_offset += 4096;
}
vcall_offset_rtx = GEN_INT (vcall_offset); /* cannot be 0 */
} }
delta_rtx = scratch; /* SCRATCH = *(*THIS + VCALL_OFFSET). */
} emit_move_insn (scratch, gen_rtx_MEM (Pmode,
gen_rtx_PLUS (Pmode,
scratch,
vcall_offset_rtx)));
emit_insn (gen_rtx_SET (VOIDmode, /* THIS += *(*THIS + VCALL_OFFSET). */
this, emit_insn (gen_add2_insn (this, scratch));
gen_rtx_PLUS (Pmode, this, delta_rtx))); }
/* Generate a tail call to the target function. */ /* Generate a tail call to the target function. */
if (! TREE_USED (function)) if (! TREE_USED (function))
...@@ -8674,6 +8724,19 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, ...@@ -8674,6 +8724,19 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
no_new_pseudos = 0; no_new_pseudos = 0;
} }
/* Return true if sparc_output_mi_thunk would be able to output the
assembler code for the thunk function specified by the arguments
it is passed, and false otherwise. */
static bool
sparc_can_output_mi_thunk (tree thunk_fndecl ATTRIBUTE_UNUSED,
HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
HOST_WIDE_INT vcall_offset,
tree function ATTRIBUTE_UNUSED)
{
/* Bound the loop used in the default method above. */
return (vcall_offset >= -32768 || ! fixed_regs[5]);
}
/* How to allocate a 'struct machine_function'. */ /* How to allocate a 'struct machine_function'. */
static struct machine_function * static struct machine_function *
......
...@@ -2099,7 +2099,6 @@ ...@@ -2099,7 +2099,6 @@
if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode)) if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
; ;
else if (TARGET_ARCH64 else if (TARGET_ARCH64
&& CONSTANT_P (operands[1])
&& GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != HIGH
&& GET_CODE (operands[1]) != LO_SUM) && GET_CODE (operands[1]) != LO_SUM)
{ {
......
2004-10-13 Eric Botcazou <ebotcazou@libertysurf.fr>
* g++.dg/inherit/thunk1.C: Run on the SPARC.
2004-10-13 Jakub Jelinek <jakub@redhat.com> 2004-10-13 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/17724 PR tree-optimization/17724
......
// { dg-do run { target i?86-*-* x86_64-*-* s390*-*-* alpha*-*-* ia64-*-* } } // { dg-do run { target i?86-*-* x86_64-*-* s390*-*-* alpha*-*-* ia64-*-* sparc*-*-* } }
#include <stdarg.h> #include <stdarg.h>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment