]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
flow.c (find_basic_blocks): Don't create a new basic block for calls in a LIBCALL...
authorJason Merrill <jason@gcc.gnu.org>
Wed, 11 Feb 1998 10:21:23 +0000 (05:21 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 11 Feb 1998 10:21:23 +0000 (05:21 -0500)
* flow.c (find_basic_blocks): Don't create a new basic block
for calls in a LIBCALL block.
* flow.c (flow_analysis): Be consistent with find_basic_blocks in
determining when a new basic block starts.
* flow.c (find_basic_blocks): A CALL_INSN that can throw starts
a new basic block.
(find_basic_blocks_1): Likewise.
* except.c (get_dynamic_handler_chain): Only make the call once per
  function.
* except.c (expand_fixup_region_end): New fn.
(expand_fixup_region_start): Likewise.
(expand_eh_region_start_tree): Store cleanup into finalization here.
* stmt.c (expand_cleanups): Use them to protect fixups.
* except.c (get_dynamic_handler_chain): Build up a FUNCTION_DECL.
* optabs.c (init_optabs): Lose get_dynamic_handler_chain_libfunc.
* expr.h: Likewise.
cp/:
* decl.c (copy_args_p): Handle copy elision for types with virtual
  bases.
   * call.c (build_over_call): Likewise.
* exception.cc (__cp_pop_exception): Lose handler arg.
* except.c (do_pop_exception): Likewise.
(push_eh_cleanup): Let the cleanup mechanism supply the handler.
(expand_end_catch_block): Likewise.

From-SVN: r17856

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl.c
gcc/cp/except.c
gcc/cp/exception.cc
gcc/except.c
gcc/expr.h
gcc/flow.c
gcc/optabs.c
gcc/stmt.c

index 1f8d2de1d254c91f8b10469ac3cf18de88e94311..b75d4fdff7393019b27d71402d1d01e89e8f62e4 100644 (file)
@@ -1,3 +1,37 @@
+Sun Dec 28 00:32:16 1997  Jeffrey A Law  (law@cygnus.com)
+
+       * flow.c (find_basic_blocks): Don't create a new basic block
+       for calls in a LIBCALL block.
+
+Fri Dec 12 01:19:48 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * flow.c (flow_analysis): Be consistent with find_basic_blocks in
+       determining when a new basic block starts.
+
+Thu Dec 11 22:02:10 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * flow.c (find_basic_blocks): A CALL_INSN that can throw starts
+       a new basic block.
+       (find_basic_blocks_1): Likewise.
+
+Thu Dec  4 11:51:00 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * except.c (get_dynamic_handler_chain): Only make the call once per
+       function.
+
+Wed Dec  3 12:01:56 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * except.c (expand_fixup_region_end): New fn.
+       (expand_fixup_region_start): Likewise.
+       (expand_eh_region_start_tree): Store cleanup into finalization here.
+       * stmt.c (expand_cleanups): Use them to protect fixups.
+
+Mon Nov 24 22:41:55 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * except.c (get_dynamic_handler_chain): Build up a FUNCTION_DECL.
+       * optabs.c (init_optabs): Lose get_dynamic_handler_chain_libfunc.
+       * expr.h: Likewise.
+
 Wed Feb 11 01:39:47 1998  Richard Henderson  <rth@cygnus.com>
 
        * stor-layout.c (layout_type): Do upper - lower in the native type,
index 87e72a1401e89b703c27d53ff352610400355d8c..e57e66bfc9d20af163071c3016da53763259e299 100644 (file)
@@ -1,3 +1,16 @@
+Mon Dec  8 23:17:13 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl.c (copy_args_p): Handle copy elision for types with virtual
+       bases.
+       * call.c (build_over_call): Likewise.
+
+Tue Dec  2 01:37:19 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * exception.cc (__cp_pop_exception): Lose handler arg.
+       * except.c (do_pop_exception): Likewise.
+       (push_eh_cleanup): Let the cleanup mechanism supply the handler.
+       (expand_end_catch_block): Likewise.
+
 Sun Feb  8 23:59:04 1998  scott snyder  <sss@d0linux01.fnal.gov>
 
        * method.c (make_thunk): Avoid name buffer overflow.
index 4e66a307e93485a713414735f75227cff5da58ea..dc983b3c2687c68e786517f466b038c6a88643e1 100644 (file)
@@ -5498,7 +5498,10 @@ build_over_call (fn, convs, args, flags)
       && copy_args_p (fn))
     {
       tree targ;
-      arg = TREE_VALUE (TREE_CHAIN (converted_args));
+      arg = TREE_CHAIN (converted_args);
+      if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+       arg = TREE_CHAIN (arg);
+      arg = TREE_VALUE (arg);
 
       /* Pull out the real argument, disregarding const-correctness.  */
       targ = arg;
index fad7cfa5e8aebea2f20f9507fd201169ead49c12..2d7e72cfa3dba034aee491aa0bc3d014c6a9457a 100644 (file)
@@ -10267,6 +10267,9 @@ copy_args_p (d)
      tree d;
 {
   tree t = FUNCTION_ARG_CHAIN (d);
+  if (DECL_CONSTRUCTOR_P (d)
+      && TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d)))
+    t = TREE_CHAIN (t);
   if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
       && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
          == DECL_CLASS_CONTEXT (d))
index 65eaf8ae52d434ccdc0b538b5e8ad2c4a5819164..341ded8388db71da7295c05b6b54ca6dcf187478 100644 (file)
@@ -474,8 +474,7 @@ build_eh_type (exp)
    if it is, it avoids destroying the object on rethrow.  */
 
 static tree
-do_pop_exception (handler)
-     tree handler;
+do_pop_exception ()
 {
   tree fn, cleanup;
   fn = get_identifier ("__cp_pop_exception");
@@ -490,9 +489,7 @@ do_pop_exception (handler)
       fn = build_lang_decl
        (FUNCTION_DECL, fn,
         build_function_type (void_type_node, tree_cons
-                             (NULL_TREE, ptr_type_node, tree_cons
-                              (NULL_TREE, boolean_type_node,
-                               void_list_node))));
+                             (NULL_TREE, ptr_type_node, void_list_node)));
       DECL_EXTERNAL (fn) = 1;
       TREE_PUBLIC (fn) = 1;
       DECL_ARTIFICIAL (fn) = 1;
@@ -505,8 +502,7 @@ do_pop_exception (handler)
   /* Arrange to do a dynamically scoped cleanup upon exit from this region.  */
   cleanup = lookup_name (get_identifier ("__exception_info"), 0);
   cleanup = build_function_call (fn, expr_tree_cons
-                                (NULL_TREE, cleanup, expr_tree_cons
-                                 (NULL_TREE, handler, NULL_TREE)));
+                                (NULL_TREE, cleanup, NULL_TREE));
   return cleanup;
 }
 
@@ -515,17 +511,15 @@ do_pop_exception (handler)
 static void
 push_eh_cleanup ()
 {
-  /* All cleanups must last longer than normal.  */
-  int yes = suspend_momentary ();
-  expand_decl_cleanup_no_eh (NULL_TREE, do_pop_exception (boolean_false_node));
-  resume_momentary (yes);
+  int yes;
 
   expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
               const0_rtx, VOIDmode, EXPAND_NORMAL);
 
-  /* We don't destroy the exception object on rethrow, so we can't use
-     the normal cleanup mechanism for it.  */
-  expand_eh_region_start ();
+  yes = suspend_momentary ();
+  /* All cleanups must last longer than normal.  */
+  expand_decl_cleanup (NULL_TREE, do_pop_exception ());
+  resume_momentary (yes);
 }
 
 /* call this to start a catch block. Typename is the typename, and identifier
@@ -695,9 +689,6 @@ expand_end_catch_block ()
   expand_end_bindings (getdecls (), kept_level_p (), 0);
   poplevel (kept_level_p (), 1, 0);
       
-  /* Matches push_eh_cleanup.  */
-  expand_eh_region_end (do_pop_exception (boolean_true_node));
-
   /* Cleanup the EH object.  */
   expand_end_bindings (getdecls (), kept_level_p (), 0);
   poplevel (kept_level_p (), 1, 0);
index caaf5892282665baba0157c543f5538a820a90c8..57423ac065884524c6c4b0ab6af07e747fcf1ec9 100644 (file)
@@ -125,17 +125,20 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
 
 /* Compiler hook to pop an exception that has been finalized.  Used by
    push_eh_cleanup().  P is the info for the exception caught by the
-   current catch block, and HANDLER determines if we've been called from
-   an exception handler; if so, we avoid destroying the object on rethrow.  */
+   current catch block.  */
 
 extern "C" void
-__cp_pop_exception (cp_eh_info *p, bool handler)
+__cp_pop_exception (cp_eh_info *p)
 {
   cp_eh_info **q = &__eh_info;
 
   --p->handlers;
 
-  if (p->handlers > 0 || (handler && p == *q))
+  /* Don't really pop if there are still active handlers for our exception,
+     or if our exception is being rethrown (i.e. if the active exception is
+     our exception and it is uncaught).  */
+  if (p->handlers != 0
+      || (p == *q && !p->caught))
     return;
 
   for (; *q; q = &((*q)->next))
index 3336471bd86dd04f13b664e5f53393b66ba781c8..1924b10f9c872cdfde117df6bdd75884606ec718 100644 (file)
@@ -729,38 +729,53 @@ add_partial_entry (handler)
    This routine is here to facilitate the porting of this code to
    systems with threads.  One can either replace the routine we emit a
    call for here in libgcc2.c, or one can modify this routine to work
-   with their thread system.  */
+   with their thread system.
+
+   Ideally, we really only want one per real function, not one
+   per inlined function.  */
 
 rtx
 get_dynamic_handler_chain ()
 {
-#if 0
-  /* Do this once we figure out how to get this to the front of the
-     function, and we really only want one per real function, not one
-     per inlined function.  */
-  if (current_function_dhc == 0)
+  static tree fn;
+  tree expr;
+  rtx insns;
+
+  if (current_function_dhc)
+    return current_function_dhc;
+
+  if (fn == NULL_TREE)
     {
-      rtx dhc, insns;
-      start_sequence ();
-
-      dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
-                                    NULL_RTX, 1,
-                                    Pmode, 0);
-      current_function_dhc = copy_to_reg (dhc);
-      insns = get_insns ();
-      end_sequence ();
-      emit_insns_before (insns, get_first_nonparm_insn ());
+      tree fntype;
+      fn = get_identifier ("__get_dynamic_handler_chain");
+      push_obstacks_nochange ();
+      end_temporary_allocation ();
+      fntype = build_pointer_type (build_pointer_type
+                                  (build_pointer_type (void_type_node)));
+      fntype = build_function_type (fntype, NULL_TREE);
+      fn = build_decl (FUNCTION_DECL, fn, fntype);
+      DECL_EXTERNAL (fn) = 1;
+      TREE_PUBLIC (fn) = 1;
+      DECL_ARTIFICIAL (fn) = 1;
+      TREE_READONLY (fn) = 1;
+      make_decl_rtl (fn, NULL_PTR, 1);
+      assemble_external (fn);
+      pop_obstacks ();
     }
-#else
-  rtx dhc;
-  dhc = emit_library_call_value (get_dynamic_handler_chain_libfunc,
-                                NULL_RTX, 1,
-                                Pmode, 0);
-  current_function_dhc = copy_to_reg (dhc);
-#endif
 
-  /* We don't want a copy of the dhc, but rather, the single dhc.  */
-  return gen_rtx (MEM, Pmode, current_function_dhc);
+  expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
+  expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
+               expr, NULL_TREE, NULL_TREE);
+  TREE_SIDE_EFFECTS (expr) = 1;
+  expr = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
+
+  start_sequence ();
+  current_function_dhc = expand_expr (expr, NULL_RTX, VOIDmode, 0);
+  insns = get_insns ();
+  end_sequence ();
+  emit_insns_before (insns, get_first_nonparm_insn ());
+
+  return current_function_dhc;
 }
 
 /* Get a reference to the dynamic cleanup chain.  It points to the
@@ -993,6 +1008,7 @@ expand_eh_region_start_tree (decl, cleanup)
     }
 
   expand_eh_region_start_for_decl (decl);
+  ehstack.top->entry->finalization = cleanup;
 
   return 0;
 }
@@ -1118,6 +1134,57 @@ expand_eh_region_end (handler)
     }
 }
 
+/* End the EH region for a goto fixup.  We only need them in the region-based
+   EH scheme.  */
+
+void
+expand_fixup_region_start ()
+{
+  if (! doing_eh (0) || exceptions_via_longjmp)
+    return;
+
+  expand_eh_region_start ();
+}
+
+/* End the EH region for a goto fixup.  CLEANUP is the cleanup we just
+   expanded; to avoid running it twice if it throws, we look through the
+   ehqueue for a matching region and rethrow from its outer_context.  */
+
+void
+expand_fixup_region_end (cleanup)
+     tree cleanup;
+{
+  tree t;
+  struct eh_node *node;
+  int yes;
+
+  if (! doing_eh (0) || exceptions_via_longjmp)
+    return;
+
+  for (node = ehstack.top; node && node->entry->finalization != cleanup; )
+    node = node->chain;
+  if (node == 0)
+    for (node = ehqueue.head; node && node->entry->finalization != cleanup; )
+      node = node->chain;
+  if (node == 0)
+    abort ();
+
+  yes = suspend_momentary ();
+
+  t = build (RTL_EXPR, void_type_node, NULL_RTX, const0_rtx);
+  TREE_SIDE_EFFECTS (t) = 1;
+  do_pending_stack_adjust ();
+  start_sequence_for_rtl_expr (t);
+  expand_internal_throw (node->entry->outer_context);
+  do_pending_stack_adjust ();
+  RTL_EXPR_SEQUENCE (t) = get_insns ();
+  end_sequence ();
+
+  resume_momentary (yes);
+
+  expand_eh_region_end (t);
+}
+
 /* If we are using the setjmp/longjmp EH codegen method, we emit a
    call to __sjthrow.
 
index fa7b7edd81c6e29e7e3f2ac38ad1098fbe8e440f..cd4cef0919fee05a376fb4ac33b835653cb6d50b 100644 (file)
@@ -416,7 +416,6 @@ extern rtx sjpopnthrow_libfunc;
 extern rtx terminate_libfunc;
 extern rtx setjmp_libfunc;
 extern rtx longjmp_libfunc;
-extern rtx get_dynamic_handler_chain_libfunc;
 
 extern rtx eqhf2_libfunc;
 extern rtx nehf2_libfunc;
index 66374163e8bfc6ea9eca07976b4e3e284ee20bf2..986d74aa90e2318f6d54781ee9932dc381516b7e 100644 (file)
@@ -282,6 +282,7 @@ flow_analysis (f, nregs, file)
   register rtx insn;
   register int i;
   rtx nonlocal_label_list = nonlocal_label_rtx_list ();
+  int in_libcall_block = 0;
 
 #ifdef ELIMINABLE_REGS
   static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
@@ -304,11 +305,18 @@ flow_analysis (f, nregs, file)
   {
     register RTX_CODE prev_code = JUMP_INSN;
     register RTX_CODE code;
+    int eh_region = 0;
 
     max_uid_for_flow = 0;
 
     for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
       {
+
+       /* Track when we are inside in LIBCALL block.  */
+       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+           && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+         in_libcall_block = 1;
+
        code = GET_CODE (insn);
        if (INSN_UID (insn) > max_uid_for_flow)
          max_uid_for_flow = INSN_UID (insn);
@@ -316,7 +324,8 @@ flow_analysis (f, nregs, file)
            || (GET_RTX_CLASS (code) == 'i'
                && (prev_code == JUMP_INSN
                    || (prev_code == CALL_INSN
-                       && nonlocal_label_list != 0)
+                       && (nonlocal_label_list != 0 || eh_region)
+                       && ! in_libcall_block)
                    || prev_code == BARRIER)))
          i++;
 
@@ -325,6 +334,14 @@ flow_analysis (f, nregs, file)
 
        if (code != NOTE)
          prev_code = code;
+       else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+         ++eh_region;
+       else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
+         --eh_region;
+
+       if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+           && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+         in_libcall_block = 0;
       }
   }
 
@@ -381,6 +398,7 @@ find_basic_blocks (f, nonlocal_label_list)
   rtx x, note, eh_note;
   enum rtx_code prev_code, code;
   int depth, pass;
+  int in_libcall_block = 0;
 
   pass = 1;
   active_eh_handler = (rtx *) alloca ((max_uid_for_flow + 1) * sizeof (rtx));
@@ -404,6 +422,12 @@ find_basic_blocks (f, nonlocal_label_list)
   for (eh_note = NULL_RTX, insn = f, i = -1, prev_code = JUMP_INSN, depth = 1;
        insn; insn = NEXT_INSN (insn))
     {
+
+      /* Track when we are inside in LIBCALL block.  */
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+         && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+       in_libcall_block = 1;
+
       code = GET_CODE (insn);
       if (code == NOTE)
        {
@@ -418,8 +442,8 @@ find_basic_blocks (f, nonlocal_label_list)
               || (GET_RTX_CLASS (code) == 'i'
                   && (prev_code == JUMP_INSN
                       || (prev_code == CALL_INSN
-                          && nonlocal_label_list != 0
-                          && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))
+                          && (nonlocal_label_list != 0 || eh_note)
+                          && ! in_libcall_block)
                       || prev_code == BARRIER)))
        {
          basic_block_head[++i] = insn;
@@ -482,13 +506,17 @@ find_basic_blocks (f, nonlocal_label_list)
               && (asynchronous_exceptions
                   || code == CODE_LABEL
                   || (GET_CODE (insn) == CALL_INSN
-                      && ! find_reg_note (insn, REG_RETVAL, NULL_RTX))))
+                      && ! in_libcall_block)))
        active_eh_handler[INSN_UID (insn)] = XEXP (eh_note, 0);
 
       BLOCK_NUM (insn) = i;
 
       if (code != NOTE)
        prev_code = code;
+
+      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+         && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+       in_libcall_block = 0;
     }
 
   /* During the second pass, `n_basic_blocks' is only an upper bound.
index a5f2e7ed064311f71f45fec0ee4d6f0aa095bebd..746713553455ced7d4d64125cd6a1e7669d2c3ac 100644 (file)
@@ -124,7 +124,6 @@ rtx sjpopnthrow_libfunc;
 rtx terminate_libfunc;
 rtx setjmp_libfunc;
 rtx longjmp_libfunc;
-rtx get_dynamic_handler_chain_libfunc;
 
 rtx eqhf2_libfunc;
 rtx nehf2_libfunc;
@@ -4289,7 +4288,6 @@ init_optabs ()
   setjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "setjmp");
   longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "longjmp");
 #endif
-  get_dynamic_handler_chain_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__get_dynamic_handler_chain");
 
   eqhf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__eqhf2");
   nehf2_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__nehf2");
index 573a3f19c3d6ca8c2ceb8691e365d9640eaafecd..65e376028d245065f35627d50c04569bb3d3a107 100644 (file)
@@ -4229,7 +4229,14 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
                   the target.  Though the cleanups are expanded multiple
                   times, the control paths are non-overlapping so the
                   cleanups will not be executed twice.  */
+
+               /* We may need to protect fixups with rethrow regions.  */
+               int protect = (in_fixup && ! TREE_ADDRESSABLE (tail));
+               if (protect)
+                 expand_fixup_region_start ();
                expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0);
+               if (protect)
+                 expand_fixup_region_end (TREE_VALUE (tail));
                free_temp_slots ();
              }
          }