/* Expands front end tree to back end RTL for GCC.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "coretypes.h"
#include "tm.h"
#include "rtl-error.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "stor-layout.h"
#include "varasm.h"
#include "stringpool.h"
#include "flags.h"
#include "except.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
#include "hard-reg-set.h"
-#include "input.h"
#include "function.h"
+#include "rtl.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "insn-codes.h"
#include "optabs.h"
#include "libfuncs.h"
#include "regs.h"
-#include "insn-config.h"
#include "recog.h"
#include "output.h"
#include "tm_p.h"
struct function *cfun = 0;
/* These hashes record the prologue and epilogue insns. */
-static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
- htab_t prologue_insn_hash;
-static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
- htab_t epilogue_insn_hash;
+
+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; }
+};
+
+static GTY((cache))
+ hash_table<insn_cache_hasher> *prologue_insn_hash;
+static GTY((cache))
+ hash_table<insn_cache_hasher> *epilogue_insn_hash;
\f
hash_table<used_type_hasher> *types_used_by_vars_hash = NULL;
extern tree debug_find_var_in_block_tree (tree, tree);
/* We always define `record_insns' even if it's not used so that we
can always export `prologue_epilogue_contains'. */
-static void record_insns (rtx_insn *, rtx, htab_t *) ATTRIBUTE_UNUSED;
-static bool contains (const_rtx, htab_t);
+static void record_insns (rtx_insn *, rtx, hash_table<insn_cache_hasher> **)
+ ATTRIBUTE_UNUSED;
+static bool contains (const_rtx, hash_table<insn_cache_hasher> *);
static void prepare_function_start (void);
static void do_clobber_return_reg (rtx, void *);
static void do_use_return_reg (rtx, void *);
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 *);
/* When not optimizing, disregard register keyword for variables with
types containing methods, otherwise the methods won't be callable
from the debugger. */
- if (TYPE_METHODS (TREE_TYPE (decl)))
+ if (TYPE_METHODS (TYPE_MAIN_VARIANT (TREE_TYPE (decl))))
return false;
break;
default:
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);
crtl->args.size = CEIL_ROUND (crtl->args.size,
PARM_BOUNDARY / BITS_PER_UNIT);
-#ifdef ARGS_GROW_DOWNWARD
- crtl->args.arg_offset_rtx
- = (all.stack_args_size.var == 0 ? GEN_INT (-all.stack_args_size.constant)
- : expand_expr (size_diffop (all.stack_args_size.var,
- size_int (-all.stack_args_size.constant)),
- NULL_RTX, VOIDmode, EXPAND_NORMAL));
-#else
- crtl->args.arg_offset_rtx = ARGS_SIZE_RTX (all.stack_args_size);
-#endif
+ if (ARGS_GROW_DOWNWARD)
+ {
+ crtl->args.arg_offset_rtx
+ = (all.stack_args_size.var == 0 ? GEN_INT (-all.stack_args_size.constant)
+ : expand_expr (size_diffop (all.stack_args_size.var,
+ size_int (-all.stack_args_size.constant)),
+ NULL_RTX, VOIDmode, EXPAND_NORMAL));
+ }
+ else
+ crtl->args.arg_offset_rtx = ARGS_SIZE_RTX (all.stack_args_size);
/* See how many bytes, if any, of its args a function should try to pop
on return. */
if (crtl->preferred_stack_boundary < boundary)
crtl->preferred_stack_boundary = boundary;
-#ifdef ARGS_GROW_DOWNWARD
- locate->slot_offset.constant = -initial_offset_ptr->constant;
- if (initial_offset_ptr->var)
- locate->slot_offset.var = size_binop (MINUS_EXPR, ssize_int (0),
- initial_offset_ptr->var);
+ if (ARGS_GROW_DOWNWARD)
+ {
+ locate->slot_offset.constant = -initial_offset_ptr->constant;
+ if (initial_offset_ptr->var)
+ locate->slot_offset.var = size_binop (MINUS_EXPR, ssize_int (0),
+ initial_offset_ptr->var);
- {
- tree s2 = sizetree;
- if (where_pad != none
- && (!tree_fits_uhwi_p (sizetree)
- || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
- s2 = round_up (s2, round_boundary / BITS_PER_UNIT);
- SUB_PARM_SIZE (locate->slot_offset, s2);
- }
+ {
+ tree s2 = sizetree;
+ if (where_pad != none
+ && (!tree_fits_uhwi_p (sizetree)
+ || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
+ s2 = round_up (s2, round_boundary / BITS_PER_UNIT);
+ SUB_PARM_SIZE (locate->slot_offset, s2);
+ }
+
+ locate->slot_offset.constant += part_size_in_regs;
- locate->slot_offset.constant += part_size_in_regs;
-
- if (!in_regs || reg_parm_stack_space > 0)
- pad_to_arg_alignment (&locate->slot_offset, boundary,
- &locate->alignment_pad);
-
- locate->size.constant = (-initial_offset_ptr->constant
- - locate->slot_offset.constant);
- if (initial_offset_ptr->var)
- locate->size.var = size_binop (MINUS_EXPR,
- size_binop (MINUS_EXPR,
- ssize_int (0),
- initial_offset_ptr->var),
- locate->slot_offset.var);
-
- /* Pad_below needs the pre-rounded size to know how much to pad
- below. */
- locate->offset = locate->slot_offset;
- if (where_pad == downward)
- pad_below (&locate->offset, passed_mode, sizetree);
-
-#else /* !ARGS_GROW_DOWNWARD */
- if (!in_regs || reg_parm_stack_space > 0)
- pad_to_arg_alignment (initial_offset_ptr, boundary,
- &locate->alignment_pad);
- locate->slot_offset = *initial_offset_ptr;
+ if (!in_regs || reg_parm_stack_space > 0)
+ pad_to_arg_alignment (&locate->slot_offset, boundary,
+ &locate->alignment_pad);
+
+ locate->size.constant = (-initial_offset_ptr->constant
+ - locate->slot_offset.constant);
+ if (initial_offset_ptr->var)
+ locate->size.var = size_binop (MINUS_EXPR,
+ size_binop (MINUS_EXPR,
+ ssize_int (0),
+ initial_offset_ptr->var),
+ locate->slot_offset.var);
+
+ /* Pad_below needs the pre-rounded size to know how much to pad
+ below. */
+ locate->offset = locate->slot_offset;
+ if (where_pad == downward)
+ pad_below (&locate->offset, passed_mode, sizetree);
+
+ }
+ else
+ {
+ if (!in_regs || reg_parm_stack_space > 0)
+ pad_to_arg_alignment (initial_offset_ptr, boundary,
+ &locate->alignment_pad);
+ locate->slot_offset = *initial_offset_ptr;
#ifdef PUSH_ROUNDING
- if (passed_mode != BLKmode)
- sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
+ if (passed_mode != BLKmode)
+ sizetree = size_int (PUSH_ROUNDING (TREE_INT_CST_LOW (sizetree)));
#endif
- /* Pad_below needs the pre-rounded size to know how much to pad below
- so this must be done before rounding up. */
- locate->offset = locate->slot_offset;
- if (where_pad == downward)
- pad_below (&locate->offset, passed_mode, sizetree);
+ /* Pad_below needs the pre-rounded size to know how much to pad below
+ so this must be done before rounding up. */
+ locate->offset = locate->slot_offset;
+ if (where_pad == downward)
+ pad_below (&locate->offset, passed_mode, sizetree);
- if (where_pad != none
- && (!tree_fits_uhwi_p (sizetree)
- || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
- sizetree = round_up (sizetree, round_boundary / BITS_PER_UNIT);
+ if (where_pad != none
+ && (!tree_fits_uhwi_p (sizetree)
+ || (tree_to_uhwi (sizetree) * BITS_PER_UNIT) % round_boundary))
+ sizetree = round_up (sizetree, round_boundary / BITS_PER_UNIT);
- ADD_PARM_SIZE (locate->size, sizetree);
+ ADD_PARM_SIZE (locate->size, sizetree);
- locate->size.constant -= part_size_in_regs;
-#endif /* ARGS_GROW_DOWNWARD */
+ locate->size.constant -= part_size_in_regs;
+ }
#ifdef FUNCTION_ARG_OFFSET
locate->offset.constant += FUNCTION_ARG_OFFSET (passed_mode, type);
tree offset = size_binop (PLUS_EXPR,
ARGS_SIZE_TREE (*offset_ptr),
sp_offset_tree);
-#ifdef ARGS_GROW_DOWNWARD
- tree rounded = round_down (offset, boundary / BITS_PER_UNIT);
-#else
- tree rounded = round_up (offset, boundary / BITS_PER_UNIT);
-#endif
+ tree rounded;
+ if (ARGS_GROW_DOWNWARD)
+ rounded = round_down (offset, boundary / BITS_PER_UNIT);
+ else
+ rounded = round_up (offset, boundary / BITS_PER_UNIT);
offset_ptr->var = size_binop (MINUS_EXPR, rounded, sp_offset_tree);
/* ARGS_SIZE_TREE includes constant term. */
else
{
offset_ptr->constant = -sp_offset +
-#ifdef ARGS_GROW_DOWNWARD
- FLOOR_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes);
-#else
- CEIL_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes);
-#endif
+ (ARGS_GROW_DOWNWARD
+ ? FLOOR_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes)
+ : CEIL_ROUND (offset_ptr->constant + sp_offset, boundary_in_bytes));
+
if (boundary > PARM_BOUNDARY)
alignment_pad->constant = offset_ptr->constant - save_constant;
}
static void
prepare_function_start (void)
{
- gcc_assert (!crtl->emit.x_last_insn);
+ gcc_assert (!get_last_insn ());
init_temp_slots ();
init_emit ();
init_varasm_status ();
frame_pointer_needed = 0;
}
+void
+push_dummy_function (bool with_decl)
+{
+ tree fn_decl, fn_type, fn_result_decl;
+
+ gcc_assert (!in_dummy_function);
+ in_dummy_function = true;
+
+ if (with_decl)
+ {
+ fn_type = build_function_type_list (void_type_node, NULL_TREE);
+ fn_decl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, NULL_TREE,
+ fn_type);
+ fn_result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
+ NULL_TREE, void_type_node);
+ DECL_RESULT (fn_decl) = fn_result_decl;
+ }
+ else
+ fn_decl = NULL_TREE;
+
+ push_struct_function (fn_decl);
+}
+
/* Initialize the rtl expansion mechanism so that we can do simple things
like generate sequences. This is used to provide a context during global
initialization of some passes. You must call expand_dummy_function_end
void
init_dummy_function_start (void)
{
- gcc_assert (!in_dummy_function);
- in_dummy_function = true;
- push_struct_function (NULL_TREE);
+ push_dummy_function (false);
prepare_function_start ();
}
/* 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);
if (cfun->static_chain_decl)
{
tree parm = cfun->static_chain_decl;
- rtx local, chain, insn;
+ rtx local, chain;
+ rtx_insn *insn;
local = gen_reg_rtx (Pmode);
chain = targetm.calls.static_chain (current_function_decl, true);
stack_check_probe_note = emit_note (NOTE_INSN_DELETED);
}
\f
+void
+pop_dummy_function (void)
+{
+ pop_cfun ();
+ in_dummy_function = false;
+}
+
/* Undo the effects of init_dummy_function_start. */
void
expand_dummy_function_end (void)
free_after_parsing (cfun);
free_after_compilation (cfun);
- pop_cfun ();
- in_dummy_function = false;
+ pop_dummy_function ();
}
/* Helper for diddle_return_value. */
void
diddle_return_value (void (*doit) (rtx, void *), void *arg)
{
- diddle_return_value_1 (doit, arg, crtl->return_rtx);
diddle_return_value_1 (doit, arg, crtl->return_bnd);
+ diddle_return_value_1 (doit, arg, crtl->return_rtx);
}
static void
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 ();
for the first time. */
static void
-record_insns (rtx_insn *insns, rtx end, htab_t *hashp)
+record_insns (rtx_insn *insns, rtx end, hash_table<insn_cache_hasher> **hashp)
{
rtx_insn *tmp;
- htab_t hash = *hashp;
+ hash_table<insn_cache_hasher> *hash = *hashp;
if (hash == NULL)
- *hashp = hash
- = htab_create_ggc (17, htab_hash_pointer, htab_eq_pointer, NULL);
+ *hashp = hash = hash_table<insn_cache_hasher>::create_ggc (17);
for (tmp = insns; tmp != end; tmp = NEXT_INSN (tmp))
{
- void **slot = htab_find_slot (hash, tmp, INSERT);
+ rtx *slot = hash->find_slot (tmp, INSERT);
gcc_assert (*slot == NULL);
*slot = tmp;
}
void
maybe_copy_prologue_epilogue_insn (rtx insn, rtx copy)
{
- htab_t hash;
- void **slot;
+ hash_table<insn_cache_hasher> *hash;
+ rtx *slot;
hash = epilogue_insn_hash;
- if (!hash || !htab_find (hash, insn))
+ if (!hash || !hash->find (insn))
{
hash = prologue_insn_hash;
- if (!hash || !htab_find (hash, insn))
+ if (!hash || !hash->find (insn))
return;
}
- slot = htab_find_slot (hash, copy, INSERT);
+ slot = hash->find_slot (copy, INSERT);
gcc_assert (*slot == NULL);
*slot = copy;
}
we can be running after reorg, SEQUENCE rtl is possible. */
static bool
-contains (const_rtx insn, htab_t hash)
+contains (const_rtx insn, hash_table<insn_cache_hasher> *hash)
{
if (hash == NULL)
return false;
rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
int i;
for (i = seq->len () - 1; i >= 0; i--)
- if (htab_find (hash, seq->element (i)))
+ if (hash->find (seq->element (i)))
return true;
return false;
}
- return htab_find (hash, insn) != NULL;
+ return hash->find (const_cast<rtx> (insn)) != NULL;
}
int
return 0;
}
-#ifdef HAVE_return
/* Insert use of return register before the end of BB. */
static void
emit_use_return_register_into_block (basic_block bb)
{
- rtx seq, insn;
start_sequence ();
use_return_register ();
- seq = get_insns ();
+ rtx_insn *seq = get_insns ();
end_sequence ();
- insn = BB_END (bb);
-#ifdef HAVE_cc0
- if (reg_mentioned_p (cc0_rtx, PATTERN (insn)))
+ rtx_insn *insn = BB_END (bb);
+ if (HAVE_cc0 && reg_mentioned_p (cc0_rtx, PATTERN (insn)))
insn = prev_cc0_setter (insn);
-#endif
+
emit_insn_before (seq, 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)
{
-#ifdef HAVE_simple_return
- return simple_p ? gen_simple_return () : gen_return ();
-#else
- gcc_assert (!simple_p);
- return gen_return ();
-#endif
+ 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));
JUMP_LABEL (jump) = pat;
}
-#endif
/* Set JUMP_LABEL for a return insn. */
void
-set_return_jump_label (rtx returnjump)
+set_return_jump_label (rtx_insn *returnjump)
{
rtx pat = PATTERN (returnjump);
if (GET_CODE (pat) == PARALLEL)
JUMP_LABEL (returnjump) = ret_rtx;
}
-#if defined (HAVE_return) || defined (HAVE_simple_return)
/* Return true if there are any active insns between HEAD and TAIL. */
bool
active_insn_between (rtx_insn *head, rtx_insn *tail)
{
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 = simple_return_rtx;
else
dest = ret_rtx;
- if (!redirect_jump (jump, dest, 0))
+ if (!redirect_jump (as_a <rtx_jump_insn *> (jump), dest, 0))
{
-#ifdef HAVE_simple_return
- if (simple_p)
+ if (targetm.have_simple_return () && simple_p)
{
if (dump_file)
fprintf (dump_file,
"Failed to redirect bb %d branch.\n", bb->index);
unconverted.safe_push (e);
}
-#endif
continue;
}
}
else
{
-#ifdef HAVE_simple_return
- if (simple_p)
+ if (targetm.have_simple_return () && simple_p)
{
if (dump_file)
fprintf (dump_file,
"Failed to redirect bb %d branch.\n", bb->index);
unconverted.safe_push (e);
}
-#endif
continue;
}
exit_fallthru_edge->flags &= ~EDGE_FALLTHRU;
return last_bb;
}
-#endif
/* Generate the prologue and epilogue RTL if the machine supports it. Thread
thread_prologue_and_epilogue_insns (void)
{
bool inserted;
-#ifdef HAVE_simple_return
vec<edge> unconverted_simple_returns = vNULL;
bitmap_head bb_flags;
-#endif
rtx_insn *returnjump;
rtx_insn *epilogue_end ATTRIBUTE_UNUSED;
rtx_insn *prologue_seq ATTRIBUTE_UNUSED, *split_prologue_seq ATTRIBUTE_UNUSED;
}
#endif
-#ifdef HAVE_simple_return
bitmap_initialize (&bb_flags, &bitmap_default_obstack);
/* Try to perform a kind of shrink-wrapping, making sure the
function that require it. */
try_shrink_wrapping (&entry_edge, orig_entry_edge, &bb_flags, prologue_seq);
-#endif
if (split_prologue_seq != NULL_RTX)
{
exit_fallthru_edge = find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds);
-#ifdef HAVE_simple_return
- if (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);
-#endif
-#ifdef HAVE_return
- if (HAVE_return)
+ if (targetm.have_return ())
{
if (exit_fallthru_edge == NULL)
goto epilogue_done;
{
last_bb = emit_return_for_exit (exit_fallthru_edge, false);
epilogue_end = returnjump = BB_END (last_bb);
-#ifdef HAVE_simple_return
+
/* Emitting the return may add a basic block.
Fix bb_flags for the added block. */
- if (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);
-#endif
+
goto epilogue_done;
}
}
}
-#endif
/* A small fib -- epilogue is not yet completed, but we wish to re-use
this marker for the splits of EH_RETURN patterns, and nothing else
if (exit_fallthru_edge == NULL)
goto epilogue_done;
-#ifdef HAVE_epilogue
if (HAVE_epilogue)
{
start_sequence ();
set_return_jump_label (returnjump);
}
else
-#endif
{
basic_block cur_bb;
}
}
-#ifdef HAVE_simple_return
- convert_to_simple_return (entry_edge, orig_entry_edge, bb_flags, returnjump,
- unconverted_simple_returns);
-#endif
+ if (targetm.have_simple_return ())
+ convert_to_simple_return (entry_edge, orig_entry_edge, bb_flags,
+ returnjump, unconverted_simple_returns);
#ifdef HAVE_sibcall_epilogue
/* Emit sibling epilogues before any sibling call sites. */
if (!CALL_P (insn)
|| ! SIBLING_CALL_P (insn)
-#ifdef HAVE_simple_return
- || (entry_edge != orig_entry_edge
- && !bitmap_bit_p (&bb_flags, bb->index))
-#endif
- )
+ || (targetm.have_simple_return ()
+ && entry_edge != orig_entry_edge
+ && !bitmap_bit_p (&bb_flags, bb->index)))
{
ei_next (&ei);
continue;
}
#endif
-#ifdef HAVE_epilogue
if (epilogue_end)
{
rtx_insn *insn, *next;
reorder_insns (insn, insn, PREV_INSN (epilogue_end));
}
}
-#endif
-#ifdef HAVE_simple_return
bitmap_clear (&bb_flags);
-#endif
/* Threading the prologue and epilogue changes the artificial refs
in the entry and exit blocks. */
void
reposition_prologue_and_epilogue_notes (void)
{
-#if defined (HAVE_prologue) || defined (HAVE_epilogue) \
- || defined (HAVE_sibcall_epilogue)
+#if ! defined (HAVE_prologue) && ! defined (HAVE_sibcall_epilogue)
+ if (!HAVE_epilogue)
+ return;
+#endif
+
/* Since the hash table is created on demand, the fact that it is
non-null is a signal that it is non-empty. */
if (prologue_insn_hash != NULL)
{
- size_t len = htab_elements (prologue_insn_hash);
+ size_t len = prologue_insn_hash->elements ();
rtx_insn *insn, *last = NULL, *note = NULL;
/* Scan from the beginning until we reach the last prologue insn. */
}
}
}
-#endif /* HAVE_prologue or HAVE_epilogue */
}
/* Returns the name of function declared by FNDECL. */