Fix ia64-linux kernel miscompile, bad unwind info when reorder epilogue block.
authorJim Wilson <wilson@redhat.com>
Tue, 27 Mar 2001 23:15:04 +0000 (23:15 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Tue, 27 Mar 2001 23:15:04 +0000 (15:15 -0800)
* 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
gcc/config/ia64/ia64.c
gcc/final.c

index 22b2f62bd372da4a34ce73cd4705432b568ccdac..7aa2bdeccc61c4d1689622da65939792d5839e8b 100644 (file)
@@ -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.
index 3d30ff872e6bf8437a7b240b7bd21ed1f0789cef..63d830de216c2476ed0ba101672e1cd54103b4f8 100644 (file)
@@ -6335,7 +6335,32 @@ ia64_encode_section_info (decl)
     }
 }
 \f
-/* 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);
index 402ff8c22721dc54f48377d662238bfbe71d4e59..cdc2de49c5ab429b541b6a9f5a8009c16f32c20b 100644 (file)
@@ -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);