aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDominik Vogt <vogt@linux.vnet.ibm.com>2016-11-18 14:28:49 +0000
committerAndreas Krebbel <krebbel@gcc.gnu.org>2016-11-18 14:28:49 +0000
commita7790c7174a016fcea0af852a493479f0dadfdf3 (patch)
treeee729e30eec5262d5ad6e74a5080a228fb603783 /gcc
parentdbb29a2a37900549c9d90f4d33bf7e00641655c6 (diff)
downloadgcc-a7790c7174a016fcea0af852a493479f0dadfdf3.zip
gcc-a7790c7174a016fcea0af852a493479f0dadfdf3.tar.gz
gcc-a7790c7174a016fcea0af852a493479f0dadfdf3.tar.bz2
RS6000: Fix PR 77359: Properly align local variables in functions calling alloca.
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/rs6000/aix.h35
-rw-r--r--gcc/config/rs6000/rs6000.c24
-rw-r--r--gcc/config/rs6000/rs6000.h26
4 files changed, 84 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a63c795..95506d3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index b254236..f6eb122 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -40,6 +40,41 @@
#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
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index e050da8..bec49bf 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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,
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 1148212..19a476b 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -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.