diff options
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 92 |
1 files changed, 77 insertions, 15 deletions
diff --git a/gcc/function.c b/gcc/function.c index 0937844d812..a4033a9a6b8 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -786,6 +786,10 @@ assign_stack_local (mode, size, align) else alignment = align / BITS_PER_UNIT; +#ifdef FRAME_GROWS_DOWNWARD + frame_offset -= size; +#endif + /* Round frame offset to that alignment. We must be careful here, since FRAME_OFFSET might be negative and division with a negative dividend isn't as well defined as we might @@ -802,10 +806,6 @@ assign_stack_local (mode, size, align) if (BYTES_BIG_ENDIAN && mode != BLKmode) bigend_correction = size - GET_MODE_SIZE (mode); -#ifdef FRAME_GROWS_DOWNWARD - frame_offset -= size; -#endif - /* If we have already instantiated virtual registers, return the actual address relative to the frame pointer. */ if (virtuals_instantiated) @@ -871,6 +871,10 @@ assign_outer_stack_local (mode, size, align, function) else alignment = align / BITS_PER_UNIT; +#ifdef FRAME_GROWS_DOWNWARD + function->frame_offset -= size; +#endif + /* Round frame offset to that alignment. */ #ifdef FRAME_GROWS_DOWNWARD function->frame_offset = FLOOR_ROUND (function->frame_offset, alignment); @@ -883,9 +887,6 @@ assign_outer_stack_local (mode, size, align, function) if (BYTES_BIG_ENDIAN && mode != BLKmode) bigend_correction = size - GET_MODE_SIZE (mode); -#ifdef FRAME_GROWS_DOWNWARD - function->frame_offset -= size; -#endif addr = plus_constant (virtual_stack_vars_rtx, function->frame_offset + bigend_correction); #ifndef FRAME_GROWS_DOWNWARD @@ -1027,11 +1028,12 @@ assign_stack_temp_for_type (mode, size, keep, type) So for requests which depended on the rounding of SIZE, we go ahead and round it now. We also make sure ALIGNMENT is at least BIGGEST_ALIGNMENT. */ - if (mode == BLKmode && align < (BIGGEST_ALIGNMENT / BITS_PER_UNIT)) + if (mode == BLKmode && align < BIGGEST_ALIGNMENT) abort(); p->slot = assign_stack_local (mode, - mode == BLKmode - ? CEIL_ROUND (size, align) : size, + (mode == BLKmode + ? CEIL_ROUND (size, align / BITS_PER_UNIT) + : size), align); p->align = align; @@ -1426,7 +1428,16 @@ free_temps_for_rtl_expr (t) for (p = temp_slots; p; p = p->next) if (p->rtl_expr == t) - p->in_use = 0; + { + /* If this slot is below the current TEMP_SLOT_LEVEL, then it + needs to be preserved. This can happen if a temporary in + the RTL_EXPR was addressed; preserve_temp_slots will move + the temporary into a higher level. */ + if (temp_slot_level <= p->level) + p->in_use = 0; + else + p->rtl_expr = NULL_TREE; + } combine_temp_slots (); } @@ -6693,7 +6704,10 @@ void thread_prologue_and_epilogue_insns (f) rtx f ATTRIBUTE_UNUSED; { - int insertted = 0; + int inserted = 0; +#ifdef HAVE_prologue + rtx prologue_end = NULL_RTX; +#endif prologue = 0; #ifdef HAVE_prologue @@ -6710,7 +6724,7 @@ thread_prologue_and_epilogue_insns (f) seq = get_insns (); prologue = record_insns (seq); - emit_note (NULL, NOTE_INSN_PROLOGUE_END); + prologue_end = emit_note (NULL, NOTE_INSN_PROLOGUE_END); seq = gen_sequence (); end_sequence (); @@ -6723,7 +6737,7 @@ thread_prologue_and_epilogue_insns (f) abort (); insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ); - insertted = 1; + inserted = 1; } else emit_insn_after (seq, f); @@ -6855,8 +6869,56 @@ thread_prologue_and_epilogue_insns (f) } #endif - if (insertted) + if (inserted) commit_edge_insertions (); + +#ifdef HAVE_prologue + if (prologue_end) + { + rtx insn, prev; + + /* GDB handles `break f' by setting a breakpoint on the first + line note *after* the prologue. Which means (1) that if + there are line number notes before where we inserted the + prologue we should move them, and (2) if there is no such + note, then we should generate one at the prologue. */ + + for (insn = prologue_end; insn ; insn = prev) + { + prev = PREV_INSN (insn); + if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) + { + /* Note that we cannot reorder the first insn in the + chain, since rest_of_compilation relies on that + remaining constant. Do the next best thing. */ + if (prev == NULL) + { + emit_line_note_after (NOTE_SOURCE_FILE (insn), + NOTE_LINE_NUMBER (insn), + prologue_end); + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; + } + else + reorder_insns (insn, insn, prologue_end); + } + } + + insn = NEXT_INSN (prologue_end); + if (! insn || GET_CODE (insn) != NOTE || NOTE_LINE_NUMBER (insn) <= 0) + { + for (insn = next_active_insn (f); insn ; insn = PREV_INSN (insn)) + { + if (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) > 0) + { + emit_line_note_after (NOTE_SOURCE_FILE (insn), + NOTE_LINE_NUMBER (insn), + prologue_end); + break; + } + } + } + } + #endif } /* Reposition the prologue-end and epilogue-begin notes after instruction |