This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
patch for broken thunk on sparc
- From: Alexey Starovoytov <alexey dot starovoytov at sun dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 4 Apr 2006 13:49:31 -0700 (PDT)
- Subject: patch for broken thunk on sparc
Hi,
on sparc the thunk (support for C++ multiple inheritance)
is created incorrectly if flag_pic or -mcmodel=*medany -m64 are present.
The problem is in code (for -m32):
sub %sp, 8, %sp
st %o7, [%sp]
st %l7, [%sp+4]
which incorrectly uses window save space.
If OS needs to save window after that sequence the restored registers
will contain some junk.
Any C++ program with multiple or virtual inheritance can be affected.
To reproduce the problem one can write a code:
--------------------------------------
class A {
public:
virtual int foo() = 0;
int a;
};
class B: virtual public A {};
class C: public B {
public:
int foo() {}
};
int
main()
{
B *b = new C;
while (1) b->foo();
return 0;
}
--------------------------------------
Such code compiled with 'g++ -fPIC file.cc' will core dump pretty soon
with GCC 4.0, 4.1 and 4.2.
For some reason -O and above optimize that thunk sequence away, so users
at least have sort of workaround.
Would be nice to patch all 4.x branches.
Alex.
Here is the proposed patch:
* config/sparc/sparc.c (emit_and_preserve): Use
correct slot offset to preserve registers
------- sparc.c -------
*** /tmp/ApaGGL Tue Apr 4 13:34:39 2006
--- sparc.c Mon Apr 3 19:53:08 2006
***************
*** 8929,8936 ****
emit_and_preserve (rtx seq, rtx reg, rtx reg2)
{
/* STACK_BOUNDARY guarantees that this is a 2-word slot. */
! rtx slot = gen_rtx_MEM (word_mode,
! plus_constant (stack_pointer_rtx, SPARC_STACK_BIAS));
emit_insn (gen_stack_pointer_dec (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT)));
emit_insn (gen_rtx_SET (VOIDmode, slot, reg));
--- 8929,8961 ----
emit_and_preserve (rtx seq, rtx reg, rtx reg2)
{
/* STACK_BOUNDARY guarantees that this is a 2-word slot. */
!
! /* per function.c for sparc
! * STACK_DYNAMIC_OFFSET = current_function_outgoing_args_size
! * + REG_PARM_STACK_SPACE (FNDECL)
! * + STACK_POINTER_OFFSET
! * Need to use it here to access slot.
! * current_function_outgoing_args_size == 0 (we are working on thunk)
! * REG_PARM_STACK_SPACE () ignores FNDECL, so we pass 0
! *
! * Also we would want to align %sp like in SPARC_STACK_ALIGN:
! * + GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT - 1)
! * / GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
! * * GEN_INT (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
! *
! * for -m32 we can wrap STACK_DYNAMIC_OFFSET with SPARC_STACK_ALIGN
! * since %sp already aligned.
! * for -m64 we cannot do that or we would need to align %sp afterwards,
! * so we just keep it as is:
! * REG_PARM_STACK_SPACE and FIRST_PARM_OFFSET are multiple of
! * STACK_BOUNDARY and SPARC_STACK_BIAS will get us to the properly
! * aligned slot
! */
! rtx slot = gen_rtx_MEM (word_mode,
! plus_constant (stack_pointer_rtx,
! TARGET_ARCH64 ? REG_PARM_STACK_SPACE (0) + STACK_POINTER_OFFSET
! : SPARC_STACK_ALIGN (REG_PARM_STACK_SPACE (0)
! + STACK_POINTER_OFFSET)));
emit_insn (gen_stack_pointer_dec (GEN_INT (STACK_BOUNDARY/BITS_PER_UNIT)));
emit_insn (gen_rtx_SET (VOIDmode, slot, reg));