#include "coretypes.h"
#include "tm.h"
#include "rtl-error.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "input.h"
#include "alias.h"
#include "symtab.h"
-#include "inchash.h"
#include "tree.h"
#include "fold-const.h"
#include "stor-layout.h"
#include "stringpool.h"
#include "flags.h"
#include "except.h"
-#include "hashtab.h"
#include "hard-reg-set.h"
#include "function.h"
#include "rtl.h"
-#include "statistics.h"
#include "insn-config.h"
#include "expmed.h"
#include "dojump.h"
/* These hashes record the prologue and epilogue insns. */
-struct insn_cache_hasher : ggc_cache_hasher<rtx>
+struct insn_cache_hasher : ggc_cache_ptr_hash<rtx_def>
{
static hashval_t hash (rtx x) { return htab_hash_pointer (x); }
static bool equal (rtx a, rtx b) { return a == b; }
struct temp_slot *temp_slot;
};
-struct temp_address_hasher : ggc_hasher<temp_slot_address_entry *>
+struct temp_address_hasher : ggc_ptr_hash<temp_slot_address_entry>
{
static hashval_t hash (temp_slot_address_entry *);
static bool equal (temp_slot_address_entry *, temp_slot_address_entry *);
return true;
}
-/* Return true if TYPE should be passed by invisible reference. */
-
-bool
-pass_by_reference (CUMULATIVE_ARGS *ca, machine_mode mode,
- tree type, bool named_arg)
-{
- if (type)
- {
- /* If this type contains non-trivial constructors, then it is
- forbidden for the middle-end to create any new copies. */
- if (TREE_ADDRESSABLE (type))
- return true;
-
- /* GCC post 3.4 passes *all* variable sized types by reference. */
- if (!TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- return true;
-
- /* If a record type should be passed the same as its first (and only)
- member, use the type and mode of that member. */
- if (TREE_CODE (type) == RECORD_TYPE && TYPE_TRANSPARENT_AGGR (type))
- {
- type = TREE_TYPE (first_field (type));
- mode = TYPE_MODE (type);
- }
- }
-
- return targetm.calls.pass_by_reference (pack_cumulative_args (ca), mode,
- type, named_arg);
-}
-
-/* Return true if TYPE, which is passed by reference, should be callee
- copied instead of caller copied. */
-
-bool
-reference_callee_copied (CUMULATIVE_ARGS *ca, machine_mode mode,
- tree type, bool named_arg)
-{
- if (type && TREE_ADDRESSABLE (type))
- return false;
- return targetm.calls.callee_copies (pack_cumulative_args (ca), mode, type,
- named_arg);
-}
-
/* Structures to communicate between the subroutines of assign_parms.
The first holds data persistent across all parameters, the second
is cleared out for each parameter. */
}
else
t = op1;
- rtx pat = gen_extend_insn (op0, t, promoted_nominal_mode,
- data->passed_mode, unsignedp);
+ rtx_insn *pat = gen_extend_insn (op0, t, promoted_nominal_mode,
+ data->passed_mode, unsignedp);
emit_insn (pat);
insns = get_insns ();
static void
assign_bounds (vec<bounds_parm_data> &bndargs,
- struct assign_parm_data_all &all)
+ struct assign_parm_data_all &all,
+ bool assign_regs, bool assign_special,
+ bool assign_bt)
{
- unsigned i, pass, handled = 0;
+ unsigned i, pass;
bounds_parm_data *pbdata;
if (!bndargs.exists ())
{
/* Pass 0 => regs only. */
if (pass == 0
- && (!pbdata->parm_data.entry_parm
- || GET_CODE (pbdata->parm_data.entry_parm) != REG))
+ && (!assign_regs
+ ||(!pbdata->parm_data.entry_parm
+ || GET_CODE (pbdata->parm_data.entry_parm) != REG)))
continue;
/* Pass 1 => slots only. */
else if (pass == 1
- && (!pbdata->parm_data.entry_parm
- || GET_CODE (pbdata->parm_data.entry_parm) == REG))
+ && (!assign_special
+ || (!pbdata->parm_data.entry_parm
+ || GET_CODE (pbdata->parm_data.entry_parm) == REG)))
continue;
/* Pass 2 => BT only. */
else if (pass == 2
- && pbdata->parm_data.entry_parm)
+ && (!assign_bt
+ || pbdata->parm_data.entry_parm))
continue;
if (!pbdata->parm_data.entry_parm
else
assign_parm_setup_stack (&all, pbdata->bounds_parm,
&pbdata->parm_data);
-
- /* Count handled bounds to make sure we miss nothing. */
- handled++;
}
-
- gcc_assert (handled == bndargs.length ());
-
- bndargs.release ();
}
/* Assign RTL expressions to the function's parameters. This may involve
/* We expect this is the last parm. Otherwise it is wrong
to assign bounds right now. */
gcc_assert (i == (fnargs.length () - 1));
- assign_bounds (bndargs, all);
+ assign_bounds (bndargs, all, true, false, false);
targetm.calls.setup_incoming_vararg_bounds (all.args_so_far,
data.promoted_mode,
data.passed_type,
&pretend_bytes,
false);
+ assign_bounds (bndargs, all, false, true, true);
+ bndargs.release ();
}
}
bound_no++;
}
- assign_bounds (bndargs, all);
+ assign_bounds (bndargs, all, true, true, true);
+ bndargs.release ();
if (targetm.calls.split_complex_arg)
assign_parms_unsplit_complex (&all, fnargs);
/* Allow the target to compare Y with X without leaking either into
a register. */
- switch ((int) (HAVE_stack_protect_test != 0))
+ switch (HAVE_stack_protect_test != 0)
{
case 1:
tmp = gen_stack_protect_test (x, y, label);
void
expand_function_end (void)
{
- rtx clobber_after;
-
/* If arg_pointer_save_area was referenced only from a nested
function, we will not have initialized it yet. Do that now. */
if (arg_pointer_save_area && ! crtl->arg_pointer_save_area_init)
We delay actual code generation after the current_function_value_rtx
is computed. */
- clobber_after = get_last_insn ();
+ rtx_insn *clobber_after = get_last_insn ();
/* Output the label for the actual return from the function. */
emit_label (return_label);
certainly doesn't fall thru into the exit block. */
if (!BARRIER_P (clobber_after))
{
- rtx seq;
-
start_sequence ();
clobber_return_register ();
- seq = get_insns ();
+ rtx_insn *seq = get_insns ();
end_sequence ();
emit_insn_after (seq, clobber_after);
if (! EXIT_IGNORE_STACK
&& cfun->calls_alloca)
{
- rtx tem = 0, seq;
+ rtx tem = 0;
start_sequence ();
emit_stack_save (SAVE_FUNCTION, &tem);
- seq = get_insns ();
+ rtx_insn *seq = get_insns ();
end_sequence ();
emit_insn_before (seq, parm_birth_insn);
if (! crtl->arg_pointer_save_area_init)
{
- rtx seq;
-
/* Save the arg pointer at the beginning of the function. The
generated stack slot may not be a valid memory address, so we
have to check it and fix it if necessary. */
start_sequence ();
emit_move_insn (validize_mem (copy_rtx (ret)),
crtl->args.internal_arg_pointer);
- seq = get_insns ();
+ rtx_insn *seq = get_insns ();
end_sequence ();
push_topmost_sequence ();
static void
emit_use_return_register_into_block (basic_block bb)
{
- rtx seq;
- rtx_insn *insn;
start_sequence ();
use_return_register ();
- seq = get_insns ();
+ rtx_insn *seq = get_insns ();
end_sequence ();
- insn = BB_END (bb);
+ rtx_insn *insn = BB_END (bb);
if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
insn = prev_cc0_setter (insn);
/* Create a return pattern, either simple_return or return, depending on
simple_p. */
-static rtx
+static rtx_insn *
gen_return_pattern (bool simple_p)
{
- if (!HAVE_simple_return)
- gcc_assert (!simple_p);
-
- return simple_p ? gen_simple_return () : gen_return ();
+ return (simple_p
+ ? targetm.gen_simple_return ()
+ : targetm.gen_return ());
}
/* Insert an appropriate return pattern at the end of block BB. This
void
emit_return_into_block (bool simple_p, basic_block bb)
{
- rtx jump, pat;
- jump = emit_jump_insn_after (gen_return_pattern (simple_p), BB_END (bb));
- pat = PATTERN (jump);
+ rtx_jump_insn *jump = emit_jump_insn_after (gen_return_pattern (simple_p),
+ BB_END (bb));
+ rtx pat = PATTERN (jump);
if (GET_CODE (pat) == PARALLEL)
pat = XVECEXP (pat, 0, 0);
gcc_assert (ANY_RETURN_P (pat));
{
int i;
basic_block bb;
- rtx label;
edge_iterator ei;
edge e;
auto_vec<basic_block> src_bbs (EDGE_COUNT (last_bb->preds));
if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
src_bbs.quick_push (e->src);
- label = BB_HEAD (last_bb);
+ rtx_insn *label = BB_HEAD (last_bb);
FOR_EACH_VEC_ELT (src_bbs, i, bb)
{
dest = ret_rtx;
if (!redirect_jump (as_a <rtx_jump_insn *> (jump), dest, 0))
{
- if (HAVE_simple_return && simple_p)
+ if (targetm.have_simple_return () && simple_p)
{
if (dump_file)
fprintf (dump_file,
}
else
{
- if (HAVE_simple_return && simple_p)
+ if (targetm.have_simple_return () && simple_p)
{
if (dump_file)
fprintf (dump_file,
exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
- if (HAVE_simple_return && entry_edge != orig_entry_edge)
+ if (targetm.have_simple_return () && entry_edge != orig_entry_edge)
exit_fallthru_edge
= get_unconverted_simple_return (exit_fallthru_edge, bb_flags,
&unconverted_simple_returns,
&returnjump);
- if (HAVE_return)
+ if (targetm.have_return ())
{
if (exit_fallthru_edge == NULL)
goto epilogue_done;
/* Emitting the return may add a basic block.
Fix bb_flags for the added block. */
- if (HAVE_simple_return && last_bb != exit_fallthru_edge->src)
+ if (targetm.have_simple_return ()
+ && last_bb != exit_fallthru_edge->src)
bitmap_set_bit (&bb_flags, last_bb->index);
goto epilogue_done;
}
}
- if (HAVE_simple_return)
+ if (targetm.have_simple_return ())
convert_to_simple_return (entry_edge, orig_entry_edge, bb_flags,
returnjump, unconverted_simple_returns);
if (!CALL_P (insn)
|| ! SIBLING_CALL_P (insn)
- || (HAVE_simple_return && (entry_edge != orig_entry_edge
- && !bitmap_bit_p (&bb_flags, bb->index))))
+ || (targetm.have_simple_return ()
+ && entry_edge != orig_entry_edge
+ && !bitmap_bit_p (&bb_flags, bb->index)))
{
ei_next (&ei);
continue;