@@ -2453,7 +2453,7 @@ struct GTY(()) stack_local_entry {
[saved regs]
<- regs_save_offset
[padding0]
-
+ <- stack_realign_offset
[saved SSE regs]
<- sse_regs_save_offset
[padding1] |
@@ -2479,6 +2479,8 @@ struct ix86_frame
HOST_WIDE_INT stack_pointer_offset;
HOST_WIDE_INT hfp_save_offset;
HOST_WIDE_INT reg_save_offset;
+ HOST_WIDE_INT stack_realign_allocate_offset;
+ HOST_WIDE_INT stack_realign_offset;
HOST_WIDE_INT sse_reg_save_offset;
/* When save_regs_using_mov is set, emit prologue using
@@ -12457,28 +12459,36 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
if (TARGET_SEH)
frame->hard_frame_pointer_offset = offset;
+ /* When re-aligning the stack frame, but not saving SSE registers, this
+ is the offset we want to allocate memory for. */
+ frame->stack_realign_allocate_offset = offset;
+
+ /* The re-aligned stack starts here. Values before this point are not
+ directly comparable with values below this point. Use sp_valid_at
+ to determine if the stack pointer is valid for a given offset and
+ fp_valid_at for the frame pointer. */
+ if (stack_realign_fp)
+ offset = ROUND_UP (offset, stack_alignment_needed);
+ frame->stack_realign_offset = offset;
+
/* Align and set SSE register save area. */
if (frame->nsseregs)
{
/* The only ABI that has saved SSE registers (Win64) also has a
- 16-byte aligned default stack, and thus we don't need to be
- within the re-aligned local stack frame to save them. In case
- incoming stack boundary is aligned to less than 16 bytes,
- unaligned move of SSE register will be emitted, so there is
- no point to round up the SSE register save area outside the
- re-aligned local stack frame to 16 bytes. */
- if (ix86_incoming_stack_boundary >= 128)
+ 16-byte aligned default stack. However, many programs violate
+ the ABI, and Wine64 forces stack realignment to compensate.
+
+ If the incoming stack boundary is at least 16 bytes, or DRAP is
+ required and the DRAP re-alignment boundary is at least 16 bytes,
+ then we want the SSE register save area properly aligned. */
+ if (ix86_incoming_stack_boundary >= 128
+ || (stack_realign_drap && stack_alignment_needed >= 16))
offset = ROUND_UP (offset, 16);
offset += frame->nsseregs * 16;
+ frame->stack_realign_allocate_offset = offset;
}
- frame->sse_reg_save_offset = offset;
- /* The re-aligned stack starts here. Values before this point are not
- directly comparable with values below this point. In order to make
- sure that no value happens to be the same before and after, force
- the alignment computation below to add a non-zero value. */
- if (stack_realign_fp)
- offset = ROUND_UP (offset, stack_alignment_needed);
+ frame->sse_reg_save_offset = offset;
/* Va-arg area */
frame->va_arg_size = ix86_varargs_gpr_size + ix86_varargs_fpr_size;