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]

Re: [ARM] Fix register r3 wrongly used to save ip in nested APCS frame


> > 2013-09-05  Eric Botcazou  <ebotcazou@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;

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