diff options
author | Jim Wilson <wilson@redhat.com> | 2001-03-27 23:15:04 +0000 |
---|---|---|
committer | Jim Wilson <wilson@gcc.gnu.org> | 2001-03-27 15:15:04 -0800 |
commit | ad0fc6987804eb16dccee061dc63fdd6ca07be48 (patch) | |
tree | 532d2ee7bd30f32f7fe080f207dfdccba9120355 /gcc | |
parent | 911e61070f7b39ca392345444b1f91411aad3925 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 53 | ||||
-rw-r--r-- | gcc/final.c | 3 |
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); |