aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c92
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