]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/except.c
[testsuite] Add missing dg-require-effective-target label_values
[thirdparty/gcc.git] / gcc / except.c
index 4991e7bb01bd1f0b70bae6b3a1e71b60b922af19..edaeeb4cfd1b8f57e0ad75167302d4e6614e4a3f 100644 (file)
@@ -1,5 +1,5 @@
 /* Implements exception handling.
-   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+   Copyright (C) 1989-2019 Free Software Foundation, Inc.
    Contributed by Mike Stump <mrs@cygnus.com>.
 
 This file is part of GCC.
@@ -147,7 +147,9 @@ along with GCC; see the file COPYING3.  If not see
 
 static GTY(()) int call_site_base;
 
-static GTY (()) hash_map<tree_hash, tree> *type_to_runtime_map;
+static GTY(()) hash_map<tree_hash, tree> *type_to_runtime_map;
+
+static GTY(()) tree setjmp_fn;
 
 /* Describe the SjLj_Function_Context structure.  */
 static GTY(()) tree sjlj_fc_type_node;
@@ -331,6 +333,16 @@ init_eh (void)
       sjlj_fc_jbuf_ofs
        = (tree_to_uhwi (DECL_FIELD_OFFSET (f_jbuf))
           + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (f_jbuf)) / BITS_PER_UNIT);
+
+#ifdef DONT_USE_BUILTIN_SETJMP
+      tmp = build_function_type_list (integer_type_node, TREE_TYPE (f_jbuf),
+                                     NULL);
+      setjmp_fn = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
+                             get_identifier ("setjmp"), tmp);
+      TREE_PUBLIC (setjmp_fn) = 1;
+      DECL_EXTERNAL (setjmp_fn) = 1;
+      DECL_ASSEMBLER_NAME (setjmp_fn);
+#endif
     }
 }
 
@@ -935,7 +947,7 @@ emit_to_new_bb_before (rtx_insn *seq, rtx_insn *insn)
    at the rtl level.  Emit the code required by the target at a landing
    pad for the given region.  */
 
-void
+static void
 expand_dw2_landing_pad_for_region (eh_region region)
 {
   if (targetm.have_exception_receiver ())
@@ -991,7 +1003,6 @@ dw2_build_landing_pads (void)
 
       bb = emit_to_new_bb_before (seq, label_rtx (lp->post_landing_pad));
       bb->count = bb->next_bb->count;
-      bb->frequency = bb->next_bb->frequency;
       make_single_succ_edge (bb, bb->next_bb, e_flags);
       if (current_loops)
        {
@@ -1148,7 +1159,7 @@ sjlj_emit_function_enter (rtx_code_label *dispatch_label)
 
   /* We're storing this libcall's address into memory instead of
      calling it directly.  Thus, we must call assemble_external_libcall
-     here, as we can not depend on emit_library_call to do it for us.  */
+     here, as we cannot depend on emit_library_call to do it for us.  */
   assemble_external_libcall (personality);
   mem = adjust_address (fc, Pmode, sjlj_fc_personality_ofs);
   emit_move_insn (mem, personality);
@@ -1176,8 +1187,7 @@ sjlj_emit_function_enter (rtx_code_label *dispatch_label)
       addr = convert_memory_address (ptr_mode, addr);
       tree addr_tree = make_tree (ptr_type_node, addr);
 
-      tree fn = builtin_decl_implicit (BUILT_IN_SETJMP);
-      tree call_expr = build_call_expr (fn, 1, addr_tree);
+      tree call_expr = build_call_expr (setjmp_fn, 1, addr_tree);
       rtx x = expand_call (call_expr, NULL_RTX, false);
 
       emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
@@ -1500,12 +1510,8 @@ finish_eh_generation (void)
     sjlj_build_landing_pads ();
   else
     dw2_build_landing_pads ();
-  break_superblocks ();
 
-  if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
-      /* Kludge for Alpha (see alpha_gp_save_rtx).  */
-      || single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->insns.r)
-    commit_edge_insertions ();
+  break_superblocks ();
 
   /* Redirect all EH edges from the post_landing_pad to the landing pad.  */
   FOR_EACH_BB_FN (bb, cfun)
@@ -1536,6 +1542,11 @@ finish_eh_generation (void)
                       : EDGE_ABNORMAL);
        }
     }
+
+  if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
+      /* Kludge for Alpha (see alpha_gp_save_rtx).  */
+      || single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->insns.r)
+    commit_edge_insertions ();
 }
 \f
 /* This section handles removing dead code for flow.  */
@@ -1745,6 +1756,8 @@ copy_reg_eh_region_note_forward (rtx note_or_insn, rtx_insn *first, rtx last)
       if (note == NULL)
        return;
     }
+  else if (is_a <rtx_insn *> (note_or_insn))
+    return;
   note = XEXP (note, 0);
 
   for (insn = first; insn != last ; insn = NEXT_INSN (insn))
@@ -1767,6 +1780,8 @@ copy_reg_eh_region_note_backward (rtx note_or_insn, rtx_insn *last, rtx first)
       if (note == NULL)
        return;
     }
+  else if (is_a <rtx_insn *> (note_or_insn))
+    return;
   note = XEXP (note, 0);
 
   for (insn = last; insn != first; insn = PREV_INSN (insn))
@@ -2273,7 +2288,7 @@ expand_eh_return (void)
       if (rtx handler = EH_RETURN_HANDLER_RTX)
        emit_move_insn (handler, crtl->eh.ehr_handler);
       else
-       error ("__builtin_eh_return not supported on this target");
+       error ("%<__builtin_eh_return%> not supported on this target");
     }
 
   emit_label (around_label);
@@ -2455,14 +2470,6 @@ add_call_site (rtx landing_pad, int action, int section)
 static rtx_note *
 emit_note_eh_region_end (rtx_insn *insn)
 {
-  rtx_insn *next = NEXT_INSN (insn);
-
-  /* Make sure we do not split a call and its corresponding
-     CALL_ARG_LOCATION note.  */
-  if (next && NOTE_P (next)
-      && NOTE_KIND (next) == NOTE_INSN_CALL_ARG_LOCATION)
-    insn = next;
-
   return emit_note_after (NOTE_INSN_EH_REGION_END, insn);
 }
 
@@ -2937,7 +2944,6 @@ switch_to_exception_section (const char * ARG_UNUSED (fnname))
   switch_to_section (s);
 }
 
-
 /* Output a reference from an exception table to the type_info object TYPE.
    TT_FORMAT and TT_FORMAT_SIZE describe the DWARF encoding method used for
    the value.  */
@@ -2987,6 +2993,13 @@ output_ttype (tree type, int tt_format, int tt_format_size)
     dw2_asm_output_encoded_addr_rtx (tt_format, value, is_public, NULL);
 }
 
+/* Output an exception table for the current function according to SECTION.
+
+   If the function has been partitioned into hot and cold parts, value 0 for
+   SECTION refers to the table associated with the hot part while value 1
+   refers to the table associated with the cold part.  If the function has
+   not been partitioned, value 0 refers to the single exception table.  */
 static void
 output_one_function_exception_table (int section)
 {
@@ -3165,13 +3178,27 @@ output_one_function_exception_table (int section)
     }
 }
 
+/* Output an exception table for the current function according to SECTION,
+   switching back and forth from the function section appropriately.
+
+   If the function has been partitioned into hot and cold parts, value 0 for
+   SECTION refers to the table associated with the hot part while value 1
+   refers to the table associated with the cold part.  If the function has
+   not been partitioned, value 0 refers to the single exception table.  */
+
 void
-output_function_exception_table (const char *fnname)
+output_function_exception_table (int section)
 {
+  const char *fnname = get_fnname_from_decl (current_function_decl);
   rtx personality = get_personality_function (current_function_decl);
 
   /* Not all functions need anything.  */
-  if (! crtl->uses_eh_lsda)
+  if (!crtl->uses_eh_lsda
+      || targetm_common.except_unwind_info (&global_options) == UI_NONE)
+    return;
+
+  /* No need to emit any boilerplate stuff for the cold part.  */
+  if (section == 1 && !crtl->eh.call_site_record_v[1])
     return;
 
   if (personality)
@@ -3187,9 +3214,8 @@ output_function_exception_table (const char *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_v[1])
-    output_one_function_exception_table (1);
+  /* Do the real work.  */
+  output_one_function_exception_table (section);
 
   switch_to_section (current_function_section ());
 }
@@ -3386,7 +3412,7 @@ verify_eh_tree (struct function *fun)
          count_r++;
        else
          {
-           error ("region_array is corrupted for region %i", r->index);
+           error ("%<region_array%> is corrupted for region %i", r->index);
            err = true;
          }
       }
@@ -3399,7 +3425,7 @@ verify_eh_tree (struct function *fun)
          count_lp++;
        else
          {
-           error ("lp_array is corrupted for lp %i", lp->index);
+           error ("%<lp_array%> is corrupted for lp %i", lp->index);
            err = true;
          }
       }
@@ -3411,7 +3437,7 @@ verify_eh_tree (struct function *fun)
     {
       if ((*fun->eh->region_array)[r->index] != r)
        {
-         error ("region_array is corrupted for region %i", r->index);
+         error ("%<region_array%> is corrupted for region %i", r->index);
          err = true;
        }
       if (r->outer != outer)
@@ -3430,7 +3456,7 @@ verify_eh_tree (struct function *fun)
        {
          if ((*fun->eh->lp_array)[lp->index] != lp)
            {
-             error ("lp_array is corrupted for lp %i", lp->index);
+             error ("%<lp_array%> is corrupted for lp %i", lp->index);
              err = true;
            }
          if (lp->region != r)
@@ -3467,19 +3493,19 @@ verify_eh_tree (struct function *fun)
     }
   if (count_r != nvisited_r)
     {
-      error ("region_array does not match region_tree");
+      error ("%<region_array%> does not match %<region_tree%>");
       err = true;
     }
   if (count_lp != nvisited_lp)
     {
-      error ("lp_array does not match region_tree");
+      error ("%<lp_array%> does not match %<region_tree%>");
       err = true;
     }
 
   if (err)
     {
       dump_eh_tree (stderr, fun);
-      internal_error ("verify_eh_tree failed");
+      internal_error ("%qs failed", __func__);
     }
 }
 \f