diff options
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 61 |
1 files changed, 53 insertions, 8 deletions
diff --git a/gcc/function.c b/gcc/function.c index 3024383..954e946 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -377,6 +377,7 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size, poly_int64 bigend_correction = 0; poly_int64 slot_offset = 0, old_frame_offset; unsigned int alignment, alignment_in_bits; + bool dynamic_align_addr = false; if (align == 0) { @@ -395,14 +396,20 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size, alignment_in_bits = alignment * BITS_PER_UNIT; - /* Ignore alignment if it exceeds MAX_SUPPORTED_STACK_ALIGNMENT. */ if (alignment_in_bits > MAX_SUPPORTED_STACK_ALIGNMENT) { - alignment_in_bits = MAX_SUPPORTED_STACK_ALIGNMENT; - alignment = alignment_in_bits / BITS_PER_UNIT; + /* If the required alignment exceeds MAX_SUPPORTED_STACK_ALIGNMENT and + it is not OK to reduce it. Align the slot dynamically. */ + if (mode == BLKmode && (kind & ASLK_REDUCE_ALIGN) == 0) + dynamic_align_addr = true; + else + { + alignment_in_bits = MAX_SUPPORTED_STACK_ALIGNMENT; + alignment = MAX_SUPPORTED_STACK_ALIGNMENT / BITS_PER_UNIT; + } } - if (SUPPORTS_STACK_ALIGNMENT) + if (SUPPORTS_STACK_ALIGNMENT && !dynamic_align_addr) { if (crtl->stack_alignment_estimated < alignment_in_bits) { @@ -432,10 +439,42 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size, } } - if (crtl->stack_alignment_needed < alignment_in_bits) - crtl->stack_alignment_needed = alignment_in_bits; - if (crtl->max_used_stack_slot_alignment < alignment_in_bits) - crtl->max_used_stack_slot_alignment = alignment_in_bits; + /* Handle overalignment here for parameter copy on the stack. + Reserved enough space for it and dynamically align the address. + No free frame_space is added here. */ + if (dynamic_align_addr) + { + rtx allocsize = gen_int_mode (size, Pmode); + get_dynamic_stack_size (&allocsize, 0, alignment_in_bits, NULL); + + /* This is the size of space needed to accommodate required size of data + with given alignment. */ + poly_int64 len = rtx_to_poly_int64 (allocsize); + old_frame_offset = frame_offset; + + if (FRAME_GROWS_DOWNWARD) + { + frame_offset -= len; + try_fit_stack_local (frame_offset, len, len, + PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT, + &slot_offset); + } + else + { + frame_offset += len; + try_fit_stack_local (old_frame_offset, len, len, + PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT, + &slot_offset); + } + goto found_space; + } + else + { + if (crtl->stack_alignment_needed < alignment_in_bits) + crtl->stack_alignment_needed = alignment_in_bits; + if (crtl->max_used_stack_slot_alignment < alignment_in_bits) + crtl->max_used_stack_slot_alignment = alignment_in_bits; + } if (mode != BLKmode || maybe_ne (size, 0)) { @@ -522,6 +561,12 @@ assign_stack_local_1 (machine_mode mode, poly_int64 size, (slot_offset + bigend_correction, Pmode)); + if (dynamic_align_addr) + { + addr = align_dynamic_address (addr, alignment_in_bits); + mark_reg_pointer (addr, alignment_in_bits); + } + x = gen_rtx_MEM (mode, addr); set_mem_align (x, alignment_in_bits); MEM_NOTRAP_P (x) = 1; |