Have -fnew-exceptions actually use the runtime field, and not generate runtime checki...
authorAndrew MacLeod <amacleod@cygnus.com>
Tue, 23 Jun 1998 07:10:29 +0000 (07:10 +0000)
committerAndrew Macleod <amacleod@gcc.gnu.org>
Tue, 23 Jun 1998 07:10:29 +0000 (07:10 +0000)
Have -fnew-exceptions actually use the runtime field, and not generate
runtime checking code inside each handler.
THis works at low opt, but not with optimization at the moment.
Tue Jun 23 10:06:07 EDT 1998  Andrew MacLeod  (amacleod@cygnus.com)
* eh-common.h (struct __eh_info): Remove coerced value field.
* libgcc2.c (find_exception_handler): Don't set coerced_value field.
* except.c (get_dynamic_handler_chain, get_dynamic_cleanup_chain): Use
POINTER_SIZE instead of Pmode.
(expand_start_all_catch): Call start_catch_handler() if we are not
using new style exceptions.
1998-06-22  Andrew MacLeod  (amacleod@cygnus.com)
* parse.y (function_try_block): Don't call start_catch_handler.
* except.c (call_eh_info): Remove coerced field from declaration.
(build_eh_type_type_ref): New function to create an address of a
rtti function for the new style exception tables.
(expand_start_catch_block): Split function, this contains the
common part.
(process_start_catch_block_old): New function to perform the rest
of expand_start_catch_block under old style exceptions.
(process_start_catch_block_old): New function to perform the rest
of expand_start_catch_block under new style exceptions.
(expand_end_catch_block): Only pop the false label off the stack under
the old style of exceptions.
* semantics.c (finish_try_block): Don't call start_catch_handler.
* exception.cc (struct cp_eh_info): Add original_value field.
(__cplus_type_matcher): Perform type matching on the original exception
value, and if we have a match, set the current value.
(__cp_push_exception): Set the original expcetion value.

From-SVN: r20671

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/except.c
gcc/cp/exception.cc
gcc/cp/parse.y
gcc/cp/semantics.c
gcc/eh-common.h
gcc/except.c
gcc/libgcc2.c

index 69b80ca98b9f8a4a6ec19ea8d1e6a776655fa899..d4f3d456c6494407e8ab261d19526ddb0c290c60 100644 (file)
@@ -1,3 +1,12 @@
+Tue Jun 23 10:06:07 EDT 1998  Andrew MacLeod  (amacleod@cygnus.com)
+
+       * eh-common.h (struct __eh_info): Remove coerced value field.
+       * libgcc2.c (find_exception_handler): Don't set coerced_value field.
+       * except.c (get_dynamic_handler_chain, get_dynamic_cleanup_chain): Use 
+       POINTER_SIZE instead of Pmode.
+       (expand_start_all_catch): Call start_catch_handler() if we are not
+       using new style exceptions.
+
 Tue Jun 23 06:45:00 1998  Catherine Moore  <clm@cygnus.com>
 
         * varasm.c (assemble_variable): Remove reference to warn_bss_align.
index 27a81786e74a3bf597589a7abff4022981ea3fb3..ddd56db73370bf7ec08a881c12378dd5a1093985 100644 (file)
@@ -1,3 +1,23 @@
+1998-06-23  Andrew MacLeod  (amacleod@cygnus.com)
+
+       * parse.y (function_try_block): Don't call start_catch_handler.
+       * except.c (call_eh_info): Remove coerced field from declaration.
+       (build_eh_type_type_ref): New function to create an address of a
+       rtti function for the new style exception tables.
+       (expand_start_catch_block): Split function, this contains the
+       common part.
+       (process_start_catch_block_old): New function to perform the rest
+       of expand_start_catch_block under old style exceptions.
+       (process_start_catch_block_old): New function to perform the rest
+       of expand_start_catch_block under new style exceptions.
+       (expand_end_catch_block): Only pop the false label off the stack under
+       the old style of exceptions.
+       * semantics.c (finish_try_block): Don't call start_catch_handler.
+       * exception.cc (struct cp_eh_info): Add original_value field.
+       (__cplus_type_matcher): Perform type matching on the original exception
+       value, and if we have a match, set the current value.
+       (__cp_push_exception): Set the original expcetion value.
+
 1998-06-23  Jason Merrill  <jason@yorick.cygnus.com>
 
        * call.c (joust): Fix confusing conversion warning.
index dba0f0919c44d0a9fa0ce8fc022fac56c55fe8c1..438351ef8cd7848af762f860faa7344294833bb5 100644 (file)
@@ -56,6 +56,9 @@ static tree get_eh_type PROTO((void));
 static tree get_eh_caught PROTO((void));
 static tree get_eh_handlers PROTO((void));
 static tree do_pop_exception PROTO((void));
+static void process_start_catch_block PROTO((tree, tree));
+static void process_start_catch_block_old PROTO((tree, tree));
+static tree build_eh_type_type_ref PROTO((tree));
 
 #if 0
 /* This is the startup, and finish stuff per exception table.  */
@@ -273,14 +276,12 @@ call_eh_info ()
       fields[0] = build_lang_field_decl (FIELD_DECL, 
                     get_identifier ("match_function"), ptr_type_node);
       fields[1] = build_lang_field_decl (FIELD_DECL, 
-                    get_identifier ("coerced_value"), ptr_type_node);
-      fields[2] = build_lang_field_decl (FIELD_DECL, 
                     get_identifier ("language"), short_integer_type_node);
-      fields[3] = build_lang_field_decl (FIELD_DECL, 
+      fields[2] = build_lang_field_decl (FIELD_DECL, 
                     get_identifier ("version"), short_integer_type_node);
       /* N.B.: The fourth field LEN is expected to be
         the number of fields - 1, not the total number of fields.  */
-      finish_builtin_type (t1, "__eh_info", fields, 3, ptr_type_node);
+      finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
       t = make_lang_type (RECORD_TYPE);
       fields[0] = build_lang_field_decl (FIELD_DECL, 
                                               get_identifier ("eh_info"), t1);
@@ -414,6 +415,48 @@ build_eh_type_type (type)
   return build1 (ADDR_EXPR, ptr_type_node, exp);
 }
 
+/* Build the address of a runtime type for use in the runtime matching
+   field of the new exception model */
+
+static tree
+build_eh_type_type_ref (type)
+     tree type;
+{
+  char *typestring;
+  tree exp;
+  int susp;
+
+  if (type == error_mark_node)
+    return error_mark_node;
+
+  /* peel back references, so they match.  */
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    type = TREE_TYPE (type);
+
+  /* Peel off cv qualifiers.  */
+  type = TYPE_MAIN_VARIANT (type);
+
+  push_obstacks_nochange ();
+  end_temporary_allocation ();
+
+  if (flag_rtti)
+    {
+      exp = get_tinfo_fn (type);
+      TREE_USED (exp) = 1;
+      mark_inline_for_output (exp);
+      exp = build1 (ADDR_EXPR, ptr_type_node, exp);
+    }
+  else
+    {
+      typestring = build_overload_name (type, 1, 1);
+      exp = combine_strings (build_string (strlen (typestring)+1, typestring));
+      exp = build1 (ADDR_EXPR, ptr_type_node, exp);
+    }
+  pop_obstacks ();
+  return (exp);
+}
+
+
 /* Build a type value for use at runtime for a exp that is thrown or
    matched against by the exception handling system.  */
 
@@ -495,7 +538,7 @@ build_terminate_handler ()
   return term;
 }
 
-/* call this to start a catch block. Typename is the typename, and identifier
+/* Call this to start a catch block. Typename is the typename, and identifier
    is the variable to place the object in or NULL if the variable doesn't
    matter.  If typename is NULL, that means its a "catch (...)" or catch
    everything.  In that case we don't need to do any type checking.
@@ -505,9 +548,7 @@ void
 expand_start_catch_block (declspecs, declarator)
      tree declspecs, declarator;
 {
-  rtx false_label_rtx;
-  tree decl = NULL_TREE;
-  tree init;
+  tree decl;
 
   if (processing_template_decl)
     {
@@ -527,6 +568,25 @@ 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);
+}
+
+
+/* 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);
@@ -631,6 +691,111 @@ expand_start_catch_block (declspecs, declarator)
   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. */
+
+static void 
+process_start_catch_block (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);
+
+
+  if (declspecs)
+    {
+      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
+
+      if (decl == NULL_TREE)
+       error ("invalid catch parameter");
+    }
+
+  if (decl)
+    start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl)));
+  else
+    start_catch_handler (NULL_TREE);
+
+  emit_line_note (input_filename, lineno);
+
+  push_eh_info ();
+
+  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 = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+
+      push_eh_cleanup ();
+
+      /* Create a binding level for the parm.  */
+      pushlevel (0);
+      expand_start_bindings (0);
+
+      init = convert_from_reference (exp);
+
+      /* 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);
+
+      cp_finish_decl (decl, init, 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);
+}
+
 
 
 /* Call this to end a catch block.  Its responsible for emitting the
@@ -658,7 +823,8 @@ expand_end_catch_block ()
 
   /* label we emit to jump to if this catch block didn't match.  */
   /* This the closing } in the `if (eq) {' of the documentation.  */
-  emit_label (pop_label_entry (&false_label_stack));
+  if (! flag_new_exceptions)
+    emit_label (pop_label_entry (&false_label_stack));
 }
 
 /* An exception spec is implemented more or less like:
@@ -686,7 +852,6 @@ expand_end_eh_spec (raises)
   int count = 0;
 
   expand_start_all_catch ();
-  start_catch_handler (NULL);
   expand_start_catch_block (NULL_TREE, NULL_TREE);
 
   /* Build up an array of type_infos.  */
index b081fa7bcc0688542060e3b31f6bb2a11751cf5f..cad73046462b8793e4d4a8d239a35937c2c335b2 100644 (file)
@@ -93,6 +93,7 @@ struct cp_eh_info
   bool caught;
   cp_eh_info *next;
   long handlers;
+  void *original_value;
 };
 
 /* Language-specific EH info pointer, defined in libgcc2. */
@@ -162,7 +163,10 @@ __cplus_type_matcher (cp_eh_info *info, exception_table *matching_info,
   /* we don't worry about version info yet, there is only one version! */
   
   void *match_type = ((rtimetype) (matching_info->match_info)) ();
-  ret = __throw_type_match_rtti (match_type, info->type, info->value);
+  ret = __throw_type_match_rtti (match_type, info->type, info->original_value);
+  /* change value of exception */
+  if (ret)
+    info->value = ret;
   return ret;
 }
 
@@ -180,11 +184,11 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
   p->cleanup = cleanup;
   p->handlers = 0;
   p->caught = false;
+  p->original_value = value;
 
   p->eh_info.match_function = __cplus_type_matcher;
   p->eh_info.language = EH_LANG_C_plus_plus;
   p->eh_info.version = 1;
-  p->eh_info.coerced_value = NULL;
 
   cp_eh_info **q = __get_eh_info ();
 
index b3b408c2a22ec38fdd72bd15b15899a395f6a73f..ffc45e61c6ee886ffb1907e10694868001260e53 100644 (file)
@@ -3253,7 +3253,6 @@ function_try_block:
          ctor_initializer_opt compstmt
                { 
                   expand_start_all_catch (); 
-                  start_catch_handler (NULL);
                 }
          handler_seq
                {
index 60c4c3213c3a5178b0c5465361d2570f9e3fe2ce..763f208cf360af65a0d443411e44bfdcb7b20076 100644 (file)
@@ -589,7 +589,6 @@ finish_try_block (try_block)
   else
     {
       expand_start_all_catch ();  
-      start_catch_handler (NULL);
     }
 }
 
index c16d66a5008cbdf7be7dcf842e905c42d939c4d0..c8d98c09072fcaca810cf7dd66a90f28f7754eaa 100644 (file)
@@ -92,7 +92,6 @@ typedef void * (*__eh_matcher)          PROTO ((void *, void *, void *));
 typedef struct __eh_info 
 {
   __eh_matcher match_function;
-  void *coerced_value;
   short language;
   short version;
 } __eh_info;
index 63d6c82fc47ba8f930995c074025a14daa72a381..6ffa92038676a72c108c18793563c9b2bf0b1295 100644 (file)
@@ -1025,7 +1025,7 @@ get_dynamic_handler_chain ()
 
   /* This is the offset of dynamic_handler_chain in the eh_context struct
      declared in eh-common.h. If its location is change, change this offset */
-  dhc = plus_constant (ehc, GET_MODE_SIZE (Pmode));
+  dhc = plus_constant (ehc, POINTER_SIZE / BITS_PER_UNIT);
 
   result = copy_to_reg (dhc);
 
@@ -1045,7 +1045,7 @@ get_dynamic_cleanup_chain ()
   rtx dhc, dcc, result;
 
   dhc = get_dynamic_handler_chain ();
-  dcc = plus_constant (dhc, GET_MODE_SIZE (Pmode));
+  dcc = plus_constant (dhc, POINTER_SIZE / BITS_PER_UNIT);
 
   result = copy_to_reg (dcc);
 
@@ -1618,6 +1618,10 @@ expand_start_all_catch ()
       expand_eh_region_start ();
       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
index 1fc703e84d245c43c12f589baab126c322da3aaf..4e17faf491948370704d50ab5dbf9209600efe41 100644 (file)
@@ -3426,10 +3426,7 @@ find_exception_handler (void *pc, exception_descriptor *table, void *eh_info)
                     {
                       ret = (*matcher)(eh_info, &tab[pos], table);
                       if (ret)
-                        {
-                          ((__eh_info *)eh_info)->coerced_value = ret;
-                          return tab[pos].exception_handler;
-                        }
+                        return tab[pos].exception_handler;
                     }
                 }
               else