From: Dominik Vogt Date: Fri, 18 Nov 2016 14:28:49 +0000 (+0000) Subject: RS6000: Fix PR 77359: Properly align local variables in functions calling alloca. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a7790c7174a016fcea0af852a493479f0dadfdf3;p=gcc.git RS6000: Fix PR 77359: Properly align local variables in functions calling alloca. gcc/ChangeLog: 2016-11-18 Dominik Vogt * 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a63c7952ce1..95506d39c0f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2016-11-18 Dominik Vogt + + 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 Alan Hayward David Sherwood diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index b2542360e79..f6eb122d45a 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 e050da8875e..bec49bffea2 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 1148212c7ff..19a476bc804 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.