From: iwj@cam-orl.co.UK (Ian Jackson)
Subject: ARM stack pointer not restored in some function epilogues
Summary: bug report and patch enclosed
Keywords: arm, gcc2.2.2
Organization: Olivetti Research Ltd
Distribution: gnu
Date: Wed, 14 Oct 1992 12:12:38 GMT

I have found a bug in the function epilogue code for the Advanced Risc
Machines ARM processor. If a function does not need a frame pointer
but does have variables in the stack frame that are not optimised into
registers, compiling the function optimised results in the stack
pointer not being restored in the epilogue.

I have a patch which adds a single add instruction just before the
last movs of lr into pc so that sp is restored correctly.

The patch, to config/arm.c, is enclosed below. I hope it was the right
place to patch it; it appears to generate correct code for the various
optimised and unoptimised cases though due to the nature of our
application it has only been tested on a thousand lines or so of C
source.

The gcc was compiled as a cross-compiler from sparc-sun-sunos4.1.2 to
ARMs, and another version compiled with host=mips-dec-ultrix4.2.0. I
have patched and recompiled and am now using both compilers.

Script started on Wed Oct 14 12:59:51 1992
pepper:toolstest> cat demo.c
void foo(void) {
  volatile int x;
  x++;
}
pepper:toolstest> arm-gcc -v -O2 -Wall -S demo.c
gcc version 2.2.2
 /project/atmos/utils/sun4/arm/lib/arm/2.2.2/cpp -lang-c -v -undef -D__GNUC__=2 -Darm -Driscix -Dunix -D__arm__ -D__riscix__ -D__unix__ -D__arm -D__riscix -D__unix -D__OPTIMIZE__ -Wall demo.c /usr/tmp/cca14529.i
GNU CPP version 2.2.2 (ARM/RISCiX)
 /project/atmos/utils/sun4/arm/lib/arm/2.2.2/cc1 /usr/tmp/cca14529.i -quiet -dumpbase demo.c -O2 -Wall -version -o demo.s
GNU C version 2.2.2 (ARM/RISCiX) compiled by CC.
pepper:toolstest> cat demo.s
; Generated by gcc 2.2.2 for ARM/RISCiX
rfp	.req	r9
fp	.req	r11
ip	.req	r12
sp	.req	r13
lr	.req	r14
pc	.req	r15
gcc2_compiled.:
	.text
	.align	0,4
	.global	_foo
_foo:
	; args = 0, pretend = 0, frame = 4
	; frame_pointer_needed = 0, current_function_anonymous_args = 0
	sub	sp, sp, #4
	ldr	r0, [sp, #0]
	add	r0, r0, #1
	str	r0, [sp, #0]
	movs	pc, lr
pepper:toolstest> exit
script done on Wed Oct 14 13:00:05 1992

The pached version inserts
	add	sp, sp, #4
just before the last movs.

Here is the patch to arm.c:

*** arm.c.distribution	Fri Oct  9 15:48:33 1992
--- arm.c	Mon Oct 12 12:18:37 1992
***************
*** 920,925 ****
--- 920,940 ----
      }
    else
      {
+       /* next if statement and the following block added by iwj 12.10.92
+        * fixes bug with not correctly restoring stack pointer before
+        * register restore and return if function has non-register local
+        * variables and no frame pointer is used (ie, when stack pointer
+        * is used directly to find things to restore, and isn't restored
+        * itself)
+        */
+       if (frame_size)
+         {
+           operands[0] = operands[1] = stack_pointer_rtx;
+           operands[2] = gen_rtx (CONST_INT, VOIDmode, frame_size);
+           output_add_immediate (operands);
+         }
+       /* end of iwj's bugfix */
+ 
        if (current_function_pretend_args_size == 0 && regs_ever_live[14])
  	{
  	  print_multi_reg (f, "ldmfd\tsp!",
-- 
Ian Jackson  iwj@cam-orl.co.uk ..!uknet!cam-orl!iwj  These opinions are my own.
Olivetti Research Ltd, Old Addenbrookes Site, Trumpington St, Cambridge, UK;
Home: 35 Molewood Close, Cambridge, CB4 3SR; +44 223 327029.     +44 223 343398

Newsgroups: gnu.gcc.bug