install EH code
authorMike Stump <mrs@gcc.gnu.org>
Tue, 23 Jul 1996 20:03:47 +0000 (20:03 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Tue, 23 Jul 1996 20:03:47 +0000 (20:03 +0000)
From-SVN: r12549

gcc/function.h
gcc/integrate.c
gcc/jump.c
gcc/libgcc2.c
gcc/loop.c
gcc/optabs.c
gcc/output.h
gcc/print-rtl.c
gcc/sched.c
gcc/stmt.c
gcc/varasm.c

index b70d6b93d192a323afcb91d4e50b335e756ace82..47bee4943db2a8ded5bf5390e89eb0c6fd89e9ca 100644 (file)
@@ -127,6 +127,14 @@ struct function
   int emit_lineno;
   struct goto_fixup *goto_fixup_chain;
 
+  /* For exception handling information.  */
+  struct eh_stack ehstack;
+  struct eh_queue ehqueue;
+  rtx catch_clauses;
+  struct label_node *false_label_stack;
+  struct label_node *caught_return_label_stack;
+  tree protect_list;
+
   /* For expr.c.  */
   int pending_stack_adjust;
   int inhibit_defer_pop;
index 106e4fe9ad427cd0e882b0cbd608478067b8fc08..f1e778a81d8033dab86ef37ee181c10be4d8b2a7 100644 (file)
@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "integrate.h"
 #include "real.h"
+#include "except.h"
 #include "function.h"
 #include "bytecode.h"
 
@@ -170,6 +171,19 @@ function_cannot_inline_p (fndecl)
   if (current_function_has_nonlocal_goto)
     return "function with nonlocal goto cannot be inline";
 
+  /* This is a hack, until the inliner is taught about eh regions at
+     the start of the function.  */
+  for (insn = get_insns ();
+       insn &&
+         ! (GET_CODE (insn) == NOTE
+           && NOTE_LINE_NUMBER (insn) == NOTE_INSN_FUNCTION_BEG);
+       insn = NEXT_INSN (insn))
+    {
+      if (insn && GET_CODE (insn) == NOTE
+         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+       return "function with complex parameters cannot be inline";
+    }
+
   return 0;
 }
 \f
@@ -309,6 +323,7 @@ initialize_for_inline (fndecl, min_labelno, max_labelno, max_reg, copy)
      the size of the incoming stack area for parameters,
      the number of bytes popped on return,
      the stack slot list,
+     the labels that are forced to exist,
      some flags that are used to restore compiler globals,
      the value of current_function_outgoing_args_size,
      the original argument vector,
@@ -335,7 +350,7 @@ finish_inline (fndecl, head)
      tree fndecl;
      rtx head;
 {
-  NEXT_INSN (head) = get_first_nonparm_insn ();
+  FIRST_FUNCTION_INSN (head) = get_first_nonparm_insn ();
   FIRST_PARM_INSN (head) = get_insns ();
   DECL_SAVED_INSNS (fndecl) = head;
   DECL_FRAME_SIZE (fndecl) = get_frame_size ();
@@ -565,6 +580,15 @@ save_for_inline_copying (fndecl)
              NOTE_SOURCE_FILE (insn) = (char *) copy;
              NOTE_SOURCE_FILE (copy) = 0;
            }
+         if (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
+             || NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END)
+           {
+             /* We have to forward these both to match the new exception
+                region.  */
+             NOTE_BLOCK_NUMBER (copy)
+               = CODE_LABEL_NUMBER (label_map[NOTE_BLOCK_NUMBER (copy)]);
+             
+           }
          RTX_INTEGRATED_P (copy) = RTX_INTEGRATED_P (insn);
          break;
 
@@ -1872,7 +1896,18 @@ expand_inline_function (fndecl, parms, target, ignore, type,
          if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_END
              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_FUNCTION_BEG
              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
-           copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+           {
+             copy = emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
+             if (copy && (NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_BEG
+                          || NOTE_LINE_NUMBER (copy) == NOTE_INSN_EH_REGION_END))
+               {
+                 rtx label = map->label_map[NOTE_BLOCK_NUMBER (copy)];
+
+                 /* We have to forward these both to match the new exception
+                    region.  */
+                 NOTE_BLOCK_NUMBER (copy) = CODE_LABEL_NUMBER (label);
+               }
+           }
          else
            copy = 0;
          break;
index b5e60fc3fc645fa95083fa58d533d9cb186763d3..61d712c6929223a7aa03baeb90ac2c3e483753bc 100644 (file)
@@ -60,6 +60,7 @@ Boston, MA 02111-1307, USA.  */
 #include "insn-flags.h"
 #include "expr.h"
 #include "real.h"
+#include "except.h"
 
 /* ??? Eventually must record somehow the labels used by jumps
    from nested functions.  */
@@ -234,6 +235,16 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
   for (insn = forced_labels; insn; insn = XEXP (insn, 1))
     LABEL_NUSES (XEXP (insn, 0))++;
 
+  check_exception_handler_labels ();
+
+  /* Keep track of labels used for marking handlers for exception
+     regions; they cannot usually be deleted.  */
+
+  for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
+    LABEL_NUSES (XEXP (insn, 0))++;
+
+  exception_optimize ();
+
   /* Delete all labels already not referenced.
      Also find the last insn.  */
 
index 043b431eb6c65bf8f319a0e793b0675cff580ca0..41801fa73b0619273ca0f0ee8a2685047b35d70f 100644 (file)
@@ -2989,6 +2989,13 @@ int _exit_dummy_decl = 0;        /* prevent compiler & linker warnings */
 #endif /* L_exit */
 \f
 #ifdef L_eh
+
+#ifdef EH_TABLE_LOOKUP
+
+EH_TABLE_LOOKUP
+
+#else
+
 typedef struct {
   void *start;
   void *end;
@@ -3095,21 +3102,9 @@ void *pc;
 #endif
 
 #if 0
-  printf("find_first_eh_table_match(): else: returning NULL!\n");
-#endif
-  return (void*)0;
-}
-
-void *
-__throw_type_match (void *catch_type, void *throw_type, void* obj)
-{
-#if 0
- printf("__throw_type_match (): catch_type = %s, throw_type = %s\n",
-       catch_type, throw_type);
+  printf ("find_first_eh_table_match(): else: returning NULL!\n");
 #endif
- if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
-   return obj;
- return 0;
+  return (void *) 0;
 }
 
 void
@@ -3140,6 +3135,19 @@ __register_exceptions (exception_table *table)
   node->next = exception_table_list;
   exception_table_list = node;
 }
+#endif
+
+void *
+__throw_type_match (void *catch_type, void *throw_type, void *obj)
+{
+#if 0
+ printf ("__throw_type_match (): catch_type = %s, throw_type = %s\n",
+        catch_type, throw_type);
+#endif
+ if (strcmp ((const char *)catch_type, (const char *)throw_type) == 0)
+   return obj;
+ return 0;
+}
 
 void
 __empty ()
index 4ac5d76b36b83675d1317414626f526086a82951..f4670fd073561a66760caecde8dc5d6651be8827 100644 (file)
@@ -47,6 +47,7 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "real.h"
 #include "loop.h"
+#include "except.h"
 
 /* Vector mapping INSN_UIDs to luids.
    The luids are like uids but increase monotonically always.
@@ -2290,6 +2291,19 @@ find_and_verify_loops (f)
        loop_invalid[loop_num] = 1;
     }
 
+  /* Any loop containing a label used for an exception handler must be
+     invalidated, because it can be jumped into from anywhere.  */
+
+  for (label = exception_handler_labels; label; label = XEXP (label, 1))
+    {
+      int loop_num;
+
+      for (loop_num = uid_loop_num[INSN_UID (XEXP (label, 0))];
+          loop_num != -1;
+          loop_num = loop_outer_loop[loop_num])
+       loop_invalid[loop_num] = 1;
+    }
+
   /* Now scan all insn's in the function.  If any JUMP_INSN branches into a
      loop that it is not contained within, that loop is marked invalid.
      If any INSN or CALL_INSN uses a label's address, then the loop containing
index a30819753a53a0c22a39bbb49adf7534d705450f..ba4b72f147d303940c3339829c94526971ea7d2d 100644 (file)
@@ -118,6 +118,8 @@ rtx bcmp_libfunc;
 rtx memset_libfunc;
 rtx bzero_libfunc;
 
+rtx throw_libfunc;
+
 rtx eqhf2_libfunc;
 rtx nehf2_libfunc;
 rtx gthf2_libfunc;
@@ -4247,6 +4249,8 @@ init_optabs ()
   memset_libfunc = gen_rtx (SYMBOL_REF, Pmode, "memset");
   bzero_libfunc = gen_rtx (SYMBOL_REF, Pmode, "bzero");
 
+  throw_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__throw");
+
   eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
   nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
   gthf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__gthf2");
index 7ef8b2c61b10e299c9e0a2be772a23fbe8567e4a..8722b64759027bc6dab9436e9d82bf1989b15104 100644 (file)
@@ -140,6 +140,9 @@ extern void named_section           PROTO((tree, char *));
 /* Tell assembler to switch to the section for function DECL.  */
 extern void function_section           PROTO((tree));
 
+/* Tell assembler to switch to the section for the exception table.  */
+extern void exception_section          PROTO((void));
+
 /* Create the rtl to represent a function, for a function definition.
    DECL is a FUNCTION_DECL node which describes which function.
    The rtl is stored into DECL.  */
index 20d34dbdc8e88431b901d9814a2243f921401aba..93153d4b967cbd387c1f7aada0ed5d29076a4e68 100644 (file)
@@ -108,6 +108,14 @@ print_rtx (in_rtx)
       {
       case 'S':
       case 's':
+       if (i == 3 && GET_CODE (in_rtx) == NOTE
+           && (NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_BEG
+               || NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_EH_REGION_END))
+         {
+           fprintf (outfile, " %d", NOTE_BLOCK_NUMBER (in_rtx));
+           sawclose = 1;
+           break;
+         }
        if (XSTR (in_rtx, i) == 0)
          fprintf (outfile, " \"\"");
        else
index 82acf33277fc0940b448e22d2c0e58bb60d850d0..c186cfc06994cf0a73aac3793ce46951876a8e17 100644 (file)
@@ -111,9 +111,11 @@ Boston, MA 02111-1307, USA.  */
    reg_n_calls_crossed, and reg_live_length.  Also, basic_block_head,
    basic_block_end.
 
-   The information in the line number notes is carefully retained by this
-   pass.  All other NOTE insns are grouped in their same relative order at
-   the beginning of basic blocks that have been scheduled.  */
+   The information in the line number notes is carefully retained by
+   this pass.  Notes that refer to the starting and ending of
+   exception regions are also carefully retained by this pass.  All
+   other NOTE insns are grouped in their same relative order at the
+   beginning of basic blocks that have been scheduled.  */
 \f
 #include <stdio.h>
 #include "config.h"
@@ -2078,7 +2080,7 @@ sched_analyze_insn (x, insn, loop_notes)
          sched_analyze_2 (XEXP (link, 0), insn);
       }
 
-  /* If there is a LOOP_{BEG,END} note in the middle of a basic block, then
+  /* If there is a {LOOP,EHREGION}_{BEG,END} note in the middle of a basic block, then
      we must be sure that no instructions are scheduled across it.
      Otherwise, the reg_n_refs info (which depends on loop_depth) would
      become incorrect.  */
@@ -2240,8 +2242,13 @@ sched_analyze (head, tail)
                }
              reg_pending_sets_all = 1;
 
-             /* Add a fake REG_NOTE which we will later convert
-                back into a NOTE_INSN_SETJMP note.  */
+             /* Add a pair of fake REG_NOTEs which we will later
+                convert back into a NOTE_INSN_SETJMP note.  See
+                reemit_notes for why we use a pair of of NOTEs.  */
+
+             REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
+                                         GEN_INT (0),
+                                         REG_NOTES (insn));
              REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_DEAD,
                                          GEN_INT (NOTE_INSN_SETJMP),
                                          REG_NOTES (insn));
@@ -2285,12 +2292,18 @@ sched_analyze (head, tail)
          last_function_call = insn;
          n_insns += 1;
        }
+
+      /* See comments on reemit_notes as to why we do this.  */
       else if (GET_CODE (insn) == NOTE
               && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
                   || NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END
+                  || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
+                  || NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
                   || (NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP
                       && GET_CODE (PREV_INSN (insn)) != CALL_INSN)))
        {
+         loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
+                               GEN_INT (NOTE_BLOCK_NUMBER (insn)), loop_notes);
          loop_notes = gen_rtx (EXPR_LIST, REG_DEAD,
                                GEN_INT (NOTE_LINE_NUMBER (insn)), loop_notes);
          CONST_CALL_P (loop_notes) = CONST_CALL_P (insn);
@@ -3077,10 +3090,12 @@ unlink_notes (insn, tail)
       /* Don't save away NOTE_INSN_SETJMPs, because they must remain
         immediately after the call they follow.  We use a fake
         (REG_DEAD (const_int -1)) note to remember them.
-        Likewise with NOTE_INSN_LOOP_BEG and NOTE_INSN_LOOP_END.  */
+        Likewise with NOTE_INSN_{LOOP,EHREGION}_{BEG, END}.  */
       else if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_SETJMP
               && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG
-              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END)
+              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_END
+              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
+              && NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_END)
        {
          /* Insert the note at the end of the notes list.  */
          PREV_INSN (insn) = note_list;
@@ -3143,10 +3158,12 @@ finish_sometimes_live (regs_sometimes_live, sometimes_max)
     }
 }
 
-/* Search INSN for fake REG_DEAD notes for NOTE_INSN_SETJMP,
-   NOTE_INSN_LOOP_BEG, and NOTE_INSN_LOOP_END; and convert them back
-   into NOTEs.  LAST is the last instruction output by the instruction
-   scheduler.  Return the new value of LAST.  */
+/* Search INSN for fake REG_DEAD note pairs for NOTE_INSN_SETJMP,
+   NOTE_INSN_{LOOP,EHREGION}_{BEG,END}; and convert them back into
+   NOTEs.  The REG_DEAD note following first one is contains the saved
+   value for NOTE_BLOCK_NUMBER which is useful for
+   NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  LAST is the last instruction
+   output by the instruction scheduler.  Return the new value of LAST.  */
 
 static rtx
 reemit_notes (insn, last)
@@ -3161,10 +3178,19 @@ reemit_notes (insn, last)
          && GET_CODE (XEXP (note, 0)) == CONST_INT)
        {
          if (INTVAL (XEXP (note, 0)) == NOTE_INSN_SETJMP)
-           CONST_CALL_P (emit_note_after (INTVAL (XEXP (note, 0)), insn))
-             = CONST_CALL_P (note);
+           {
+             CONST_CALL_P (emit_note_after (INTVAL (XEXP (note, 0)), insn))
+               = CONST_CALL_P (note);
+             remove_note (insn, note);
+             note = XEXP (note, 1);
+           }
          else
-           last = emit_note_before (INTVAL (XEXP (note, 0)), last);
+           {
+             last = emit_note_before (INTVAL (XEXP (note, 0)), last);
+             remove_note (insn, note);
+             note = XEXP (note, 1);
+             NOTE_BLOCK_NUMBER (last) = INTVAL (XEXP (note, 0));
+           }
          remove_note (insn, note);
        }
     }
@@ -3961,8 +3987,8 @@ schedule_block (b, file)
            }
        }
 
-      /* Put back NOTE_INSN_SETJMP, NOTE_INSN_LOOP_BEGIN, and
-        NOTE_INSN_LOOP_END notes.  */
+      /* Put back NOTE_INSN_SETJMP,
+         NOTE_INSN_{LOOP,EHREGION}_{BEGIN,END} notes.  */
 
       /* To prime the loop.  We need to handle INSN and all the insns in the
          sched group.  */
index 6d6443f43ef148284c9e3272d02762c97fbc3a2a..b443fc428f345e9b016a9196c0e6c3460e497a73 100644 (file)
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "tree.h"
 #include "flags.h"
+#include "except.h"
 #include "function.h"
 #include "insn-flags.h"
 #include "insn-config.h"
@@ -134,8 +135,6 @@ extern tree rtl_expr_chain;
    cleanup list whenever an empty list is required.  */
 static tree empty_cleanup_list;
 #endif
-
-extern void (*interim_eh_hook) PROTO((tree));
 \f
 /* Functions and data structures for expanding case statements.  */
 
@@ -473,9 +472,7 @@ void
 init_stmt ()
 {
   gcc_obstack_init (&stmt_obstack);
-#if 0
-  empty_cleanup_list = build_tree_list (NULL_TREE, NULL_TREE);
-#endif
+  init_eh ();
 }
 
 void
@@ -498,6 +495,8 @@ init_stmt_for_function ()
   /* We are not processing a ({...}) grouping.  */
   expr_stmts_for_value = 0;
   last_expr_type = 0;
+
+  init_eh_for_function ();
 }
 
 void
@@ -518,6 +517,7 @@ save_stmt_status (p)
   p->emit_filename = emit_filename;
   p->emit_lineno = emit_lineno;
   p->goto_fixup_chain = goto_fixup_chain;
+  save_eh_status (p);
 }
 
 void
@@ -538,6 +538,7 @@ restore_stmt_status (p)
   emit_filename = p->emit_filename;
   emit_lineno = p->emit_lineno;
   goto_fixup_chain = p->goto_fixup_chain;
+  restore_eh_status (p);
 }
 \f
 /* Emit a no-op instruction.  */
@@ -3730,7 +3731,7 @@ expand_decl_cleanup (decl, cleanup)
        = temp_tree_cons (decl, cleanup, thisblock->data.block.cleanups);
       /* If this block has a cleanup, it belongs in stack_block_stack.  */
       stack_block_stack = thisblock;
-      (*interim_eh_hook) (NULL_TREE);
+      expand_eh_region_start ();
     }
   return 1;
 }
@@ -3831,7 +3832,7 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
        else
          {
            if (! in_fixup)
-             (*interim_eh_hook) (TREE_VALUE (tail));
+             expand_eh_region_end (TREE_VALUE (tail));
 
            if (reachable)
              {
index 3878e8b893ee71110183267e7b969202044ccc0c..67a31ca998cf13b032684cdc0255cd886a48edca 100644 (file)
@@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "tree.h"
 #include "flags.h"
+#include "except.h"
 #include "function.h"
 #include "expr.h"
 #include "output.h"
@@ -414,6 +415,26 @@ variable_section (decl, reloc)
 #endif
     }
 }
+
+/* Tell assembler to switch to the section for the exception handling
+   table.  */
+
+void
+exception_section ()
+{
+#ifdef ASM_OUTPUT_SECTION_NAME
+  named_section (NULL_TREE, ".gcc_except_table");
+#else
+  if (flag_pic)
+    data_section ();
+  else
+#if defined (EXCEPTION_SECTION)
+    EXCEPTION_SECTION ();
+#else
+    readonly_data_section ();
+#endif
+#endif
+}
 \f
 /* Create the rtl to represent a function, for a function definition.
    DECL is a FUNCTION_DECL node which describes which function.