* [RFC] Fix PR target/14454
@ 2004-10-10 18:27 Eric Botcazou
2004-10-10 18:31 ` John David Anglin
2004-10-11 21:08 ` Richard Henderson
0 siblings, 2 replies; 4+ messages in thread
From: Eric Botcazou @ 2004-10-10 18:27 UTC (permalink / raw)
To: gcc-patches; +Cc: Richard Earnshaw, Dave Anglin
[-- Attachment #1: Type: text/plain, Size: 1563 bytes --]
Hi,
Any attempt to compile C++ code using virtual vararg methods in the context
of multiple inheritance will fail on the SPARC with the message:
virtual.cpp:23: error: generic thunk code fails for method `virtual void
Foo::log(int, const char*, ...)' which uses `...'
This is a regression from 2.95.3 present on all active branches. It appears
that the SPARC back-end was not upgraded two years ago when the new
mechanism for thunks was devised (new proto for TARGET_ASM_OUTPUT_MI_THUNK
and new target hook TARGET_ASM_CAN_OUTPUT_MI_THUNK). Part of the problem
might be that this new interface has never been documented in tm.texi.
[Other ports might be in the same situation, e.g. ARM and PA.]
This patch implements the long-overdue upgrade for the SPARC. The default
method used in the generic case when VCALL_OFFSET is non-null is based on
estimates provided by Nathan (thanks!). Tested on sparc64-sun-solaris2.9
and sparc-sun-solaris2.8.
I'd appreciate comments from other SPARC maintainers. Thanks in advance.
2004-10-10 Eric Botcazou <ebotcazou@libertysurf.fr>
PR target/14454
* config/sparc/sparc.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Set to true.
(sparc_output_mi_thunk): Simplify handling of delta offset. Add
handling of vcall offset.
* 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.
2004-10-10 Eric Botcazou <ebotcazou@libertysurf.fr>
* g++.dg/inherit/thunk1.C: Run on the SPARC.
--
Eric Botcazou
[-- Attachment #2: pr14454.diff --]
[-- Type: text/x-diff, Size: 9103 bytes --]
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.271.4.21
diff -c -p -r1.271.4.21 sparc.c
*** config/sparc/sparc.c 8 Oct 2004 13:41:22 -0000 1.271.4.21
--- config/sparc/sparc.c 10 Oct 2004 14:49:28 -0000
*************** enum processor_type sparc_cpu;
*** 270,276 ****
#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
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
--- 270,276 ----
#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 hook_bool_tree_hwi_hwi_tree_true
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
*************** sparc_rtx_costs (rtx x, int code, int ou
*** 9286,9301 ****
}
}
! /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
! Used for C++ multiple inheritance. */
static void
sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
! HOST_WIDE_INT delta,
! HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
! rtx this, insn, funexp, delta_rtx, tmp;
reload_completed = 1;
epilogue_completed = 1;
--- 9286,9303 ----
}
}
! /* 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,
tree function)
{
! rtx this, insn, funexp;
reload_completed = 1;
epilogue_completed = 1;
*************** sparc_output_mi_thunk (FILE *file, tree
*** 9313,9338 ****
/* 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))
{
rtx scratch = gen_rtx_REG (Pmode, 1);
! if (input_operand (delta_rtx, GET_MODE (scratch)))
! emit_insn (gen_rtx_SET (VOIDmode, scratch, delta_rtx));
else
{
! if (TARGET_ARCH64)
! sparc_emit_set_const64 (scratch, delta_rtx);
! else
! sparc_emit_set_const32 (scratch, delta_rtx);
}
! delta_rtx = scratch;
! }
! tmp = gen_rtx_PLUS (Pmode, this, delta_rtx);
! emit_insn (gen_rtx_SET (VOIDmode, this, tmp));
/* Generate a tail call to the target function. */
if (! TREE_USED (function))
--- 9315,9387 ----
/* Add DELTA. When possible use a plain add, otherwise load it into
a register first. */
! 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 (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
{
! 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 */
}
! /* SCRATCH = *(*THIS + VCALL_OFFSET). */
! emit_move_insn (scratch, gen_rtx_MEM (Pmode,
! gen_rtx_PLUS (Pmode,
! scratch,
! vcall_offset_rtx)));
! /* THIS += *(*THIS + VCALL_OFFSET). */
! emit_insn (gen_add2_insn (this, scratch));
! }
/* Generate a tail call to the target function. */
if (! TREE_USED (function))
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.281.2.17
diff -c -p -r1.281.2.17 tm.texi
*** doc/tm.texi 30 Sep 2004 17:45:49 -0000 1.281.2.17
--- doc/tm.texi 10 Oct 2004 16:53:53 -0000
*************** You need not define this macro if you di
*** 4314,4320 ****
@code{DELAY_SLOTS_FOR_EPILOGUE}.
@end defmac
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_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,
--- 4314,4320 ----
@code{DELAY_SLOTS_FOR_EPILOGUE}.
@end defmac
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_INT @var{delta}, HOST_WIDE_INT @var{vcall_offset}, 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,
*************** in C++. This is the incoming argument @
*** 4328,4334 ****
e.g.@: @samp{%o0} on a sparc. The addition must preserve the values of
all other incoming arguments.
! After the addition, emit code to jump to @var{function}, which is a
@code{FUNCTION_DECL}. This is a direct pure jump, not a call, and does
not touch the return address. Hence returning from @var{FUNCTION} will
return to whoever called the current @samp{thunk}.
--- 4328,4342 ----
e.g.@: @samp{%o0} on a sparc. The addition must preserve the values of
all other incoming arguments.
! Then, if @var{vcall_offset} is nonzero, 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:
!
! @smallexample
! p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]
! @end smallexample
!
! After the additions, emit code to jump to @var{function}, which is a
@code{FUNCTION_DECL}. This is a direct pure jump, not a call, and does
not touch the return address. Hence returning from @var{FUNCTION} will
return to whoever called the current @samp{thunk}.
*************** front end will generate a less efficient
*** 4348,4366 ****
not support varargs.
@end deftypefn
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_VCALL_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_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 nonzero, 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:
!
! @smallexample
! p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]
! @end smallexample
!
! @noindent
! If this function is defined, it will always be used in place of
! @code{TARGET_ASM_OUTPUT_MI_THUNK}.
@end deftypefn
@node Profiling
--- 4356,4367 ----
not support varargs.
@end deftypefn
! @deftypefn {Target Hook} bool TARGET_ASM_CAN_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_INT @var{delta}, HOST_WIDE_INT @var{vcall_offset}, tree @var{function})
! A function that returns true if TARGET_ASM_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. In the latter case, the
! generic approach will be used by the C++ front end, with the limitations
! previously exposed.
@end deftypefn
@node Profiling
[-- Attachment #3: thunk1.diff --]
[-- Type: text/x-diff, Size: 533 bytes --]
Index: g++.dg/inherit/thunk1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/inherit/thunk1.C,v
retrieving revision 1.5
diff -u -r1.5 thunk1.C
--- g++.dg/inherit/thunk1.C 24 Oct 2002 09:16:36 -0000 1.5
+++ g++.dg/inherit/thunk1.C 10 Oct 2004 18:02:17 -0000
@@ -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>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] Fix PR target/14454
2004-10-10 18:27 [RFC] Fix PR target/14454 Eric Botcazou
@ 2004-10-10 18:31 ` John David Anglin
2004-10-11 21:08 ` Richard Henderson
1 sibling, 0 replies; 4+ messages in thread
From: John David Anglin @ 2004-10-10 18:31 UTC (permalink / raw)
To: Eric Botcazou; +Cc: gcc-patches, rearnsha, dave.anglin
> [Other ports might be in the same situation, e.g. ARM and PA.]
PA (hppa-unknown-linux-gnu) fails the test program. So, it appears
we need a similar fix.
Dave
--
J. David Anglin dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] Fix PR target/14454
2004-10-10 18:27 [RFC] Fix PR target/14454 Eric Botcazou
2004-10-10 18:31 ` John David Anglin
@ 2004-10-11 21:08 ` Richard Henderson
2004-10-13 14:47 ` Eric Botcazou
1 sibling, 1 reply; 4+ messages in thread
From: Richard Henderson @ 2004-10-11 21:08 UTC (permalink / raw)
To: Eric Botcazou; +Cc: gcc-patches, Richard Earnshaw, Dave Anglin
On Sun, Oct 10, 2004 at 08:10:53PM +0200, Eric Botcazou wrote:
> * config/sparc/sparc.c (TARGET_ASM_CAN_OUTPUT_MI_THUNK): Set to true.
> (sparc_output_mi_thunk): Simplify handling of delta offset. Add
> handling of vcall offset.
> * 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.
Looks good, except,
> ! /* 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;
You may want to bound this loop. One can fairly easilly generate
artificial test cases for which this number is arbitrarily large.
r~
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC] Fix PR target/14454
2004-10-11 21:08 ` Richard Henderson
@ 2004-10-13 14:47 ` Eric Botcazou
0 siblings, 0 replies; 4+ messages in thread
From: Eric Botcazou @ 2004-10-13 14:47 UTC (permalink / raw)
To: gcc-patches; +Cc: Richard Henderson, Richard Earnshaw, Dave Anglin
[-- Attachment #1: Type: text/plain, Size: 1268 bytes --]
> > ! /* 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;
>
> You may want to bound this loop. One can fairly easilly generate
> artificial test cases for which this number is arbitrarily large.
Of course. I turned -32768 into an implementation limit for the optimized
thunk as suggested by Nathan. Thanks for the review.
Applied to mainline and 3.4 branch.
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.
--
Eric Botcazou
[-- Attachment #2: pr14454-2.diff --]
[-- Type: text/x-diff, Size: 10293 bytes --]
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.271.4.21
diff -c -p -r1.271.4.21 sparc.c
*** config/sparc/sparc.c 8 Oct 2004 13:41:22 -0000 1.271.4.21
--- config/sparc/sparc.c 11 Oct 2004 21:57:16 -0000
*************** static bool sparc_function_ok_for_sibcal
*** 187,192 ****
--- 187,194 ----
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);
*************** enum processor_type sparc_cpu;
*** 270,276 ****
#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
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
--- 272,278 ----
#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 sparc_can_output_mi_thunk
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
*************** sparc_rtx_costs (rtx x, int code, int ou
*** 9286,9301 ****
}
}
! /* Output code to add DELTA to the first argument, and then jump to FUNCTION.
! Used for C++ multiple inheritance. */
static void
sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
! HOST_WIDE_INT delta,
! HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
tree function)
{
! rtx this, insn, funexp, delta_rtx, tmp;
reload_completed = 1;
epilogue_completed = 1;
--- 9288,9305 ----
}
}
! /* 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,
tree function)
{
! rtx this, insn, funexp;
reload_completed = 1;
epilogue_completed = 1;
*************** sparc_output_mi_thunk (FILE *file, tree
*** 9313,9338 ****
/* 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))
{
rtx scratch = gen_rtx_REG (Pmode, 1);
! if (input_operand (delta_rtx, GET_MODE (scratch)))
! emit_insn (gen_rtx_SET (VOIDmode, scratch, delta_rtx));
else
{
! if (TARGET_ARCH64)
! sparc_emit_set_const64 (scratch, delta_rtx);
! else
! sparc_emit_set_const32 (scratch, delta_rtx);
}
! delta_rtx = scratch;
! }
! tmp = gen_rtx_PLUS (Pmode, this, delta_rtx);
! emit_insn (gen_rtx_SET (VOIDmode, this, tmp));
/* Generate a tail call to the target function. */
if (! TREE_USED (function))
--- 9317,9389 ----
/* Add DELTA. When possible use a plain add, otherwise load it into
a register first. */
! 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 (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
{
! 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 */
}
! /* SCRATCH = *(*THIS + VCALL_OFFSET). */
! emit_move_insn (scratch, gen_rtx_MEM (Pmode,
! gen_rtx_PLUS (Pmode,
! scratch,
! vcall_offset_rtx)));
! /* THIS += *(*THIS + VCALL_OFFSET). */
! emit_insn (gen_add2_insn (this, scratch));
! }
/* Generate a tail call to the target function. */
if (! TREE_USED (function))
*************** sparc_output_mi_thunk (FILE *file, tree
*** 9362,9367 ****
--- 9413,9431 ----
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 *
Index: doc/tm.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/tm.texi,v
retrieving revision 1.281.2.18
diff -c -p -r1.281.2.18 tm.texi
*** doc/tm.texi 6 Oct 2004 01:01:35 -0000 1.281.2.18
--- doc/tm.texi 11 Oct 2004 21:57:51 -0000
*************** You need not define this macro if you di
*** 4334,4340 ****
@code{DELAY_SLOTS_FOR_EPILOGUE}.
@end defmac
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_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,
--- 4334,4340 ----
@code{DELAY_SLOTS_FOR_EPILOGUE}.
@end defmac
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_INT @var{delta}, HOST_WIDE_INT @var{vcall_offset}, 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,
*************** in C++. This is the incoming argument @
*** 4348,4354 ****
e.g.@: @samp{%o0} on a sparc. The addition must preserve the values of
all other incoming arguments.
! After the addition, emit code to jump to @var{function}, which is a
@code{FUNCTION_DECL}. This is a direct pure jump, not a call, and does
not touch the return address. Hence returning from @var{FUNCTION} will
return to whoever called the current @samp{thunk}.
--- 4348,4362 ----
e.g.@: @samp{%o0} on a sparc. The addition must preserve the values of
all other incoming arguments.
! Then, if @var{vcall_offset} is nonzero, 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:
!
! @smallexample
! p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]
! @end smallexample
!
! After the additions, emit code to jump to @var{function}, which is a
@code{FUNCTION_DECL}. This is a direct pure jump, not a call, and does
not touch the return address. Hence returning from @var{FUNCTION} will
return to whoever called the current @samp{thunk}.
*************** front end will generate a less efficient
*** 4368,4386 ****
not support varargs.
@end deftypefn
! @deftypefn {Target Hook} void TARGET_ASM_OUTPUT_MI_VCALL_THUNK (FILE *@var{file}, tree @var{thunk_fndecl}, HOST_WIDE_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 nonzero, 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:
!
! @smallexample
! p += (*((ptrdiff_t **)p))[vcall_offset/sizeof(ptrdiff_t)]
! @end smallexample
!
! @noindent
! If this function is defined, it will always be used in place of
! @code{TARGET_ASM_OUTPUT_MI_THUNK}.
@end deftypefn
@node Profiling
--- 4376,4387 ----
not support varargs.
@end deftypefn
! @deftypefn {Target Hook} bool TARGET_ASM_CAN_OUTPUT_MI_THUNK (tree @var{thunk_fndecl}, HOST_WIDE_INT @var{delta}, HOST_WIDE_INT @var{vcall_offset}, tree @var{function})
! A function that returns true if TARGET_ASM_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. In the latter case, the
! generic approach will be used by the C++ front end, with the limitations
! previously exposed.
@end deftypefn
@node Profiling
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-10-13 14:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-10-10 18:27 [RFC] Fix PR target/14454 Eric Botcazou
2004-10-10 18:31 ` John David Anglin
2004-10-11 21:08 ` Richard Henderson
2004-10-13 14:47 ` Eric Botcazou
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).