> > 2013-09-05  Eric Botcazou  <ebotca...@adacore.com>
> > 
> >     * config/arm/arm.c (arm_expand_prologue): In a nested APCS frame with
> >     arguments to push onto the stack and no varargs, save ip into a stack
> >     slot if r3 isn't available on entry.
> 
> This is all fragile code, so a testcase would be very much appreciated.

I have attached a reduced Ada testcase, compile it for arm-wrs-vxworks and 
you'll see at the beginning of p__f$1593:

        .type   p__f$1593, %function
p__f$1593:
        @ Nested: function declared inside another function.
        @ args = 16, pretend = 4, frame = 140
        @ frame_needed = 1, uses_anonymous_args = 0
        sub     sp, sp, #4
        mov     r3, ip
        add     ip, sp, #4
        stmfd   sp!, {r4, r5, r6, r7, r8, r9, r10, fp, ip, lr, pc}
        sub     fp, ip, #8
        mov     ip, r3
        @ ip needed
        sub     sp, sp, #140
        str     r0, [fp, #-64]
        str     r1, [fp, #-72]
        str     r2, [fp, #-68]
        str     r3, [fp, #4]

so r3 is live on function's entry but gets clobbered by the ip save.  With the 
patch, the assembly code reads:

p__f$1593:
        @ Nested: function declared inside another function.
        @ args = 16, pretend = 4, frame = 140
        @ frame_needed = 1, uses_anonymous_args = 0
        sub     sp, sp, #4
        str     ip, [sp]
        add     ip, sp, #4
        stmfd   sp!, {r4, r5, r6, r7, r8, r9, r10, fp, ip, lr, pc}
        sub     fp, ip, #8
        ldr     ip, [fp, #4]
        @ ip needed
        sub     sp, sp, #140
        str     r0, [fp, #-64]
        str     r1, [fp, #-72]
        str     r2, [fp, #-68]
        str     r3, [fp, #4]

which looks correct.  FWIW we have had the patch in our tree for 4 months now.

-- 
Eric Botcazou
procedure P (I : Integer) is

  SUBTYPE S IS INTEGER RANGE 1..100;
  TYPE ARR IS ARRAY (S RANGE <>) OF INTEGER;

  A : ARR (2..9);

  FUNCTION F (AR_VAR1, AR_VAR2, AR_VAR3 : ARR) RETURN ARR IS
  BEGIN
    if I = 0 then
      RETURN AR_VAR1 & AR_VAR2 & AR_VAR3;
    else
      RETURN AR_VAR1;
    end if;
  END;

begin
  A := (8,7,6,5,4,3,2,1);
  if F(A(2..3), A(2..4), A(2..4)) /= (8,7,8,7,6,8,7,6) then
    raise Program_Error;
  end if;
end;

Reply via email to