ARM: Invalid Stack Alignment BUG

Craig Newell CraigN@cheque.uq.edu.au
Sat Mar 11 21:05:00 GMT 2000


Hi All,

  I have been trying the latest CVS version on the ARM processor and
the compiler now generates unaligned stack pointers which are invalid
on the ARM.  

  After much learning about the internals of GCC I have found the BUG but
as I am yet to get my "GNU paperwork" in order ... I will not give a patch
but rather attempt to describe the BUG in as much detail as possible so
that someone who has the "GNU paperwork" in order can commit a patch.

  The symptoms of the BUG are that code is generated that does not keep
the stack pointer word aligned at all times. This happens alot in my code
with "-O[123]" but it also happens with "-O0" ... so here is a test case
that generates invalid code with "-O0":

A Simple Test Program:

--- t.c -------------------------
void *a;

int 
f(void) 
{
        unsigned char b;

        if(g(a, 0x002000, &b, 1) != 1)
                return -1;
        return b;
}
---------------------------------

Compiled with "arm-elf-gcc -S t.c" produces:

--- t.s -------------------------
@ Generated by gcc 2.96 20000309 (experimental) for ARM/elf
	.file	"t.c"
 .gcc2_compiled.:
.text
	.align	2
	.global	f
	.type	 f,function
f:
	@ args = 0, pretend = 0, frame = 1
	@ frame_needed = 1, current_function_anonymous_args = 0
	mov	ip, sp
	stmfd	sp!, {fp, ip, lr, pc}
	sub	fp, ip, #4
	sub	sp, sp, #1            <<=== ** BUG ** (should be 4)
	ldr	r3, .L4
	sub	r2, fp, #13
	ldr	r0, [r3, #0]
	mov	r1, #8192
	mov	r3, #1
	bl	g
	mov	r3, r0
	cmp	r3, #1
	beq	.L3
	mvn	r0, #0
	b	.L2
.L3:
	ldrb	r3, [fp, #-13]	@ zero_extendqisi2
	mov	r0, r3
.L2:
	ldmea	fp, {fp, sp, pc}
.L5:
	.align	2
.L4:
	.word	a
.Lfe1:
	.size	 f,.Lfe1-f
	.comm	a, 4	@ 4
----------------------------------------------

  So what causes this is the following commit to reload1.c:

----------------------------------------------
revision 1.198
date: 2000/02/09 13:38:09;  author: hubicka;  state: Exp;  lines: +3 -2
        * reload1.c (reload) Align stack frame to
cfun->stack_alignment_needed,
        not to BIGGEST_ALIGNMENT.
----------------------------

[craign@FreeSpirit gcc]$ cvs diff -D 2/9/2000 -D 2/10/2000 reload1.c
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/reload1.c,v
retrieving revision 1.197
retrieving revision 1.198
diff -u -r1.197 -r1.198
--- reload1.c   2000/01/17 15:47:28     1.197
+++ reload1.c   2000/02/09 13:38:09     1.198
@@ -841,11 +841,12 @@

       HOST_WIDE_INT starting_frame_size;

-      /* Round size of stack frame to BIGGEST_ALIGNMENT.  This must be done
+      /* Round size of stack frame to stack_alignment_needed.  This must be done
         here because the stack size may be a part of the offset 
computation
         for register elimination, and there might have been new stack
slots
         created in the last iteration of this loop.   */
-      assign_stack_local (BLKmode, 0, 0);
+      if (cfun->stack_alignment_needed)
+        assign_stack_local (BLKmode, 0, cfun->stack_alignment_needed);

       starting_frame_size = get_frame_size ();

-----------------------------------

  But this appears not to be in error as much as causing a false
assumption in gcc/config/arm.c to be broken.  I say this as it appears
that exactly the same problem that I am seeing here on the ARM also
occured on the SH which was then fixed with the following commit (and
another one soon after to fix a problem in the first attempt).:

-----------------------------------
Thu Feb 24 22:06:52 2000  J"orn Rennecke <amylaar@cygnus.co.uk>
        
        Fix bug exposed by reload.c no longer rounding the frame
        size to BIGGEST_ALIGNMENT:
        * sh.c (rounded_frame_size): New function.
        (sh_expand_prologue, sh_expand_epilogue): Use it.
        (initial_elimination_offset): Likewise.
----------------------------------

  So what this shows is that gcc/config/arm/arm.c in functions
arm_output_epilogue() [line 6041] and arm_expand_prologue() [line 6335]
forgets about the following limitation to get_frame_size():

---- function.c line 495 ----
/* Return size needed for stack frame based on slots so far allocated.
   This size counts from zero. It is not rounded to PREFERRED_STACK_BOUNDARY;
   the caller may have to do that.  */
HOST_WIDE_INT
get_frame_size ()
{
  return get_func_frame_size (cfun);
}
-----------------------------

  So finally, would it be possible for someone to make a patch and commit
it to the CVS so that the ARM target will be operational again.

	Thanks,

		CraigN

PS. I am in the process of getting my "GNU paperwork" in order
... hopefully not much longer ...
--
      Craig Newell                email: CraigN@cheque.uq.edu.au
      Free Spirit                 icbm:  somewhere in NJ, USA




	Thanks,

		CraigN
--
      Craig Newell                email: CraigN@cheque.uq.edu.au
      Free Spirit                 icbm:  somewhere in NJ, USA




More information about the Gcc-patches mailing list