/* Subroutines for manipulating rtx's in semantically interesting ways.
Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of GCC.
#include "recog.h"
#include "langhooks.h"
-static rtx break_out_memory_refs PARAMS ((rtx));
-static void emit_stack_probe PARAMS ((rtx));
+static rtx break_out_memory_refs (rtx);
+static void emit_stack_probe (rtx);
/* Truncate and perhaps sign-extend C as appropriate for MODE. */
HOST_WIDE_INT
-trunc_int_for_mode (c, mode)
- HOST_WIDE_INT c;
- enum machine_mode mode;
+trunc_int_for_mode (HOST_WIDE_INT c, enum machine_mode mode)
{
int width = GET_MODE_BITSIZE (mode);
This function should be used via the `plus_constant' macro. */
rtx
-plus_constant_wide (x, c)
- rtx x;
- HOST_WIDE_INT c;
+plus_constant_wide (rtx x, HOST_WIDE_INT c)
{
RTX_CODE code;
rtx y;
it is not isomorphic to X. */
rtx
-eliminate_constant_term (x, constptr)
- rtx x;
- rtx *constptr;
+eliminate_constant_term (rtx x, rtx *constptr)
{
rtx x0, x1;
rtx tem;
return x;
}
-/* Returns the insn that next references REG after INSN, or 0
- if REG is clobbered before next referenced or we cannot find
- an insn that references REG in a straight-line piece of code. */
-
-rtx
-find_next_ref (reg, insn)
- rtx reg;
- rtx insn;
-{
- rtx next;
-
- for (insn = NEXT_INSN (insn); insn; insn = next)
- {
- next = NEXT_INSN (insn);
- if (GET_CODE (insn) == NOTE)
- continue;
- if (GET_CODE (insn) == CODE_LABEL
- || GET_CODE (insn) == BARRIER)
- return 0;
- if (GET_CODE (insn) == INSN
- || GET_CODE (insn) == JUMP_INSN
- || GET_CODE (insn) == CALL_INSN)
- {
- if (reg_set_p (reg, insn))
- return 0;
- if (reg_mentioned_p (reg, PATTERN (insn)))
- return insn;
- if (GET_CODE (insn) == JUMP_INSN)
- {
- if (any_uncondjump_p (insn))
- next = JUMP_LABEL (insn);
- else
- return 0;
- }
- if (GET_CODE (insn) == CALL_INSN
- && REGNO (reg) < FIRST_PSEUDO_REGISTER
- && call_used_regs[REGNO (reg)])
- return 0;
- }
- else
- abort ();
- }
- return 0;
-}
-
/* Return an rtx for the size in bytes of the value of EXP. */
rtx
-expr_size (exp)
- tree exp;
+expr_size (tree exp)
{
tree size = (*lang_hooks.expr_size) (exp);
- if (TREE_CODE (size) != INTEGER_CST
- && contains_placeholder_p (size))
+ if (CONTAINS_PLACEHOLDER_P (size))
size = build (WITH_RECORD_EXPR, sizetype, size, exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
if the size can vary or is larger than an integer. */
HOST_WIDE_INT
-int_expr_size (exp)
- tree exp;
+int_expr_size (tree exp)
{
tree t = (*lang_hooks.expr_size) (exp);
Values returned by expand_expr with 1 for sum_ok fit this constraint. */
static rtx
-break_out_memory_refs (x)
- rtx x;
+break_out_memory_refs (rtx x)
{
if (GET_CODE (x) == MEM
|| (CONSTANT_P (x) && CONSTANT_ADDRESS_P (x)
return x;
}
-#ifdef POINTERS_EXTEND_UNSIGNED
-
/* Given X, a memory address in ptr_mode, convert it to an address
in Pmode, or vice versa (TO_MODE says which way). We take advantage of
the fact that pointers are not allowed to overflow by commuting arithmetic
used. */
rtx
-convert_memory_address (to_mode, x)
- enum machine_mode to_mode;
- rtx x;
+convert_memory_address (enum machine_mode to_mode ATTRIBUTE_UNUSED,
+ rtx x)
{
- enum machine_mode from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
+#ifndef POINTERS_EXTEND_UNSIGNED
+ return x;
+#else /* defined(POINTERS_EXTEND_UNSIGNED) */
+ enum machine_mode from_mode;
rtx temp;
enum rtx_code code;
+ /* If X already has the right mode, just return it. */
+ if (GET_MODE (x) == to_mode)
+ return x;
+
+ from_mode = to_mode == ptr_mode ? Pmode : ptr_mode;
+
/* Here we handle some special cases. If none of them apply, fall through
to the default case. */
switch (GET_CODE (x))
return convert_modes (to_mode, from_mode,
x, POINTERS_EXTEND_UNSIGNED);
+#endif /* defined(POINTERS_EXTEND_UNSIGNED) */
}
-#endif
/* Given a memory address or facsimile X, construct a new address,
currently equivalent, that is stable: future stores won't change it.
but then you wouldn't get indexed addressing in the reference. */
rtx
-copy_all_regs (x)
- rtx x;
+copy_all_regs (rtx x)
{
if (GET_CODE (x) == REG)
{
works by copying X or subexpressions of it into registers. */
rtx
-memory_address (mode, x)
- enum machine_mode mode;
- rtx x;
+memory_address (enum machine_mode mode, rtx x)
{
rtx oldx = x;
if (GET_CODE (x) == ADDRESSOF)
return x;
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (x) != Pmode)
- x = convert_memory_address (Pmode, x);
-#endif
+ x = convert_memory_address (Pmode, x);
/* By passing constant addresses thru registers
we get a chance to cse them. */
/* Like `memory_address' but pretend `flag_force_addr' is 0. */
rtx
-memory_address_noforce (mode, x)
- enum machine_mode mode;
- rtx x;
+memory_address_noforce (enum machine_mode mode, rtx x)
{
int ambient_force_addr = flag_force_addr;
rtx val;
Pass through anything else unchanged. */
rtx
-validize_mem (ref)
- rtx ref;
+validize_mem (rtx ref)
{
if (GET_CODE (ref) != MEM)
return ref;
appropriate. */
void
-maybe_set_unchanging (ref, t)
- rtx ref;
- tree t;
+maybe_set_unchanging (rtx ref, tree t)
{
/* We can set RTX_UNCHANGING_P from TREE_READONLY for decls whose
initialization is only executed once, or whose initializer always
contents of the initializer. Yes, this does eliminate a good fraction
of the number of uses of RTX_UNCHANGING_P for a language like Ada.
It also eliminates a good quantity of bugs. Let this be incentive to
- eliminate RTX_UNCHANGING_P entirely in favour of a more reliable
+ eliminate RTX_UNCHANGING_P entirely in favor of a more reliable
solution, perhaps based on alias sets. */
if ((TREE_READONLY (t) && DECL_P (t)
Perhaps even if it is a MEM, if there is no need to change it. */
rtx
-stabilize (x)
- rtx x;
+stabilize (rtx x)
{
if (GET_CODE (x) != MEM
|| ! rtx_unstable_p (XEXP (x, 0)))
/* Copy the value or contents of X to a new temp reg and return that reg. */
rtx
-copy_to_reg (x)
- rtx x;
+copy_to_reg (rtx x)
{
rtx temp = gen_reg_rtx (GET_MODE (x));
in case X is a constant. */
rtx
-copy_addr_to_reg (x)
- rtx x;
+copy_addr_to_reg (rtx x)
{
return copy_to_mode_reg (Pmode, x);
}
in case X is a constant. */
rtx
-copy_to_mode_reg (mode, x)
- enum machine_mode mode;
- rtx x;
+copy_to_mode_reg (enum machine_mode mode, rtx x)
{
rtx temp = gen_reg_rtx (mode);
since we mark it as a "constant" register. */
rtx
-force_reg (mode, x)
- enum machine_mode mode;
- rtx x;
+force_reg (enum machine_mode mode, rtx x)
{
rtx temp, insn, set;
that reg. Otherwise, return X. */
rtx
-force_not_mem (x)
- rtx x;
+force_not_mem (rtx x)
{
rtx temp;
MODE is the mode to use for X in case it is a constant. */
rtx
-copy_to_suggested_reg (x, target, mode)
- rtx x, target;
- enum machine_mode mode;
+copy_to_suggested_reg (rtx x, rtx target, enum machine_mode mode)
{
rtx temp;
FOR_CALL is nonzero if this call is promoting args for a call. */
enum machine_mode
-promote_mode (type, mode, punsignedp, for_call)
- tree type;
- enum machine_mode mode;
- int *punsignedp;
- int for_call ATTRIBUTE_UNUSED;
+promote_mode (tree type, enum machine_mode mode, int *punsignedp,
+ int for_call ATTRIBUTE_UNUSED)
{
enum tree_code code = TREE_CODE (type);
int unsignedp = *punsignedp;
This pops when ADJUST is positive. ADJUST need not be constant. */
void
-adjust_stack (adjust)
- rtx adjust;
+adjust_stack (rtx adjust)
{
rtx temp;
adjust = protect_from_queue (adjust, 0);
This pushes when ADJUST is positive. ADJUST need not be constant. */
void
-anti_adjust_stack (adjust)
- rtx adjust;
+anti_adjust_stack (rtx adjust)
{
rtx temp;
adjust = protect_from_queue (adjust, 0);
by this machine. SIZE is the desired size, which need not be constant. */
rtx
-round_push (size)
- rtx size;
+round_push (rtx size)
{
int align = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT;
are emitted at the current position. */
void
-emit_stack_save (save_level, psave, after)
- enum save_level save_level;
- rtx *psave;
- rtx after;
+emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
{
rtx sa = *psave;
/* The default is that we use a move insn and save in a Pmode object. */
- rtx (*fcn) PARAMS ((rtx, rtx)) = gen_move_insn;
+ rtx (*fcn) (rtx, rtx) = gen_move_insn;
enum machine_mode mode = STACK_SAVEAREA_MODE (save_level);
/* See if this machine has anything special to do for this kind of save. */
current position. */
void
-emit_stack_restore (save_level, sa, after)
- enum save_level save_level;
- rtx after;
- rtx sa;
+emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
{
/* The default is that we use a move insn. */
- rtx (*fcn) PARAMS ((rtx, rtx)) = gen_move_insn;
+ rtx (*fcn) (rtx, rtx) = gen_move_insn;
/* See if this machine has anything special to do for this kind of save. */
switch (save_level)
references to variable arrays below the code
that deletes (pops) the arrays. */
emit_insn (gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_MEM (BLKmode,
+ gen_rtx_MEM (BLKmode,
gen_rtx_SCRATCH (VOIDmode))));
emit_insn (gen_rtx_CLOBBER (VOIDmode,
gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
frame, thus causing a crash if a longjmp unwinds to it. */
void
-optimize_save_area_alloca (insns)
- rtx insns;
+optimize_save_area_alloca (rtx insns)
{
rtx insn;
KNOWN_ALIGN is the alignment (in bits) that we know SIZE has. */
rtx
-allocate_dynamic_stack_space (size, target, known_align)
- rtx size;
- rtx target;
- int known_align;
+allocate_dynamic_stack_space (rtx size, rtx target, int known_align)
{
#ifdef SETJMP_VIA_SAVE_AREA
rtx setjmpless_size = NULL_RTX;
NULL_RTX, 1);
}
- /* Some systems require a particular insn to refer to the stack
- to make the pages exist. */
-#ifdef HAVE_probe
- if (HAVE_probe)
- emit_insn (gen_probe ());
-#endif
-
/* Record the new stack level for nonlocal gotos. */
if (nonlocal_goto_handler_slots != 0)
emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
static GTY(()) rtx stack_check_libfunc;
void
-set_stack_check_libfunc (libfunc)
- rtx libfunc;
+set_stack_check_libfunc (rtx libfunc)
{
stack_check_libfunc = libfunc;
}
/* Emit one stack probe at ADDRESS, an address within the stack. */
static void
-emit_stack_probe (address)
- rtx address;
+emit_stack_probe (rtx address)
{
rtx memref = gen_rtx_MEM (word_mode, address);
#endif
void
-probe_stack_range (first, size)
- HOST_WIDE_INT first;
- rtx size;
+probe_stack_range (HOST_WIDE_INT first, rtx size)
{
/* First ensure SIZE is Pmode. */
if (GET_MODE (size) != VOIDmode && GET_MODE (size) != Pmode)
stack_pointer_rtx,
plus_constant (size, first)));
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE (addr) != ptr_mode)
- addr = convert_memory_address (ptr_mode, addr);
-#endif
-
+ addr = convert_memory_address (ptr_mode, addr);
emit_library_call (stack_check_libfunc, LCT_NORMAL, VOIDmode, 1, addr,
ptr_mode);
}
|| REGNO (test_addr) < FIRST_PSEUDO_REGISTER)
test_addr = force_reg (Pmode, test_addr);
- emit_note (NULL, NOTE_INSN_LOOP_BEG);
+ emit_note (NOTE_INSN_LOOP_BEG);
emit_jump (test_lab);
emit_label (loop_lab);
emit_stack_probe (test_addr);
- emit_note (NULL, NOTE_INSN_LOOP_CONT);
+ emit_note (NOTE_INSN_LOOP_CONT);
#ifdef STACK_GROWS_DOWNWARD
#define CMP_OPCODE GTU
emit_cmp_and_jump_insns (test_addr, last_addr, CMP_OPCODE,
NULL_RTX, Pmode, 1, loop_lab);
emit_jump (end_lab);
- emit_note (NULL, NOTE_INSN_LOOP_END);
+ emit_note (NOTE_INSN_LOOP_END);
emit_label (end_lab);
emit_stack_probe (last_addr);
and 0 otherwise. */
rtx
-hard_function_value (valtype, func, outgoing)
- tree valtype;
- tree func ATTRIBUTE_UNUSED;
- int outgoing ATTRIBUTE_UNUSED;
+hard_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
+ int outgoing ATTRIBUTE_UNUSED)
{
rtx val;
in which a scalar value of mode MODE was returned by a library call. */
rtx
-hard_libcall_value (mode)
- enum machine_mode mode;
+hard_libcall_value (enum machine_mode mode)
{
return LIBCALL_VALUE (mode);
}
what `enum tree_code' means. */
int
-rtx_to_tree_code (code)
- enum rtx_code code;
+rtx_to_tree_code (enum rtx_code code)
{
enum tree_code tcode;