OSDN Git Service

PR target/45844
[pf3gnuchains/gcc-fork.git] / gcc / except.c
index 0df1996..251a550 100644 (file)
@@ -209,7 +209,7 @@ init_eh (void)
 
   /* Create the SjLj_Function_Context structure.  This should match
      the definition in unwind-sjlj.c.  */
-  if (USING_SJLJ_EXCEPTIONS)
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
     {
       tree f_jbuf, f_per, f_lsda, f_prev, f_cs, f_data, tmp;
 
@@ -681,7 +681,7 @@ lookup_type_for_runtime (tree type)
 \f
 /* Represent an entry in @TTypes for either catch actions
    or exception filter actions.  */
-struct GTY(()) ttypes_filter {
+struct ttypes_filter {
   tree t;
   int filter;
 };
@@ -998,8 +998,6 @@ sjlj_assign_call_site_values (void)
 
        /* First: build the action table.  */
        action = collect_one_action_chain (ar_hash, lp->region);
-       if (action != -1)
-         crtl->uses_eh_lsda = 1;
 
        /* Next: assign call-site values.  If dwarf2 terms, this would be
           the region number assigned by convert_to_eh_region_ranges, but
@@ -1065,6 +1063,9 @@ sjlj_mark_call_sites (void)
          this_call_site = 0;
        }
 
+      if (this_call_site != -1)
+       crtl->uses_eh_lsda = 1;
+
       if (this_call_site == last_call_site)
        continue;
 
@@ -1119,27 +1120,30 @@ sjlj_emit_function_enter (rtx dispatch_label)
   else
     emit_move_insn (mem, const0_rtx);
 
+  if (dispatch_label)
+    {
 #ifdef DONT_USE_BUILTIN_SETJMP
-  {
-    rtx x, last;
-    x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
-                                TYPE_MODE (integer_type_node), 1,
-                                plus_constant (XEXP (fc, 0),
-                                               sjlj_fc_jbuf_ofs), Pmode);
-
-    emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
-                            TYPE_MODE (integer_type_node), 0, dispatch_label);
-    last = get_last_insn ();
-    if (JUMP_P (last) && any_condjump_p (last))
-      {
-        gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
-        add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
-      }
-  }
-#else
-  expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), sjlj_fc_jbuf_ofs),
+      rtx x, last;
+      x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_RETURNS_TWICE,
+                                  TYPE_MODE (integer_type_node), 1,
+                                  plus_constant (XEXP (fc, 0),
+                                                 sjlj_fc_jbuf_ofs), Pmode);
+
+      emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
+                              TYPE_MODE (integer_type_node), 0,
                               dispatch_label);
+      last = get_last_insn ();
+      if (JUMP_P (last) && any_condjump_p (last))
+       {
+         gcc_assert (!find_reg_note (last, REG_BR_PROB, 0));
+         add_reg_note (last, REG_BR_PROB, GEN_INT (REG_BR_PROB_BASE / 100));
+       }
+#else
+      expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0),
+                                                 sjlj_fc_jbuf_ofs),
+                                  dispatch_label);
 #endif
+    }
 
   emit_library_call (unwind_sjlj_register_libfunc, LCT_NORMAL, VOIDmode,
                     1, XEXP (fc, 0), Pmode);
@@ -1363,6 +1367,23 @@ sjlj_build_landing_pads (void)
       sjlj_emit_function_exit ();
     }
 
+  /* If we do not have any landing pads, we may still need to register a
+     personality routine and (empty) LSDA to handle must-not-throw regions.  */
+  else if (function_needs_eh_personality (cfun) != eh_personality_none)
+    {
+      int align = STACK_SLOT_ALIGNMENT (sjlj_fc_type_node,
+                                       TYPE_MODE (sjlj_fc_type_node),
+                                       TYPE_ALIGN (sjlj_fc_type_node));
+      crtl->eh.sjlj_fc
+       = assign_stack_local (TYPE_MODE (sjlj_fc_type_node),
+                             int_size_in_bytes (sjlj_fc_type_node),
+                             align);
+
+      sjlj_mark_call_sites ();
+      sjlj_emit_function_enter (NULL_RTX);
+      sjlj_emit_function_exit ();
+    }
+
   VEC_free (int, heap, sjlj_lp_call_site_index);
 }
 
@@ -1375,13 +1396,13 @@ finish_eh_generation (void)
   basic_block bb;
 
   /* Construct the landing pads.  */
-  if (USING_SJLJ_EXCEPTIONS)
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
     sjlj_build_landing_pads ();
   else
     dw2_build_landing_pads ();
   break_superblocks ();
 
-  if (USING_SJLJ_EXCEPTIONS
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ
       /* Kludge for Alpha/Tru64 (see alpha_gp_save_rtx).  */
       || single_succ_edge (ENTRY_BLOCK_PTR)->insns.r)
     commit_edge_insertions ();
@@ -2421,30 +2442,33 @@ convert_to_eh_region_ranges (void)
        if (last_action != this_action
            || last_landing_pad != this_landing_pad)
          {
+           /* If there is a queued no-action region in the other section
+              with hot/cold partitioning, emit it now.  */
+           if (first_no_action_insn_before_switch)
+             {
+               gcc_assert (this_action != -1
+                           && last_action == (first_no_action_insn
+                                              ? -1 : -3));
+               call_site = add_call_site (NULL_RTX, 0, 0);
+               note = emit_note_before (NOTE_INSN_EH_REGION_BEG,
+                                        first_no_action_insn_before_switch);
+               NOTE_EH_HANDLER (note) = call_site;
+               note = emit_note_after (NOTE_INSN_EH_REGION_END,
+                                       last_no_action_insn_before_switch);
+               NOTE_EH_HANDLER (note) = call_site;
+               gcc_assert (last_action != -3
+                           || (last_action_insn
+                               == last_no_action_insn_before_switch));
+               first_no_action_insn_before_switch = NULL_RTX;
+               last_no_action_insn_before_switch = NULL_RTX;
+               call_site_base++;
+             }
            /* If we'd not seen a previous action (-3) or the previous
               action was must-not-throw (-2), then we do not need an
               end note.  */
            if (last_action >= -1)
              {
                /* If we delayed the creation of the begin, do it now.  */
-               if (first_no_action_insn_before_switch)
-                 {
-                   call_site = add_call_site (NULL_RTX, 0, 0);
-                   note
-                     = emit_note_before (NOTE_INSN_EH_REGION_BEG,
-                                         first_no_action_insn_before_switch);
-                   NOTE_EH_HANDLER (note) = call_site;
-                   if (first_no_action_insn)
-                     {
-                       note
-                         = emit_note_after (NOTE_INSN_EH_REGION_END,
-                                            last_no_action_insn_before_switch);
-                       NOTE_EH_HANDLER (note) = call_site;
-                     }
-                   else
-                     gcc_assert (last_action_insn
-                                 == last_no_action_insn_before_switch);
-                 }
                if (first_no_action_insn)
                  {
                    call_site = add_call_site (NULL_RTX, 0, cur_sec);
@@ -2620,7 +2644,11 @@ static bool
 gate_convert_to_eh_region_ranges (void)
 {
   /* Nothing to do for SJLJ exceptions or if no regions created.  */
-  return !(USING_SJLJ_EXCEPTIONS || cfun->eh->region_tree == NULL);
+  if (cfun->eh->region_tree == NULL)
+    return false;
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
+    return false;
+  return true;
 }
 
 struct rtl_opt_pass pass_convert_to_eh_region_ranges =
@@ -2794,7 +2822,6 @@ sjlj_output_call_site_table (void)
   call_site_base += n;
 }
 
-#ifndef TARGET_UNWIND_INFO
 /* Switch to the section that should be used for exception tables.  */
 
 static void
@@ -2844,7 +2871,6 @@ switch_to_exception_section (const char * ARG_UNUSED (fnname))
 
   switch_to_section (s);
 }
-#endif
 
 
 /* Output a reference from an exception table to the type_info object TYPE.
@@ -2904,8 +2930,7 @@ output_ttype (tree type, int tt_format, int tt_format_size)
 }
 
 static void
-output_one_function_exception_table (const char * ARG_UNUSED (fnname),
-                                    int section, rtx ARG_UNUSED (personality))
+output_one_function_exception_table (int section)
 {
   int tt_format, cs_format, lp_format, i;
 #ifdef HAVE_AS_LEB128
@@ -2918,20 +2943,6 @@ output_one_function_exception_table (const char * ARG_UNUSED (fnname),
   int have_tt_data;
   int tt_format_size = 0;
 
-#ifdef TARGET_UNWIND_INFO
-  /* TODO: Move this into target file.  */
-  fputs ("\t.personality\t", asm_out_file);
-  output_addr_const (asm_out_file, personality);
-  fputs ("\n\t.handlerdata\n", asm_out_file);
-  /* Note that varasm still thinks we're in the function's code section.
-     The ".endp" directive that will immediately follow will take us back.  */
-#else
-  switch_to_exception_section (fnname);
-#endif
-
-  /* If the target wants a label to begin the table, emit it here.  */
-  targetm.asm_out.emit_except_table_label (asm_out_file);
-
   have_tt_data = (VEC_length (tree, cfun->eh->ttype_data)
                  || (targetm.arm_eabi_unwinder
                      ? VEC_length (tree, cfun->eh->ehspec_data.arm_eabi)
@@ -2974,7 +2985,7 @@ output_one_function_exception_table (const char * ARG_UNUSED (fnname),
                       eh_data_format_name (tt_format));
 
 #ifndef HAVE_AS_LEB128
-  if (USING_SJLJ_EXCEPTIONS)
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
     call_site_len = sjlj_size_of_call_site_table ();
   else
     call_site_len = dw2_size_of_call_site_table (section);
@@ -3041,14 +3052,14 @@ output_one_function_exception_table (const char * ARG_UNUSED (fnname),
   dw2_asm_output_delta_uleb128 (cs_end_label, cs_after_size_label,
                                "Call-site table length");
   ASM_OUTPUT_LABEL (asm_out_file, cs_after_size_label);
-  if (USING_SJLJ_EXCEPTIONS)
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
     sjlj_output_call_site_table ();
   else
     dw2_output_call_site_table (cs_format, section);
   ASM_OUTPUT_LABEL (asm_out_file, cs_end_label);
 #else
   dw2_asm_output_data_uleb128 (call_site_len, "Call-site table length");
-  if (USING_SJLJ_EXCEPTIONS)
+  if (targetm.except_unwind_info (&global_options) == UI_SJLJ)
     sjlj_output_call_site_table ();
   else
     dw2_output_call_site_table (cs_format, section);
@@ -3095,7 +3106,7 @@ output_one_function_exception_table (const char * ARG_UNUSED (fnname),
 }
 
 void
-output_function_exception_table (const char * ARG_UNUSED (fnname))
+output_function_exception_table (const char *fnname)
 {
   rtx personality = get_personality_function (current_function_decl);
 
@@ -3104,11 +3115,21 @@ output_function_exception_table (const char * ARG_UNUSED (fnname))
     return;
 
   if (personality)
-    assemble_external_libcall (personality);
+    {
+      assemble_external_libcall (personality);
+
+      if (targetm.asm_out.emit_except_personality)
+       targetm.asm_out.emit_except_personality (personality);
+    }
 
-  output_one_function_exception_table (fnname, 0, personality);
+  switch_to_exception_section (fnname);
+
+  /* If the target wants a label to begin the table, emit it here.  */
+  targetm.asm_out.emit_except_table_label (asm_out_file);
+
+  output_one_function_exception_table (0);
   if (crtl->eh.call_site_record[1] != NULL)
-    output_one_function_exception_table (fnname, 1, personality);
+    output_one_function_exception_table (1);
 
   switch_to_section (current_function_section ());
 }
@@ -3197,7 +3218,7 @@ dump_eh_tree (FILE * out, struct function *fun)
            }
          else
            {
-             for (lp = i->landing_pads; lp ; lp = lp->next_lp);
+             for (lp = i->landing_pads; lp ; lp = lp->next_lp)
                {
                  fprintf (out, "{%i,", lp->index);
                  if (lp->landing_pad)