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]

new macro STARTING_FRAME_PHASE: alignment


hullo.

the following local wasn't being aligned properly on the ppc stack.

	int foo[4] __attribute__((aligned(16)));

which was causing altivec locals to be unaligned (and not work).

geoff seriously helped me figure out that, though the ppc stack was
aligned to 16bytes, the frame actually starts 8bytes later.  this
patch explains to assign_stack_local_1() that, although the stack
can be aligned, the starting frame offset can introduce an additional
displacement that is not necessarily aligned.

in the ppc case (for 32bit ppc), the stack is 16byte aligned, but
the starting frame offset is 8bytes displaced, so we need to add an
additional 8bytes to align a local variable.

this patch introduces a new macro STARTING_FRAME_PHASE (documented).

i have also added a sanity check in instantiate_virtual_regs() to make
sure we are aligned after introducing this phase info.  i have only
enabled this check if the new macro STARTING_FRAME_PHASE is defined,
otherwise we might trigger an abort on a port that, like ppc, is
lying with regards to it's alignment.

as a heads up for the apple folks, this explains the magic +8 in your
(apple source) RS6000_VARARGS_SIZE definition.  with this patch you can 
remove the +8:

  /* APPLE LOCAL: AltiVec */
  /* Size of V.4 varargs area in bytes.  Round to 0 mod 16. */
  #define RS6000_VARARGS_SIZE \
    ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8 + 8)
									 ^^^^

i have done some minor testing on darwin (because my box is too slow)...
and fully tested for regressions on ppc linux.

ok to install?

2002-01-18  Aldy Hernandez  <aldyh@redhat.com>

	* gcc.dg/20020118-1.c: New.

	* tm.texi (STARTING_FRAME_PHASE): Document.

	* function.c (assign_stack_local_1): Adjust x_frame_offset with
	STARTING_FRAME_PHASE.
	(STARTING_FRAME_PHASE): New.
	(instantiate_virtual_regs): Check saneness of
	STARTING_FRAME_PHASE.

	* rs6000.h (STARTING_FRAME_PHASE): New.

Index: function.c
===================================================================
RCS file: /cvs/uberbaum/gcc/function.c,v
retrieving revision 1.342
diff -c -p -r1.342 function.c
*** function.c	2002/01/18 13:40:30	1.342
--- function.c	2002/01/19 02:16:26
*************** Software Foundation, 59 Temple Place - S
*** 68,73 ****
--- 68,77 ----
  #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
  #endif
  
+ #ifndef STARTING_FRAME_PHASE
+ #define STARTING_FRAME_PHASE 0
+ #endif
+ 
  /* Some systems use __main in a way incompatible with its use in gcc, in these
     cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
     give the same symbol without quotes for an alternative entry point.  You
*************** assign_stack_local_1 (mode, size, align,
*** 567,575 ****
       like.  So we instead assume that ALIGNMENT is a power of two and
       use logical operations which are unambiguous.  */
  #ifdef FRAME_GROWS_DOWNWARD
!   function->x_frame_offset = FLOOR_ROUND (function->x_frame_offset, alignment);
  #else
!   function->x_frame_offset = CEIL_ROUND (function->x_frame_offset, alignment);
  #endif
  
    /* On a big-endian machine, if we are allocating more space than we will use,
--- 571,579 ----
       like.  So we instead assume that ALIGNMENT is a power of two and
       use logical operations which are unambiguous.  */
  #ifdef FRAME_GROWS_DOWNWARD
!   function->x_frame_offset = FLOOR_ROUND (function->x_frame_offset - STARTING_FRAME_PHASE, alignment) + STARTING_FRAME_PHASE;
  #else
!   function->x_frame_offset = CEIL_ROUND (function->x_frame_offset - STARTING_FRAME_PHASE, alignment) + STARTING_FRAME_PHASE;
  #endif
  
    /* On a big-endian machine, if we are allocating more space than we will use,
*************** instantiate_virtual_regs (fndecl, insns)
*** 3476,3481 ****
--- 3480,3504 ----
  {
    rtx insn;
    unsigned int i;
+ 
+ #if STARTING_FRAME_PHASE != 0
+   /* Make sure the frame offset and phase displacement are aligned as
+      advertised.
+ 
+      We conditionalize this on the existence of STARTING_FRAME_PHASE,
+      else we might trigger this abort on ports who claim to have
+      STARTING_FRAME_OFFSET aligned properly, but don't.  I suppose we
+      could enable this and fix those ports.  */
+ 
+   if ((STARTING_FRAME_OFFSET + STARTING_FRAME_PHASE)
+       % (STACK_BOUNDARY / BITS_PER_UNIT))
+     abort ();
+ #endif
  
    /* Compute the offsets to use for this function.  */
    in_arg_offset = FIRST_PARM_OFFSET (fndecl);
Index: config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.173
diff -c -p -r1.173 rs6000.h
*** rs6000.h	2002/01/11 03:29:35	1.173
--- rs6000.h	2002/01/19 02:16:36
*************** typedef struct rs6000_stack {
*** 1399,1404 ****
--- 1399,1409 ----
     + RS6000_VARARGS_AREA						\
     + RS6000_SAVE_AREA)
  
+ /* How far (in bytes) is the start of the frame from the stack
+    alignment.  For ppc 32bits, the stack is aligned to 128 bits, but
+    the frame starts 64bits later.  */
+ #define STARTING_FRAME_PHASE (TARGET_32BIT ? 8 : 0)
+ 
  /* Offset from the stack pointer register to an item dynamically
     allocated on the stack, e.g., by `alloca'.
  
Index: doc/tm.texi
===================================================================
RCS file: /cvs/uberbaum/gcc/doc/tm.texi,v
retrieving revision 1.89
diff -c -p -r1.89 tm.texi
*** tm.texi	2002/01/16 02:37:14	1.89
--- tm.texi	2002/01/19 02:17:17
*************** value @code{STARTING_FRAME_OFFSET}.
*** 2598,2603 ****
--- 2598,2615 ----
  @c i'm not sure if the above is still correct.. had to change it to get
  @c rid of an overfull.  --mew 2feb93
  
+ @findex STARTING_FRAME_PHASE
+ @item STARTING_FRAME_PHASE
+ This option species how many bytes the frame is out of phase from the
+ stack alignment.
+ 
+ For example, some ports assume a stack alignment of 128 bits, but the
+ start of the frame is 64 bits displaced from this alignment.  In this
+ case, you would define @code{STARTING_FRAME_PHASE} to be 8.
+ 
+ This macro defaults to 0, so there is no need to define it if the start
+ of the frame maintains the stack alignment.
+ 
  @findex STACK_POINTER_OFFSET
  @item STACK_POINTER_OFFSET
  Offset from the stack pointer register to the first location at which
Index: testsuite/gcc.dg/20020118-1.c
===================================================================
RCS file: 20020118-1.c
diff -N 20020118-1.c
*** /dev/null	Tue May  5 13:32:27 1998
--- 20020118-1.c	Fri Jan 18 18:17:17 2002
***************
*** 0 ****
--- 1,15 ----
+ /* { dg-do run { target powerpc*-*-* } }*/
+ 
+ /* Test local alignment.  Test new target macro STARTING_FRAME_PHASE.  */
+ /* Origin: Aldy Hernandez <aldyh@redhat.com>.  */
+ 
+ int main ()
+ {       
+   int darisa[4] __attribute__((aligned(16)));
+   int *stephanie = (int *) darisa;
+ 
+   if ((unsigned long) stephanie % 16 != 0)
+     abort ();
+ 
+   return 0;
+ }


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