From ad0fc6987804eb16dccee061dc63fdd6ca07be48 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Tue, 27 Mar 2001 23:15:04 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 8 +++++++ gcc/config/ia64/ia64.c | 53 +++++++++++++++++++++++++++++++++++++----- gcc/final.c | 3 +++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 22b2f62bd37..7aa2bdeccc6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -7,6 +7,14 @@ 2001-03-27 Jim Wilson + * 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 3d30ff872e6..63d830de216 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 402ff8c2272..cdc2de49c5a 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); -- 2.30.2