This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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));



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]