a partial merge.
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Jul 1994 04:33:01 +0000 (04:33 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 7 Jul 1994 04:33:01 +0000 (04:33 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7668 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/cp/except.c
gcc/cp/gxxint.texi
gcc/cp/parse.y

index 78aef9f..d0f869c 100644 (file)
@@ -1,3 +1,24 @@
+Wed Jul  6 20:25:48 1994  Mike Stump  (mrs@cygnus.com)
+
+       * except.c (init_exception_processing): Setup interim_eh_hook to
+       call lang_interim_eh. 
+       * except.c (do_unwind): Propagate throw object value across
+       stack unwinding.
+       * except.c (saved_throw_value): Used to hold the value of the object
+       being thrown.  It is always a reference to the real value.
+       * except.c (expand_start_catch_block): Add handling for the
+       value of the exception object.
+       * except.c (expand_start_catch_block): Add handler for the handler,
+       so that throws inside the handler go to the outer block.
+       * except.c (expand_end_catch_block): Ditto.
+       * parse.y (handler_args): Use parm instead, as the other doesn't yet
+       handle references correctly.
+
+Wed Jul  6 17:55:32 1994  Per Bothner  (bothner@kalessin.cygnus.com)
+
+       * decl2.c (mark_vtable_entries):  If -ftable-thunks, set the
+       vtable entry properly to abort.
+
 Fri Jul  1 09:35:51 1994  Jason Merrill  (jason@deneb.cygnus.com)
 
        * parse.y (init): ANSI C++ does not forbid { }.
index d04cf51..80bb62a 100644 (file)
@@ -2322,6 +2322,8 @@ mark_vtable_entries (decl)
       if (DECL_ABSTRACT_VIRTUAL_P (fn))
        {
          extern tree abort_fndecl;
+         if (flag_vtable_thunks)
+           fnaddr = TREE_VALUE (entries);
          TREE_OPERAND (fnaddr, 0) = abort_fndecl;
        }
     }
index 160a10b..dc91b9d 100644 (file)
@@ -31,6 +31,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "obstack.h"
 #include "expr.h"
 
+extern void (*interim_eh_hook) PROTO((tree));
+
 /* holds the fndecl for __builtin_return_address () */
 tree builtin_return_address_fndecl;
 
@@ -231,8 +233,10 @@ do_unwind (throw_label)
   emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
                                                         Pmode,
                                                         throw_label), -8));
+  /* We use three values, PC, type, and value */
   easy_expand_asm ("st %l0,[%fp]");
   easy_expand_asm ("st %l1,[%fp+4]");
+  easy_expand_asm ("st %l2,[%fp+8]");
   easy_expand_asm ("ret");
   easy_expand_asm ("restore");
   emit_barrier ();
@@ -488,10 +492,12 @@ struct exceptStack {
 
    ========================================================================= */
 
-/* holds the pc for doing "throw" */
+/* Holds the pc for doing "throw" */
 rtx saved_pc;
-/* holds the type of the thing being thrown. */
+/* Holds the type of the thing being thrown. */
 rtx saved_throw_type;
+/* Holds the value being thrown.  */
+rtx saved_throw_value;
 
 rtx throw_label;
 
@@ -749,6 +755,15 @@ new_except_stack (stack)
 }
 /* ========================================================================= */
 
+void
+lang_interim_eh (finalization)
+     tree finalization;
+{
+  if (finalization)
+    end_protect (finalization);
+  else
+    start_protect ();
+}
 
 /* sets up all the global eh stuff that needs to be initialized at the
    start of compilation.
@@ -772,6 +787,8 @@ init_exception_processing ()
   tree unwind_fndecl;
   tree temp, PFV;
 
+  interim_eh_hook = lang_interim_eh;
+
   /* void (*)() */
   PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
 
@@ -844,6 +861,7 @@ init_exception_processing ()
   throw_label = gen_label_rtx ();
   saved_pc = gen_rtx (REG, Pmode, 16);
   saved_throw_type = gen_rtx (REG, Pmode, 17);
+  saved_throw_value = gen_rtx (REG, Pmode, 18);
 
   new_eh_queue (&ehqueue);
   new_eh_queue (&eh_table_output_queue);
@@ -949,13 +967,17 @@ expand_start_all_catch ()
   label = gen_label_rtx ();
   /* The label for the exception handling block we will save.  */
   emit_label (label);
+  
   push_label_entry (&caught_return_label_stack, label);
 
   /* Remember where we started. */
   push_last_insn ();
 
+  emit_insn (gen_nop ());
+
   /* Will this help us not stomp on it? */
   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
 
   while (1)
     {
@@ -989,7 +1011,6 @@ expand_start_all_catch ()
   pop_rtl_from_perm ();
   emit_label (entry->end_label);
 
-
   enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
 
   /* After running the finalization, continue on out to the next
@@ -997,6 +1018,7 @@ expand_start_all_catch ()
   emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry->end_label));
   /* Will this help us not stomp on it? */
   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
   emit_jump (throw_label);
   emit_label (entry->exception_handler_label);
   expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
@@ -1029,7 +1051,7 @@ expand_end_all_catch ()
 
   push_except_stmts (&exceptstack, catchstart, catchend);
   
-  /* Here was fall through into the continuation code.  */
+  /* Here we fall through into the continuation code.  */
 }
 
 
@@ -1046,6 +1068,7 @@ expand_leftover_cleanups ()
 
   /* Will this help us not stomp on it? */
   emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
 
   while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
     {
@@ -1082,6 +1105,7 @@ expand_leftover_cleanups ()
       emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry.end_label));
       /* Will this help us not stomp on it? */
       emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+      emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
       emit_jump (throw_label);
       emit_label (entry.exception_handler_label);
       expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
@@ -1099,16 +1123,40 @@ expand_start_catch_block (declspecs, declarator)
      tree declspecs, declarator;
 {
   rtx false_label_rtx;
+  rtx protect_label_rtx;
   tree type;
   tree decl;
+  tree init;
 
   if (! doing_eh (1))
     return;
 
+  /* Create a binding level for the parm.  */
+  expand_start_bindings (0);
+
   if (declspecs)
     {
-      decl = grokdeclarator (declarator, declspecs, PARM, 0, NULL_TREE);
+      tree init_type;
+      decl = grokdeclarator (declarator, declspecs, NORMAL, 1, NULL_TREE);
+
+      /* Figure out the type that the initializer is. */
+      init_type = TREE_TYPE (decl);
+      if (TREE_CODE (init_type) != REFERENCE_TYPE)
+       init_type = build_reference_type (init_type);
+
+      init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value)));
+      
+      /* Do we need the below two lines? */
+      /* Let `finish_decl' know that this initializer is ok.  */
+      DECL_INITIAL (decl) = init;
+      /* This needs to be preallocated under the try block,
+        in a union of all catch variables. */
+      pushdecl (decl);
       type = TREE_TYPE (decl);
+
+      /* peel back references, so they match. */
+      if (TREE_CODE (type) == REFERENCE_TYPE)
+       type = TREE_TYPE (type);
     }
   else
     type = NULL_TREE;
@@ -1116,6 +1164,12 @@ expand_start_catch_block (declspecs, declarator)
   false_label_rtx = gen_label_rtx ();
   push_label_entry (&false_label_stack, false_label_rtx);
 
+  /* This is saved for the exception table.  */
+  push_rtl_perm ();
+  protect_label_rtx = gen_label_rtx ();
+  pop_rtl_from_perm ();
+  push_label_entry (&false_label_stack, protect_label_rtx);
+
   if (type)
     {
       tree params;
@@ -1143,11 +1197,16 @@ expand_start_catch_block (declspecs, declarator)
 
       /* if it returned FALSE, jump over the catch block, else fall into it */
       emit_jump_insn (gen_bne (false_label_rtx));
+      finish_decl (decl, init, NULL_TREE, 0);
     }
   else
     {
       /* Fall into the catch all section. */
     }
+
+  /* This is the starting of something to protect.  */
+  emit_label (protect_label_rtx);
+
   emit_line_note (input_filename, lineno);
 }
 
@@ -1159,11 +1218,45 @@ void expand_end_catch_block ()
 {
   if (doing_eh (1))
     {
+      rtx start_protect_label_rtx;
+      rtx end_protect_label_rtx;
+      tree decls;
+      struct ehEntry entry;
+
       /* label we jump to if we caught the exception */
       emit_jump (top_label_entry (&caught_return_label_stack));
 
+      /* Code to throw out to outer context, if we get an throw from within
+        our catch handler. */
+      /* These are saved for the exception table.  */
+      push_rtl_perm ();
+      entry.exception_handler_label = gen_label_rtx ();
+      pop_rtl_from_perm ();
+      emit_label (entry.exception_handler_label);
+      emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
+                                        Pmode,
+                                        top_label_entry (&caught_return_label_stack)));
+      emit_jump (throw_label);
+      /* No associated finalization.  */
+      entry.finalization = NULL_TREE;
+
+      /* Because we are reordered out of line, we have to protect this. */
+      /* label for the start of the protection region.  */
+      start_protect_label_rtx = pop_label_entry (&false_label_stack);
+
+      /* Cleanup the EH paramater.  */
+      expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
+      
       /* label we emit to jump to if this catch block didn't match. */
-      emit_label (pop_label_entry (&false_label_stack));
+      emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack));
+
+      /* Because we are reordered out of line, we have to protect this. */
+      entry.start_label = start_protect_label_rtx;
+      entry.end_label = end_protect_label_rtx;
+
+      /* These set up a call to throw the caught exception into the outer
+       context.  */
+      enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
     }
 }
 
@@ -1300,34 +1393,45 @@ void
 expand_throw (exp)
      tree exp;
 {
-  tree raiseid = NULL_TREE;
-  rtx temp_size;
   rtx label;
   tree type;
 
   if (! doing_eh (1))
     return;
 
+  /* This is the label that represents where in the code we were, when
+     we got an exception.  This needs to be updated when we rethrow an
+     exception, so that the matching routine knows to search out.  */
   label = gen_label_rtx ();
   emit_label (label);
   emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
 
   if (exp)
     {
-      /* throw variable */
+      /* throw expression */
       /* First, decay it. */
       exp = default_conversion (exp);
       type = TREE_TYPE (exp);
+
+      {
+       char *typestring = build_overload_name (type, 1, 1);
+       tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
+       rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
+       rtx throw_value_rtx;
+
+       emit_move_insn (saved_throw_type, throw_type_rtx);
+       exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, NULL_TREE);
+       if (exp == error_mark_node)
+         error ("  in thrown expression");
+       throw_value_rtx = expand_expr (build_unary_op (ADDR_EXPR, exp, 0), NULL_RTX, VOIDmode, 0);
+       emit_move_insn (saved_throw_value, throw_value_rtx);
+      }
     }
   else
-    type = void_type_node;
-
-  {
-    char *typestring = build_overload_name (type, 1, 1);
-    tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
-    rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
-    emit_move_insn (saved_throw_type, throw_type_rtx);
-  }
+    {
+      /* rethrow current exception */
+      /* This part is easy, as we dont' have to do anything else.  */
+    }
 
   emit_jump (throw_label);
 }
index 426417a..00ff72e 100644 (file)
@@ -1133,6 +1133,8 @@ This issue is currently under discussion in the core reflector
 @node  Exception Handling, Free Store, Copying Objects, Top
 @section Exception Handling
 
+Note, exception handling in g++ is still under development.  
+
 This section describes the mapping of C++ exceptions in the C++
 front-end, into the back-end exception handling framework.
 
@@ -1150,7 +1152,9 @@ building functions names.  Int's are "i", const char * is PCc, etc...
 
 Unfortunately, the standard allows standard type conversions on throw
 parameters so they can match catch handlers.  This means we need a
-mechanism to handle type conversion at run time, ICK.
+mechanism to handle type conversion at run time, ICK.  I read this part
+again, and it appears that we only have to be able to do a few of the
+conversions at run time, so we should be ok.
 
 In C++, all cleanups should be protected by exception regions.  The
 region starts just after the reason why the cleanup is created has
@@ -1177,6 +1181,52 @@ hit before the section finishes normally, they examine the list for
 actions to perform.  I hope they add this logic into the back-end, as it
 would be nice to get that alternative approach in C++.
 
+On an rs6000, xlC stores exception objects on that stack, under the try
+block.  When is unwinds down into a handler, the frame pointer is
+adjusted back to the normal value for the frame in which the handler
+resides, and the stack pointer is left unchanged from the time at which
+the object was throwed.  This is so that there is always someplace for
+the exception object, and nothing can overwrite it, once we start
+throwing.  The only bad part, is that the stack remains large.
+
+Flaws in g++'s exception handling.  The stack pointer is restored from
+stack, we want to match rs6000, and propagate the stack pointer from
+time of throw, down, to the catch place.
+
+Only exact type matching of throw types works (references work also),
+catch variables cannot be used.  Only works on a Sun sparc running SunOS
+4.1.x.  Unwinding to outer catch clauses works.  All temps and local
+variables are cleaned up in all unwinded scopes.  Completed parts of
+partially constructed objects are not cleaned up.  Don't expect
+exception handling to work right if you optimize, in fact the compiler
+will probably core dump.  You can only have one source file worth of
+exception handling code.  If two EH regions are the exact same size, the
+backend cannot tell which one is first.  It punts by picking the last
+one, if they tie.  This is usually right.  We really should stick in a
+nop, if they are the same size.
+
+If we fall off the end of a series of catch blocks, we return to the
+flow of control in a normal fasion.  But this is wrong, we should
+rethrow.
+
+When we invoke the copy constructor for an exception object because it
+is passed by value, and if we take a hit (exception) inside the copy
+constructor someplace, where do we go?  I have tentatively choosen to
+not catch throws by the outer block at the same unwind level, if one
+exists, but rather to allow the frame to unwind into the next series of
+handlers, if any.  If this is the wrong way to do it, we will need to
+protect the rest of the handler in some fashion.  Maybe just changing
+the handler's handler to protect the whole series of handlers is the
+right way to go.
+
+The EH object is copied like it should be, if it is passed by value,
+otherwise we get a reference directly to it.
+
+EH objects make it through unwinding, but are subject to being
+overwritten as they are still past the top of stack.
+
+Exceptions in catch handlers now go to outer block.
+
 @node Free Store, Concept Index, Exception Handling, Top
 @section Free Store
 
index 44ea9ea..d30e511 100644 (file)
@@ -3369,6 +3369,7 @@ type_specifier_seq:
 handler_args:
          '(' ELLIPSIS ')'
                { expand_start_catch_block (NULL_TREE, NULL_TREE); }
+       /* This doesn't allow reference parameters, the below does.
        | '(' type_specifier_seq absdcl ')'
                { expand_start_catch_block ($2, $3); }
        | '(' type_specifier_seq ')'
@@ -3377,6 +3378,10 @@ handler_args:
                { expand_start_catch_block ($2, $3); }
        | '(' typed_typespecs after_type_declarator ')'
                { expand_start_catch_block ($2, $3); }
+       */
+       | '(' parm ')'
+               { expand_start_catch_block (TREE_PURPOSE ($2),
+                                           TREE_VALUE ($2)); }
        ;
 
 label_colon: