aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJim Wilson <wilson@redhat.com>2001-03-27 23:15:04 +0000
committerJim Wilson <wilson@gcc.gnu.org>2001-03-27 15:15:04 -0800
commitad0fc6987804eb16dccee061dc63fdd6ca07be48 (patch)
tree532d2ee7bd30f32f7fe080f207dfdccba9120355 /gcc
parent911e61070f7b39ca392345444b1f91411aad3925 (diff)
downloadgcc-ad0fc6987804eb16dccee061dc63fdd6ca07be48.zip
gcc-ad0fc6987804eb16dccee061dc63fdd6ca07be48.tar.gz
gcc-ad0fc6987804eb16dccee061dc63fdd6ca07be48.tar.bz2
Fix ia64-linux kernel miscompile, bad unwind info when reorder epilogue block.
* final.c (final_scan_insn, case NOTE_INSN_BASIC_BLOCK): Call IA64_UNWIND_EMIT. * config/ia64/ia64.c (block_num, need_copy_state): New static vars. (process_epilogue): New static function. (process_set): Call process_epilogue instead of emitting .restore directly. (process_for_unwind_directive): Handle NOTE_INSN_BASIC_BLOCK. From-SVN: r40885
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/ia64/ia64.c53
-rw-r--r--gcc/final.c3
3 files changed, 58 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 22b2f62..7aa2bde 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -7,6 +7,14 @@
2001-03-27 Jim Wilson <wilson@redhat.com>
+ * final.c (final_scan_insn, case NOTE_INSN_BASIC_BLOCK): Call
+ IA64_UNWIND_EMIT.
+ * config/ia64/ia64.c (block_num, need_copy_state): New static vars.
+ (process_epilogue): New static function.
+ (process_set): Call process_epilogue instead of emitting .restore
+ directly.
+ (process_for_unwind_directive): Handle NOTE_INSN_BASIC_BLOCK.
+
* flow.c (struct reg_cond_life_info): New fields orig_condition
and stores.
(init_propagate_block_info): Set new fields.
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 3d30ff8..63d830d 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -6335,7 +6335,32 @@ ia64_encode_section_info (decl)
}
}
-/* Output assmebly directives for prologue regions. */
+/* Output assembly directives for prologue regions. */
+
+/* The current basic block number. */
+
+static int block_num;
+
+/* True if we need a copy_state command at the start of the next block. */
+
+static int need_copy_state;
+
+/* The function emits unwind directives for the start of an epilogue. */
+
+static void
+process_epilogue ()
+{
+ /* If this isn't the last block of the function, then we need to label the
+ current state, and copy it back in at the start of the next block. */
+
+ if (block_num != n_basic_blocks - 1)
+ {
+ fprintf (asm_out_file, "\t.label_state 1\n");
+ need_copy_state = 1;
+ }
+
+ fprintf (asm_out_file, "\t.restore sp\n");
+}
/* This function processes a SET pattern looking for specific patterns
which result in emitting an assembly directive required for unwinding. */
@@ -6383,14 +6408,14 @@ process_set (asm_out_file, pat)
fputc ('\n', asm_out_file);
}
else
- fprintf (asm_out_file, "\t.restore sp\n");
+ process_epilogue ();
}
else
abort ();
}
else if (GET_CODE (src) == REG
&& REGNO (src) == HARD_FRAME_POINTER_REGNUM)
- fprintf (asm_out_file, "\t.restore sp\n");
+ process_epilogue ();
else
abort ();
@@ -6561,12 +6586,28 @@ process_for_unwind_directive (asm_out_file, insn)
FILE *asm_out_file;
rtx insn;
{
- if ((flag_unwind_tables
- || (flag_exceptions && !exceptions_via_longjmp))
- && RTX_FRAME_RELATED_P (insn))
+ if (flag_unwind_tables
+ || (flag_exceptions && !exceptions_via_longjmp))
{
rtx pat;
+ if (GET_CODE (insn) == NOTE
+ && NOTE_LINE_NUMBER (insn) == NOTE_INSN_BASIC_BLOCK)
+ {
+ block_num = NOTE_BASIC_BLOCK (insn)->index;
+
+ /* Restore unwind state from immediately before the epilogue. */
+ if (need_copy_state)
+ {
+ fprintf (asm_out_file, "\t.body\n");
+ fprintf (asm_out_file, "\t.copy_state 1\n");
+ need_copy_state = 0;
+ }
+ }
+
+ if (! RTX_FRAME_RELATED_P (insn))
+ return;
+
pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
if (pat)
pat = XEXP (pat, 0);
diff --git a/gcc/final.c b/gcc/final.c
index 402ff8c..cdc2de4 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -2117,6 +2117,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
break;
case NOTE_INSN_BASIC_BLOCK:
+#ifdef IA64_UNWIND_INFO
+ IA64_UNWIND_EMIT (asm_out_file, insn);
+#endif
if (flag_debug_asm)
fprintf (asm_out_file, "\t%s basic block %d\n",
ASM_COMMENT_START, NOTE_BASIC_BLOCK (insn)->index);