RS6000: Fix PR 77359: Properly align local variables in functions calling alloca.
authorDominik Vogt <vogt@linux.vnet.ibm.com>
Fri, 18 Nov 2016 14:28:49 +0000 (14:28 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Fri, 18 Nov 2016 14:28:49 +0000 (14:28 +0000)
gcc/ChangeLog:

2016-11-18  Dominik Vogt  <vogt@linux.vnet.ibm.com>

* config/rs6000/rs6000.c (rs6000_stack_info): PR/77359: Properly align
local variables in functions calling alloca.  Also update the ASCII
drawings
* config/rs6000/rs6000.h (STARTING_FRAME_OFFSET, STACK_DYNAMIC_OFFSET):
PR/77359: Likewise.
* config/rs6000/aix.h (STARTING_FRAME_OFFSET, STACK_DYNAMIC_OFFSET):
PR/77359: Copy AIX specific versions of the rs6000.h macros to aix.h.

From-SVN: r242589

gcc/ChangeLog
gcc/config/rs6000/aix.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h

index a63c7952ce15407b947228398dfef6e6f2777cdf..95506d39c0f190c90b9670640ba64938ff019e1b 100644 (file)
@@ -1,3 +1,15 @@
+2016-11-18  Dominik Vogt  <vogt@linux.vnet.ibm.com>
+
+       PR bootstrap/77359
+       * config/rs6000/rs6000.c (rs6000_stack_info): Properly align local
+       variables in functions calling alloca.  Also update the ASCII
+       drawings.
+       * config/rs6000/rs6000.h (STARTING_FRAME_OFFSET)
+       (STACK_DYNAMIC_OFFSET): Likewise.
+       * config/rs6000/aix.h (STARTING_FRAME_OFFSET)
+       (STACK_DYNAMIC_OFFSET): Copy AIX specific versions of the rs6000.h
+       macros to aix.h.
+
 2016-11-18  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index b2542360e7997e8d3aeb01b6e350b8db207682b0..f6eb122d45a761629e61c1541f7c2a5b85fa0ec9 100644 (file)
 #undef  STACK_BOUNDARY
 #define STACK_BOUNDARY 128
 
+/* Offset within stack frame to start allocating local variables at.
+   If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
+   first local allocated.  Otherwise, it is the offset to the BEGINNING
+   of the first local allocated.
+
+   On the RS/6000, the frame pointer is the same as the stack pointer,
+   except for dynamic allocations.  So we start after the fixed area and
+   outgoing parameter area.
+
+   If the function uses dynamic stack space (CALLS_ALLOCA is set), that
+   space needs to be aligned to STACK_BOUNDARY, i.e. the sum of the
+   sizes of the fixed area and the parameter area must be a multiple of
+   STACK_BOUNDARY.  */
+
+#undef STARTING_FRAME_OFFSET
+#define STARTING_FRAME_OFFSET                                          \
+  (FRAME_GROWS_DOWNWARD                                                        \
+   ? 0                                                                 \
+   : (cfun->calls_alloca                                               \
+      ? RS6000_ALIGN (crtl->outgoing_args_size + RS6000_SAVE_AREA, 16) \
+      : (RS6000_ALIGN (crtl->outgoing_args_size, 16) + RS6000_SAVE_AREA)))
+
+/* Offset from the stack pointer register to an item dynamically
+   allocated on the stack, e.g., by `alloca'.
+
+   The default value for this macro is `STACK_POINTER_OFFSET' plus the
+   length of the outgoing arguments.  The default is correct for most
+   machines.  See `function.c' for details.
+
+   This value must be a multiple of STACK_BOUNDARY (hard coded in
+   `emit-rtl.c').  */
+#undef STACK_DYNAMIC_OFFSET
+#define STACK_DYNAMIC_OFFSET(FUNDECL)                                  \
+   RS6000_ALIGN (crtl->outgoing_args_size + STACK_POINTER_OFFSET, 16)
+
 #undef  TARGET_IEEEQUAD
 #define TARGET_IEEEQUAD 0
 
index e050da8875ebd87000df7bd880eca8d6441db593..bec49bffea2a155b47255874b4dc38677bc4ccc2 100644 (file)
@@ -25898,7 +25898,7 @@ rs6000_savres_strategy (rs6000_stack_t *info,
                +---------------------------------------+
                | saved TOC pointer                     | 20      40
                +---------------------------------------+
-               | Parameter save area (P)               | 24      48
+               | Parameter save area (+padding*) (P)   | 24      48
                +---------------------------------------+
                | Alloca space (A)                      | 24+P    etc.
                +---------------------------------------+
@@ -25919,6 +25919,9 @@ rs6000_savres_strategy (rs6000_stack_t *info,
        old SP->| back chain to caller's caller         |
                +---------------------------------------+
 
+     * If the alloca area is present, the parameter save area is
+       padded so that the former starts 16-byte aligned.
+
    The required alignment for AIX configurations is two words (i.e., 8
    or 16 bytes).
 
@@ -25933,7 +25936,7 @@ rs6000_savres_strategy (rs6000_stack_t *info,
                +---------------------------------------+
                | Saved TOC pointer                     |  24
                +---------------------------------------+
-               | Parameter save area (P)               |  32
+               | Parameter save area (+padding*) (P)   |  32
                +---------------------------------------+
                | Alloca space (A)                      |  32+P
                +---------------------------------------+
@@ -25950,6 +25953,8 @@ rs6000_savres_strategy (rs6000_stack_t *info,
        old SP->| back chain to caller's caller         |  32+P+A+L+W+Y+G+F
                +---------------------------------------+
 
+     * If the alloca area is present, the parameter save area is
+       padded so that the former starts 16-byte aligned.
 
    V.4 stack frames look like:
 
@@ -25958,7 +25963,7 @@ rs6000_savres_strategy (rs6000_stack_t *info,
                +---------------------------------------+
                | caller's saved LR                     | 4
                +---------------------------------------+
-               | Parameter save area (P)               | 8
+               | Parameter save area (+padding*) (P)   | 8
                +---------------------------------------+
                | Alloca space (A)                      | 8+P
                +---------------------------------------+
@@ -25987,6 +25992,10 @@ rs6000_savres_strategy (rs6000_stack_t *info,
        old SP->| back chain to caller's caller         |
                +---------------------------------------+
 
+     * If the alloca area is present and the required alignment is
+       16 bytes, the parameter save area is padded so that the
+       alloca area starts 16-byte aligned.
+
    The required alignment for V.4 is 16 bytes, or 8 bytes if -meabi is
    given.  (But note below and in sysv4.h that we require only 8 and
    may round up the size of our stack frame anyways.  The historical
@@ -26121,8 +26130,13 @@ rs6000_stack_info (void)
   info->reg_size     = reg_size;
   info->fixed_size   = RS6000_SAVE_AREA;
   info->vars_size    = RS6000_ALIGN (get_frame_size (), 8);
-  info->parm_size    = RS6000_ALIGN (crtl->outgoing_args_size,
-                                        TARGET_ALTIVEC ? 16 : 8);
+  if (cfun->calls_alloca)
+    info->parm_size  =
+      RS6000_ALIGN (crtl->outgoing_args_size + info->fixed_size,
+                   STACK_BOUNDARY / BITS_PER_UNIT) - info->fixed_size;
+  else
+    info->parm_size  = RS6000_ALIGN (crtl->outgoing_args_size,
+                                    TARGET_ALTIVEC ? 16 : 8);
   if (FRAME_GROWS_DOWNWARD)
     info->vars_size
       += RS6000_ALIGN (info->fixed_size + info->vars_size + info->parm_size,
index 1148212c7ff20f0febb21e34677d9b45ce1688ce..19a476bc8047d9420f3a7ed25c5f7a61b35d428a 100644 (file)
@@ -1724,25 +1724,35 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
 
    On the RS/6000, the frame pointer is the same as the stack pointer,
    except for dynamic allocations.  So we start after the fixed area and
-   outgoing parameter area.  */
+   outgoing parameter area.
+
+   If the function uses dynamic stack space (CALLS_ALLOCA is set), that
+   space needs to be aligned to STACK_BOUNDARY, i.e. the sum of the
+   sizes of the fixed area and the parameter area must be a multiple of
+   STACK_BOUNDARY.  */
 
 #define STARTING_FRAME_OFFSET                                          \
   (FRAME_GROWS_DOWNWARD                                                        \
    ? 0                                                                 \
-   : (RS6000_ALIGN (crtl->outgoing_args_size,                          \
-                   (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8)            \
-      + RS6000_SAVE_AREA))
+   : (cfun->calls_alloca                                               \
+      ? (RS6000_ALIGN (crtl->outgoing_args_size + RS6000_SAVE_AREA,    \
+                      (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8 ))       \
+      : (RS6000_ALIGN (crtl->outgoing_args_size,                       \
+                      (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8)         \
+        + RS6000_SAVE_AREA)))
 
 /* Offset from the stack pointer register to an item dynamically
    allocated on the stack, e.g., by `alloca'.
 
    The default value for this macro is `STACK_POINTER_OFFSET' plus the
    length of the outgoing arguments.  The default is correct for most
-   machines.  See `function.c' for details.  */
+   machines.  See `function.c' for details.
+
+   This value must be a multiple of STACK_BOUNDARY (hard coded in
+   `emit-rtl.c').  */
 #define STACK_DYNAMIC_OFFSET(FUNDECL)                                  \
-  (RS6000_ALIGN (crtl->outgoing_args_size,                             \
-                (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8)               \
-   + (STACK_POINTER_OFFSET))
+  RS6000_ALIGN (crtl->outgoing_args_size + STACK_POINTER_OFFSET,       \
+               (TARGET_ALTIVEC || TARGET_VSX) ? 16 : 8)
 
 /* If we generate an insn to push BYTES bytes,
    this says how many the stack pointer really advances by.