OSDN Git Service

Tue Sep 15 14:10:54 EDT 1998 Andrew MacLeod <amacleod@cygnus.com>
authoramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Sep 1998 11:20:52 +0000 (11:20 +0000)
committeramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 15 Sep 1998 11:20:52 +0000 (11:20 +0000)
        * except.h (struct eh_entry): Add false_label field.
        (end_catch_handler): Add prototype.
        * except.c (push_eh_entry): Set false_label field to NULL_RTX.
        (start_catch_handler): When using old style exceptions, issue
        runtime typematch code before continuing with the handler.
        (end_catch_handler): New function, generates label after handler
        if needed by older style exceptions.
        (expand_start_all_catch): No need to check for new style exceptions.
        (output_exception_table_entry): Only output the first handler label
        for old style exceptions.
        * libgcc2.c (__eh_rtime_match): New routine to lump runtime matching
        mechanism into one function, if a runtime matcher is provided.
1998-09-15  Andrew MacLeod  <amacleod@cygnus.com>
        * cp/except.c (expand_start_catch_block): No need to check for new
        exception model.
        (process_start_catch_block_old): Deleted.
        (process_start_catch_block): Add call to start_decl_1().
        (expand_end_catch_block): Add call to end_catch_handler().
        * cp/exception.cc (__cplus_type_matcher): Only check the exception
        language if there is an exception table.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@22425 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/except.c
gcc/cp/exception.cc
gcc/except.c
gcc/except.h
gcc/libgcc2.c

index 05ded0c..44e65f4 100644 (file)
@@ -1,3 +1,18 @@
+Tue Sep 15 14:10:54 EDT 1998  Andrew MacLeod  <amacleod@cygnus.com>
+
+       * except.h (struct eh_entry): Add false_label field.
+       (end_catch_handler): Add prototype.
+       * except.c (push_eh_entry): Set false_label field to NULL_RTX.
+       (start_catch_handler): When using old style exceptions, issue
+       runtime typematch code before continuing with the handler.
+       (end_catch_handler): New function, generates label after handler
+       if needed by older style exceptions.
+       (expand_start_all_catch): No need to check for new style exceptions.
+       (output_exception_table_entry): Only output the first handler label
+       for old style exceptions.
+       * libgcc2.c (__eh_rtime_match): New routine to lump runtime matching
+       mechanism into one function, if a runtime matcher is provided.
+
 Tue Sep 15 13:53:59 EDT 1998  Andrew MacLeod  <amacleod@cygnus.com>
 
        * config/i960/i960.h (SLOW_BYTE_ACCESS): Change definition to 1.
index 6fd77b1..9ed5652 100644 (file)
@@ -1,5 +1,15 @@
 1998-09-15  Andrew MacLeod  <amacleod@cygnus.com>
 
+       * except.c (expand_start_catch_block): No need to check for new
+       exception model.
+       (process_start_catch_block_old): Deleted.
+       (process_start_catch_block): Add call to start_decl_1().
+       (expand_end_catch_block): Add call to end_catch_handler().
+       * exception.cc (__cplus_type_matcher): Only check the exception 
+       language if there is an exception table.
+
+1998-09-15  Andrew MacLeod  <amacleod@cygnus.com>
+
        * search.c (expand_indirect_vtbls_init): Mark temporary stack slots
        as used to prevent conflicts with virtual function tables.
 
index 69315be..c3ae357 100644 (file)
@@ -597,135 +597,14 @@ expand_start_catch_block (declspecs, declarator)
   if (! doing_eh (1))
     return;
 
-  if (flag_new_exceptions)
-    process_start_catch_block (declspecs, declarator);
-  else
-    process_start_catch_block_old (declspecs, declarator);
+  process_start_catch_block (declspecs, declarator);
 }
 
 
 /* This function performs the expand_start_catch_block functionality for 
-   exceptions implemented in the old style, where catch blocks were all
-   called, and had to check the runtime information themselves. */
-
-static void 
-process_start_catch_block_old (declspecs, declarator)
-     tree declspecs, declarator;
-{
-  rtx false_label_rtx;
-  tree decl = NULL_TREE;
-  tree init;
-
-  /* Create a binding level for the eh_info and the exception object
-     cleanup.  */
-  pushlevel (0);
-  expand_start_bindings (0);
-
-  false_label_rtx = gen_label_rtx ();
-  push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
-
-  emit_line_note (input_filename, lineno);
-
-  push_eh_info ();
-
-  if (declspecs)
-    {
-      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
-
-      if (decl == NULL_TREE)
-       error ("invalid catch parameter");
-    }
-
-  if (decl)
-    {
-      tree exp;
-      rtx call_rtx, return_value_rtx;
-      tree init_type;
-
-      /* Make sure we mark the catch param as used, otherwise we'll get
-        a warning about an unused ((anonymous)).  */
-      TREE_USED (decl) = 1;
-
-      /* Figure out the type that the initializer is.  */
-      init_type = TREE_TYPE (decl);
-      if (TREE_CODE (init_type) != REFERENCE_TYPE
-         && TREE_CODE (init_type) != POINTER_TYPE)
-       init_type = build_reference_type (init_type);
-
-      exp = get_eh_value ();
-
-      /* Since pointers are passed by value, initialize a reference to
-        pointer catch parm with the address of the value slot.  */
-      if (TREE_CODE (init_type) == REFERENCE_TYPE
-         && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
-       exp = build_unary_op (ADDR_EXPR, exp, 1);
-
-      exp = expr_tree_cons (NULL_TREE,
-                      build_eh_type_type (TREE_TYPE (decl)),
-                      expr_tree_cons (NULL_TREE,
-                                 get_eh_type (),
-                                 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
-      exp = build_function_call (CatchMatch, exp);
-      call_rtx = expand_call (exp, NULL_RTX, 0);
-
-      return_value_rtx = hard_function_value (ptr_type_node, exp);
-
-      /* did the throw type match function return TRUE? */
-      emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
-                   GET_MODE (return_value_rtx), 0, 0);
-
-      /* if it returned FALSE, jump over the catch block, else fall into it */
-      emit_jump_insn (gen_beq (false_label_rtx));
-
-      push_eh_cleanup ();
-
-      /* Create a binding level for the parm.  */
-      pushlevel (0);
-      expand_start_bindings (0);
-
-      init = convert_from_reference (make_tree (init_type, call_rtx));
-
-      /* If the constructor for the catch parm exits via an exception, we
-         must call terminate.  See eh23.C.  */
-      if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
-       {
-         /* Generate the copy constructor call directly so we can wrap it.
-            See also expand_default_init.  */
-         init = ocp_convert (TREE_TYPE (decl), init,
-                             CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
-         init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
-                       build_terminate_handler ());
-       }
-
-      /* Let `cp_finish_decl' know that this initializer is ok.  */
-      DECL_INITIAL (decl) = init;
-      decl = pushdecl (decl);
-
-      start_decl_1 (decl);
-      cp_finish_decl (decl, DECL_INITIAL (decl),
-                     NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
-    }
-  else
-    {
-      push_eh_cleanup ();
-
-      /* Create a binding level for the parm.  */
-      pushlevel (0);
-      expand_start_bindings (0);
-
-      /* Fall into the catch all section.  */
-    }
-
-  init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
-  expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
-  emit_line_note (input_filename, lineno);
-}
-
-/* This function performs the expand_start_catch_block functionality for 
    exceptions implemented in the new style. __throw determines whether
    a handler needs to be called or not, so the handler itself has to do
-   nothing additionaal. */
+   nothing additional. */
 
 static void 
 process_start_catch_block (declspecs, declarator)
@@ -806,6 +685,7 @@ process_start_catch_block (declspecs, declarator)
       DECL_INITIAL (decl) = init;
       decl = pushdecl (decl);
 
+      start_decl_1 (decl);
       cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
     }
   else
@@ -849,10 +729,7 @@ expand_end_catch_block ()
      documentation.  */
   expand_goto (top_label_entry (&caught_return_label_stack));
 
-  /* label we emit to jump to if this catch block didn't match.  */
-  /* This the closing } in the `if (eq) {' of the documentation.  */
-  if (! flag_new_exceptions)
-    emit_label (pop_label_entry (&false_label_stack));
+  end_catch_handler ();
 }
 
 /* An exception spec is implemented more or less like:
index 4c10404..5fafd1f 100644 (file)
@@ -157,7 +157,9 @@ __cplus_type_matcher (cp_eh_info *info, rtimetype match_info,
 {
   void *ret;
 
-  if (exception_table->lang.language != EH_LANG_C_plus_plus)
+  /* No exception table implies the old style mechanism, so don't check. */
+  if (exception_table != NULL && 
+                        exception_table->lang.language != EH_LANG_C_plus_plus)
     return NULL;
 
   if (match_info == CATCH_ALL_TYPE)
index 5f2c61a..f0d0009 100644 (file)
@@ -597,6 +597,7 @@ push_eh_entry (stack)
   entry->finalization = NULL_TREE;
   entry->label_used = 0;
   entry->exception_handler_label = gen_exception_label ();
+  entry->false_label = NULL_RTX;
 
   node->entry = entry;
   node->chain = stack->top;
@@ -1600,6 +1601,54 @@ start_catch_handler (rtime)
   receive_exception_label (handler_label);
 
   add_new_handler (eh_region_entry, get_new_handler (handler_label, rtime));
+
+  if (flag_new_exceptions && ! exceptions_via_longjmp)
+    return;
+
+  /* Under the old mechanism, as well as setjmp/longjmp, we need to
+     issue code to compare 'rtime' to the value in eh_info, via the
+     matching function in eh_info. If its is false, we branch around
+     the handler we are about to issue. */
+
+  if (rtime != NULL_TREE && rtime != CATCH_ALL_TYPE)
+    {
+      rtx call_rtx, rtime_address;
+
+      if (catchstack.top->entry->false_label != NULL_RTX)
+        error ("never issued previous false_label");
+      catchstack.top->entry->false_label = gen_exception_label ();
+
+      rtime_address = expand_expr (rtime, NULL_RTX, Pmode, EXPAND_INITIALIZER);
+      rtime_address = force_reg (Pmode, rtime_address);
+
+      /* Now issue the call, and branch around handler if needed */
+      call_rtx = emit_library_call_value (
+        gen_rtx_SYMBOL_REF (Pmode, "__eh_rtime_match"), NULL_RTX, 
+                                        0, SImode, 1, rtime_address, Pmode);
+
+      /* Did the function return true? */
+      emit_cmp_insn (call_rtx, const0_rtx, EQ, NULL_RTX,
+                                                GET_MODE (call_rtx), 0 ,0);
+      emit_jump_insn (gen_beq (catchstack.top->entry->false_label));
+    }
+}
+
+/* Called to end a catch clause. If we aren't using the new exception
+   model tabel mechanism, we need to issue the branch-around label
+   for the end of the catch block. */
+
+void 
+end_catch_handler ()
+{
+  if (! doing_eh (1) || (flag_new_exceptions && ! exceptions_via_longjmp))
+    return;
+  
+  /* A NULL label implies the catch clause was a catch all or cleanup */
+  if (catchstack.top->entry->false_label == NULL_RTX)
+    return;
+
+  emit_label (catchstack.top->entry->false_label);
+  catchstack.top->entry->false_label = NULL_RTX;
 }
 
 /* Generate RTL for the start of a group of catch clauses. 
@@ -1693,9 +1742,6 @@ expand_start_all_catch ()
       ehstack.top->entry->outer_context = outer_context;
     }
 
-  /* We also have to start the handler if we aren't using the new model. */
-  if (! flag_new_exceptions)
-    start_catch_handler (NULL);
 }
 
 /* Finish up the catch block.  At this point all the insns for the
@@ -1927,6 +1973,9 @@ output_exception_table_entry (file, n)
                                                 POINTER_SIZE / BITS_PER_UNIT);
         }
       putc ('\n', file);               /* blank line */
+      /* We only output the first label under the old scheme */
+      if (! flag_new_exceptions)
+        break;
     }
 }
 
index d20b606..5416e59 100644 (file)
@@ -53,6 +53,10 @@ struct label_node {
    label or not. New ones are needed for additional catch blocks if
    it has.
 
+   FALSE_LABEL is used when either setjmp/longjmp exceptions are in
+   use, or old style table exceptions. It contains the label for 
+   branching to the next runtime type check as handlers are processed.
+
    FINALIZATION is the tree codes for the handler, or is NULL_TREE if
    one hasn't been generated yet, or is integer_zero_node to mark the
    end of a group of try blocks.  */
@@ -62,6 +66,7 @@ struct eh_entry {
   rtx exception_handler_label;
   tree finalization;
   int label_used;
+  rtx false_label;
 };
 
 /* A list of EH_ENTRYs. ENTRY is the entry; CHAIN points to the next
@@ -237,6 +242,10 @@ extern void add_eh_table_entry                     PROTO((int n));
 extern void start_catch_handler                 PROTO((tree));
 #endif
 
+/* End an individual catch clause. */
+
+extern void end_catch_handler                   PROTO((void));
+
 /* Returns a non-zero value if we need to output an exception table.  */
 
 extern int exception_table_p                   PROTO((void));
index 7c26e6b..6f2fcfd 100644 (file)
@@ -3355,6 +3355,21 @@ __sjpopnthrow ()
 \f
 /* Support code for all exception region-based exception handling.  */
 
+int
+__eh_rtime_match (void *rtime)
+{
+  void *info;
+  __eh_matcher matcher;
+  void *ret;
+
+  info = *(__get_eh_info ());
+  matcher = ((__eh_info *)info)->match_function;
+  if (!matcher)
+    perror ("No runtime type matcher available");
+  ret = (*matcher) (info, rtime, (void *)0);
+  return ((int)ret);
+}
+
 /* This value identifies the place from which an exception is being
    thrown.  */