diff options
author | Eric Botcazou <ebotcazou@libertysurf.fr> | 2004-10-13 16:04:32 +0200 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2004-10-13 14:04:32 +0000 |
commit | b9bf58e5fa4b31a077b5fe0711b7884f5d0148ed (patch) | |
tree | 2a05cc75f88b727c5ea8b1c92233af46aedb9734 /gcc | |
parent | 2a10039cc9a027f15afbad9fa47455cfe9f10c3e (diff) | |
download | gcc-b9bf58e5fa4b31a077b5fe0711b7884f5d0148ed.zip gcc-b9bf58e5fa4b31a077b5fe0711b7884f5d0148ed.tar.gz gcc-b9bf58e5fa4b31a077b5fe0711b7884f5d0148ed.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.c | 105 | ||||
-rw-r--r-- | gcc/config/sparc/sparc.md | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/inherit/thunk1.C | 2 |
5 files changed, 105 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 3ecb586..923175c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +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> * tree-dump.c (dump_options): Remove TDF_TREE, TDF_RTL, diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 3f75954..3371db9 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -334,6 +334,8 @@ static bool sparc_function_ok_for_sibcall (tree, tree); static void sparc_init_libfuncs (void); static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, 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 bool sparc_cannot_force_const_mem (rtx); static rtx sparc_tls_get_addr (void); @@ -425,7 +427,7 @@ enum processor_type sparc_cpu; #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK sparc_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 #define TARGET_RTX_COSTS sparc_rtx_costs @@ -8511,23 +8513,25 @@ emit_and_preserve (rtx seq, rtx reg) rtx slot = gen_rtx_MEM (word_mode, 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 (seq); 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. - Used for C++ multiple inheritance. */ +/* Output the assembler code for a thunk function. THUNK_DECL is the + 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 sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, - HOST_WIDE_INT delta, - HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, tree function) { - rtx this, insn, funexp, delta_rtx; + rtx this, insn, funexp; unsigned int int_arg_first; reload_completed = 1; @@ -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 a register first. */ - delta_rtx = GEN_INT (delta); - if (!SPARC_SIMM13_P (delta)) + if (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); - if (input_operand (delta_rtx, GET_MODE (scratch))) - emit_insn (gen_rtx_SET (VOIDmode, scratch, delta_rtx)); + if (vcall_offset >= 0) + 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 { - if (TARGET_ARCH64) - sparc_emit_set_const64 (scratch, delta_rtx); - else - sparc_emit_set_const32 (scratch, delta_rtx); + rtx increment = GEN_INT (-4096); + + /* VCALL_OFFSET is a negative number whose typical range can be + 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, - gen_rtx_PLUS (Pmode, this, delta_rtx))); + /* THIS += *(*THIS + VCALL_OFFSET). */ + emit_insn (gen_add2_insn (this, scratch)); + } /* Generate a tail call to the target function. */ if (! TREE_USED (function)) @@ -8674,6 +8724,19 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, 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'. */ static struct machine_function * diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 182afb9..1000fbb 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -2099,7 +2099,6 @@ if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode)) ; else if (TARGET_ARCH64 - && CONSTANT_P (operands[1]) && GET_CODE (operands[1]) != HIGH && GET_CODE (operands[1]) != LO_SUM) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d08d005..a87db9a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +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> PR tree-optimization/17724 diff --git a/gcc/testsuite/g++.dg/inherit/thunk1.C b/gcc/testsuite/g++.dg/inherit/thunk1.C index 4426419..3bbd050 100644 --- a/gcc/testsuite/g++.dg/inherit/thunk1.C +++ b/gcc/testsuite/g++.dg/inherit/thunk1.C @@ -1,4 +1,4 @@ -// { 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> |