/* 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.
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;
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
}
}
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 ())
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)
{
/* 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);
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,
fn_begin_outside_block = false;
}
+#ifdef DONT_USE_BUILTIN_SETJMP
+ if (dispatch_label)
+ {
+ /* The sequence contains a branch in the middle so we need to force
+ the creation of a new basic block by means of BB_SUPERBLOCK. */
+ if (fn_begin_outside_block)
+ {
+ basic_block bb
+ = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
+ if (JUMP_P (BB_END (bb)))
+ emit_insn_before (seq, BB_END (bb));
+ else
+ emit_insn_after (seq, BB_END (bb));
+ }
+ else
+ emit_insn_after (seq, fn_begin);
+
+ single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))->flags |= BB_SUPERBLOCK;
+ return;
+ }
+#endif
+
if (fn_begin_outside_block)
insert_insn_on_edge (seq, single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
else
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)
: 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. */
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))
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))
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);
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);
}
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. */
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)
{
}
}
+/* 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)
/* 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 ());
}