#include "flags.h"
#include "function.h"
#include "expr.h"
+#include "libfuncs.h"
#include "insn-config.h"
#include "except.h"
#include "integrate.h"
/* End an exception region for an exception type filter. ALLOWED is a
TREE_LIST of types to be matched by the runtime. FAILURE is an
- expression to invoke if a mismatch ocurrs. */
+ expression to invoke if a mismatch ocurrs.
+
+ ??? We could use these semantics for calls to rethrow, too; if we can
+ see the surrounding catch clause, we know that the exception we're
+ rethrowing satisfies the "filter" of the catch type. */
void
expand_eh_region_end_allowed (allowed, failure)
&& fixup->type == ERT_FIXUP)
{
if (fixup->u.fixup.real_region)
- XEXP (note, 1) = GEN_INT (fixup->u.fixup.real_region->region_number);
+ XEXP (note, 0) = GEN_INT (fixup->u.fixup.real_region->region_number);
else
remove_note (insn, note);
}
/* If we wanted exceptions for non-call insns, then
any may_trap_p instruction could throw. */
|| (flag_non_call_exceptions
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && GET_CODE (PATTERN (insn)) != USE
&& may_trap_p (PATTERN (insn)))))
{
REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (cur),
cur->inner = root;
for (i = 1; i <= ifun_last_region_number; ++i)
- if (n_array[i]->outer == NULL)
+ if (n_array[i] && n_array[i]->outer == NULL)
n_array[i]->outer = cur;
}
else
}
\f
-/* ??? Move from tree.c to tree.h. */
-#define TYPE_HASH(TYPE) ((HOST_WIDE_INT) (TYPE) & 0777777)
-
static int
t2r_eq (pentry, pdata)
const PTR pentry;
/* Don't separate a call from it's argument loads. */
before = insn;
if (GET_CODE (insn) == CALL_INSN)
- {
- HARD_REG_SET parm_regs;
- int nparm_regs;
-
- /* Since different machines initialize their parameter registers
- in different orders, assume nothing. Collect the set of all
- parameter registers. */
- CLEAR_HARD_REG_SET (parm_regs);
- nparm_regs = 0;
- for (p = CALL_INSN_FUNCTION_USAGE (insn); p ; p = XEXP (p, 1))
- if (GET_CODE (XEXP (p, 0)) == USE
- && GET_CODE (XEXP (XEXP (p, 0), 0)) == REG)
- {
- if (REGNO (XEXP (XEXP (p, 0), 0)) >= FIRST_PSEUDO_REGISTER)
- abort ();
-
- /* We only care about registers which can hold function
- arguments. */
- if (! FUNCTION_ARG_REGNO_P (REGNO (XEXP (XEXP (p, 0), 0))))
- continue;
-
- SET_HARD_REG_BIT (parm_regs, REGNO (XEXP (XEXP (p, 0), 0)));
- nparm_regs++;
- }
-
- /* Search backward for the first set of a register in this set. */
- while (nparm_regs)
- {
- before = PREV_INSN (before);
-
- /* Given that we've done no other optimizations yet,
- the arguments should be immediately available. */
- if (GET_CODE (before) == CODE_LABEL)
- abort ();
-
- p = single_set (before);
- if (p && GET_CODE (SET_DEST (p)) == REG
- && REGNO (SET_DEST (p)) < FIRST_PSEUDO_REGISTER
- && TEST_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p))))
- {
- CLEAR_HARD_REG_BIT (parm_regs, REGNO (SET_DEST (p)));
- nparm_regs--;
- }
- }
- }
+ before = find_first_parameter_load (insn, NULL_RTX);
start_sequence ();
emit_move_insn (mem, GEN_INT (this_call_site));
rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0);
- cleanup_cfg (0);
+ cleanup_cfg (CLEANUP_PRE_LOOP);
/* These registers are used by the landing pads. Make sure they
have been generated. */
find_exception_handler_labels ();
rebuild_jump_labels (get_insns ());
find_basic_blocks (get_insns (), max_reg_num (), 0);
- cleanup_cfg (0);
+ cleanup_cfg (CLEANUP_PRE_LOOP);
}
\f
/* This section handles removing dead code for flow. */
expand_builtin_unwind_init ()
{
/* Set this so all the registers get saved in our frame; we need to be
- able to copy the saved values for any registers from frames we unwind. */
+ able to copy the saved values for any registers from frames we unwind. */
current_function_has_nonlocal_label = 1;
#ifdef SETUP_FRAME_ADDRESSES
emit_label (around_label);
}
\f
+/* In the following functions, we represent entries in the action table
+ as 1-based indicies. Special cases are:
+
+ 0: null action record, non-null landing pad; implies cleanups
+ -1: null action record, null landing pad; implies no action
+ -2: no call-site entry; implies must_not_throw
+ -3: we have yet to process outer regions
+
+ Further, no special cases apply to the "next" field of the record.
+ For next, 0 means end of list. */
+
struct action_record
{
int offset;
if (next == -3)
{
next = collect_one_action_chain (ar_hash, region->outer);
- if (next < 0)
+
+ /* If there is no next action, terminate the chain. */
+ if (next == -1)
next = 0;
+ /* If all outer actions are cleanups or must_not_throw,
+ we'll have no action record for it, since we had wanted
+ to encode these states in the call-site record directly.
+ Add a cleanup action to the chain to catch these. */
+ else if (next <= 0)
+ next = add_action_record (ar_hash, 0, 0);
}
next = add_action_record (ar_hash, c->u.catch.filter, next);
}
#endif
tt_format_size = size_of_encoded_value (tt_format);
- assemble_eh_align (tt_format_size * BITS_PER_UNIT);
+ assemble_align (tt_format_size * BITS_PER_UNIT);
}
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LLSDA", funcdef_number);
(i ? NULL : "Action record table"));
if (have_tt_data)
- assemble_eh_align (tt_format_size * BITS_PER_UNIT);
+ assemble_align (tt_format_size * BITS_PER_UNIT);
i = VARRAY_ACTIVE_SIZE (cfun->eh->ttype_data);
while (i-- > 0)