-/* Emit RTL for the GNU C-Compiler expander.
+/* Emit RTL for the GCC expander.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
REAL_VALUE_TYPE dconst0;
REAL_VALUE_TYPE dconst1;
REAL_VALUE_TYPE dconst2;
+REAL_VALUE_TYPE dconst3;
+REAL_VALUE_TYPE dconst10;
REAL_VALUE_TYPE dconstm1;
+REAL_VALUE_TYPE dconstm2;
+REAL_VALUE_TYPE dconsthalf;
+REAL_VALUE_TYPE dconstthird;
+REAL_VALUE_TYPE dconstpi;
+REAL_VALUE_TYPE dconste;
/* All references to the following fixed hard registers go through
these unique rtl objects. On machines where the frame-pointer and
In an inline procedure, the stack and frame pointer rtxs may not be
used for anything else. */
-rtx struct_value_rtx; /* (REG:Pmode STRUCT_VALUE_REGNUM) */
-rtx struct_value_incoming_rtx; /* (REG:Pmode STRUCT_VALUE_INCOMING_REGNUM) */
rtx static_chain_rtx; /* (REG:Pmode STATIC_CHAIN_REGNUM) */
rtx static_chain_incoming_rtx; /* (REG:Pmode STATIC_CHAIN_INCOMING_REGNUM) */
rtx pic_offset_table_rtx; /* (REG:Pmode PIC_OFFSET_TABLE_REGNUM) */
#define first_insn (cfun->emit->x_first_insn)
#define last_insn (cfun->emit->x_last_insn)
#define cur_insn_uid (cfun->emit->x_cur_insn_uid)
-#define last_linenum (cfun->emit->x_last_linenum)
-#define last_filename (cfun->emit->x_last_filename)
+#define last_location (cfun->emit->x_last_location)
#define first_label_num (cfun->emit->x_first_label_num)
-static rtx make_jump_insn_raw PARAMS ((rtx));
-static rtx make_call_insn_raw PARAMS ((rtx));
-static rtx find_line_note PARAMS ((rtx));
-static rtx change_address_1 PARAMS ((rtx, enum machine_mode, rtx,
- int));
-static void unshare_all_rtl_1 PARAMS ((rtx));
-static void unshare_all_decls PARAMS ((tree));
-static void reset_used_decls PARAMS ((tree));
-static void mark_label_nuses PARAMS ((rtx));
-static hashval_t const_int_htab_hash PARAMS ((const void *));
-static int const_int_htab_eq PARAMS ((const void *,
- const void *));
-static hashval_t const_double_htab_hash PARAMS ((const void *));
-static int const_double_htab_eq PARAMS ((const void *,
- const void *));
-static rtx lookup_const_double PARAMS ((rtx));
-static hashval_t mem_attrs_htab_hash PARAMS ((const void *));
-static int mem_attrs_htab_eq PARAMS ((const void *,
- const void *));
-static mem_attrs *get_mem_attrs PARAMS ((HOST_WIDE_INT, tree, rtx,
- rtx, unsigned int,
- enum machine_mode));
-static hashval_t reg_attrs_htab_hash PARAMS ((const void *));
-static int reg_attrs_htab_eq PARAMS ((const void *,
- const void *));
-static reg_attrs *get_reg_attrs PARAMS ((tree, int));
-static tree component_ref_for_mem_expr PARAMS ((tree));
-static rtx gen_const_vector_0 PARAMS ((enum machine_mode));
+static rtx make_jump_insn_raw (rtx);
+static rtx make_call_insn_raw (rtx);
+static rtx find_line_note (rtx);
+static rtx change_address_1 (rtx, enum machine_mode, rtx, int);
+static void unshare_all_rtl_1 (rtx);
+static void unshare_all_decls (tree);
+static void reset_used_decls (tree);
+static void mark_label_nuses (rtx);
+static hashval_t const_int_htab_hash (const void *);
+static int const_int_htab_eq (const void *, const void *);
+static hashval_t const_double_htab_hash (const void *);
+static int const_double_htab_eq (const void *, const void *);
+static rtx lookup_const_double (rtx);
+static hashval_t mem_attrs_htab_hash (const void *);
+static int mem_attrs_htab_eq (const void *, const void *);
+static mem_attrs *get_mem_attrs (HOST_WIDE_INT, tree, rtx, rtx, unsigned int,
+ enum machine_mode);
+static hashval_t reg_attrs_htab_hash (const void *);
+static int reg_attrs_htab_eq (const void *, const void *);
+static reg_attrs *get_reg_attrs (tree, int);
+static tree component_ref_for_mem_expr (tree);
+static rtx gen_const_vector_0 (enum machine_mode);
+static rtx gen_complex_constant_part (enum machine_mode, rtx, int);
/* Probability of the conditional branch currently proceeded by try_split.
Set to -1 otherwise. */
/* Returns a hash code for X (which is a really a CONST_INT). */
static hashval_t
-const_int_htab_hash (x)
- const void *x;
+const_int_htab_hash (const void *x)
{
- return (hashval_t) INTVAL ((struct rtx_def *) x);
+ return (hashval_t) INTVAL ((rtx) x);
}
/* Returns nonzero if the value represented by X (which is really a
HOST_WIDE_INT *). */
static int
-const_int_htab_eq (x, y)
- const void *x;
- const void *y;
+const_int_htab_eq (const void *x, const void *y)
{
return (INTVAL ((rtx) x) == *((const HOST_WIDE_INT *) y));
}
/* Returns a hash code for X (which is really a CONST_DOUBLE). */
static hashval_t
-const_double_htab_hash (x)
- const void *x;
+const_double_htab_hash (const void *x)
{
rtx value = (rtx) x;
hashval_t h;
h = CONST_DOUBLE_LOW (value) ^ CONST_DOUBLE_HIGH (value);
else
{
- h = real_hash (CONST_DOUBLE_REAL_VALUE (value));
+ h = real_hash (CONST_DOUBLE_REAL_VALUE (value));
/* MODE is used in the comparison, so it should be in the hash. */
h ^= GET_MODE (value);
}
/* Returns nonzero if the value represented by X (really a ...)
is the same as that represented by Y (really a ...) */
static int
-const_double_htab_eq (x, y)
- const void *x;
- const void *y;
+const_double_htab_eq (const void *x, const void *y)
{
rtx a = (rtx)x, b = (rtx)y;
/* Returns a hash code for X (which is a really a mem_attrs *). */
static hashval_t
-mem_attrs_htab_hash (x)
- const void *x;
+mem_attrs_htab_hash (const void *x)
{
mem_attrs *p = (mem_attrs *) x;
mem_attrs *). */
static int
-mem_attrs_htab_eq (x, y)
- const void *x;
- const void *y;
+mem_attrs_htab_eq (const void *x, const void *y)
{
mem_attrs *p = (mem_attrs *) x;
mem_attrs *q = (mem_attrs *) y;
MEM of mode MODE. */
static mem_attrs *
-get_mem_attrs (alias, expr, offset, size, align, mode)
- HOST_WIDE_INT alias;
- tree expr;
- rtx offset;
- rtx size;
- unsigned int align;
- enum machine_mode mode;
+get_mem_attrs (HOST_WIDE_INT alias, tree expr, rtx offset, rtx size,
+ unsigned int align, enum machine_mode mode)
{
mem_attrs attrs;
void **slot;
- /* If everything is the default, we can just return zero. */
+ /* If everything is the default, we can just return zero.
+ This must match what the corresponding MEM_* macros return when the
+ field is not present. */
if (alias == 0 && expr == 0 && offset == 0
&& (size == 0
|| (mode != BLKmode && GET_MODE_SIZE (mode) == INTVAL (size)))
- && (align == BITS_PER_UNIT
- || (STRICT_ALIGNMENT
- && mode != BLKmode && align == GET_MODE_ALIGNMENT (mode))))
+ && (STRICT_ALIGNMENT && mode != BLKmode
+ ? align == GET_MODE_ALIGNMENT (mode) : align == BITS_PER_UNIT))
return 0;
attrs.alias = alias;
/* Returns a hash code for X (which is a really a reg_attrs *). */
static hashval_t
-reg_attrs_htab_hash (x)
- const void *x;
+reg_attrs_htab_hash (const void *x)
{
reg_attrs *p = (reg_attrs *) x;
return ((p->offset * 1000) ^ (long) p->decl);
}
-/* Returns non-zero if the value represented by X (which is really a
+/* Returns nonzero if the value represented by X (which is really a
reg_attrs *) is the same as that given by Y (which is also really a
reg_attrs *). */
static int
-reg_attrs_htab_eq (x, y)
- const void *x;
- const void *y;
+reg_attrs_htab_eq (const void *x, const void *y)
{
reg_attrs *p = (reg_attrs *) x;
reg_attrs *q = (reg_attrs *) y;
MEM of mode MODE. */
static reg_attrs *
-get_reg_attrs (decl, offset)
- tree decl;
- int offset;
+get_reg_attrs (tree decl, int offset)
{
reg_attrs attrs;
void **slot;
frame_pointer_rtx). */
rtx
-gen_raw_REG (mode, regno)
- enum machine_mode mode;
- int regno;
+gen_raw_REG (enum machine_mode mode, int regno)
{
rtx x = gen_rtx_raw_REG (mode, regno);
ORIGINAL_REGNO (x) = regno;
special_rtx in gengenrtl.c as well. */
rtx
-gen_rtx_CONST_INT (mode, arg)
- enum machine_mode mode ATTRIBUTE_UNUSED;
- HOST_WIDE_INT arg;
+gen_rtx_CONST_INT (enum machine_mode mode ATTRIBUTE_UNUSED, HOST_WIDE_INT arg)
{
void **slot;
}
rtx
-gen_int_mode (c, mode)
- HOST_WIDE_INT c;
- enum machine_mode mode;
+gen_int_mode (HOST_WIDE_INT c, enum machine_mode mode)
{
return GEN_INT (trunc_int_for_mode (c, mode));
}
hash table. If so, return its counterpart; otherwise add it
to the hash table and return it. */
static rtx
-lookup_const_double (real)
- rtx real;
+lookup_const_double (rtx real)
{
void **slot = htab_find_slot (const_double_htab, real, INSERT);
if (*slot == 0)
/* Return a CONST_DOUBLE rtx for a floating-point value specified by
VALUE in mode MODE. */
rtx
-const_double_from_real_value (value, mode)
- REAL_VALUE_TYPE value;
- enum machine_mode mode;
+const_double_from_real_value (REAL_VALUE_TYPE value, enum machine_mode mode)
{
rtx real = rtx_alloc (CONST_DOUBLE);
PUT_MODE (real, mode);
REAL_VALUE_TYPE and use CONST_DOUBLE_FROM_REAL_VALUE. */
rtx
-immed_double_const (i0, i1, mode)
- HOST_WIDE_INT i0, i1;
- enum machine_mode mode;
+immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, enum machine_mode mode)
{
rtx value;
unsigned int i;
}
rtx
-gen_rtx_REG (mode, regno)
- enum machine_mode mode;
- unsigned int regno;
+gen_rtx_REG (enum machine_mode mode, unsigned int regno)
{
/* In case the MD file explicitly references the frame pointer, have
all such references point to the same frame pointer. This is
}
rtx
-gen_rtx_MEM (mode, addr)
- enum machine_mode mode;
- rtx addr;
+gen_rtx_MEM (enum machine_mode mode, rtx addr)
{
rtx rt = gen_rtx_raw_MEM (mode, addr);
}
rtx
-gen_rtx_SUBREG (mode, reg, offset)
- enum machine_mode mode;
- rtx reg;
- int offset;
+gen_rtx_SUBREG (enum machine_mode mode, rtx reg, int offset)
{
/* This is the most common failure type.
Catch it early so we can see who does it. */
is smaller than mode of REG, otherwise paradoxical SUBREG. */
rtx
-gen_lowpart_SUBREG (mode, reg)
- enum machine_mode mode;
- rtx reg;
+gen_lowpart_SUBREG (enum machine_mode mode, rtx reg)
{
enum machine_mode inmode;
/*VARARGS2*/
rtx
-gen_rtx VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
+gen_rtx (enum rtx_code code, enum machine_mode mode, ...)
{
int i; /* Array indices... */
const char *fmt; /* Current rtx's format... */
rtx rt_val; /* RTX to return to caller... */
+ va_list p;
- VA_OPEN (p, mode);
- VA_FIXEDARG (p, enum rtx_code, code);
- VA_FIXEDARG (p, enum machine_mode, mode);
+ va_start (p, mode);
switch (code)
{
{
switch (*fmt++)
{
- case '0': /* Unused field. */
+ case '0': /* Field with unknown use. Zero it. */
+ X0EXP (rt_val, i) = NULL_RTX;
break;
case 'i': /* An integer? */
break;
}
- VA_CLOSE (p);
+ va_end (p);
return rt_val;
}
/*VARARGS1*/
rtvec
-gen_rtvec VPARAMS ((int n, ...))
+gen_rtvec (int n, ...)
{
int i, save_n;
rtx *vector;
+ va_list p;
- VA_OPEN (p, n);
- VA_FIXEDARG (p, int, n);
+ va_start (p, n);
if (n == 0)
return NULL_RTVEC; /* Don't allocate an empty rtvec... */
- vector = (rtx *) alloca (n * sizeof (rtx));
+ vector = alloca (n * sizeof (rtx));
for (i = 0; i < n; i++)
vector[i] = va_arg (p, rtx);
/* The definition of VA_* in K&R C causes `n' to go out of scope. */
save_n = n;
- VA_CLOSE (p);
+ va_end (p);
return gen_rtvec_v (save_n, vector);
}
rtvec
-gen_rtvec_v (n, argp)
- int n;
- rtx *argp;
+gen_rtvec_v (int n, rtx *argp)
{
int i;
rtvec rt_val;
This pseudo is assigned the next sequential register number. */
rtx
-gen_reg_rtx (mode)
- enum machine_mode mode;
+gen_reg_rtx (enum machine_mode mode)
{
struct function *f = cfun;
rtx val;
memset (new + old_size, 0, old_size);
f->emit->regno_pointer_align = (unsigned char *) new;
- new1 = (rtx *) ggc_realloc (f->emit->x_regno_reg_rtx,
- old_size * 2 * sizeof (rtx));
+ new1 = ggc_realloc (f->emit->x_regno_reg_rtx,
+ old_size * 2 * sizeof (rtx));
memset (new1 + old_size, 0, old_size * sizeof (rtx));
regno_reg_rtx = new1;
return val;
}
-/* Generate an register with same attributes as REG,
+/* Generate a register with same attributes as REG,
but offsetted by OFFSET. */
rtx
-gen_rtx_REG_offset (reg, mode, regno, offset)
- enum machine_mode mode;
- unsigned int regno;
- int offset;
- rtx reg;
+gen_rtx_REG_offset (rtx reg, enum machine_mode mode, unsigned int regno, int offset)
{
rtx new = gen_rtx_REG (mode, regno);
REG_ATTRS (new) = get_reg_attrs (REG_EXPR (reg),
- REG_OFFSET (reg) + offset);
+ REG_OFFSET (reg) + offset);
return new;
}
/* Set the decl for MEM to DECL. */
void
-set_reg_attrs_from_mem (reg, mem)
- rtx reg;
- rtx mem;
+set_reg_attrs_from_mem (rtx reg, rtx mem)
{
if (MEM_OFFSET (mem) && GET_CODE (MEM_OFFSET (mem)) == CONST_INT)
REG_ATTRS (reg)
Use needed values from memory attributes of MEM. */
void
-set_reg_attrs_for_parm (parm_rtx, mem)
- rtx parm_rtx;
- rtx mem;
+set_reg_attrs_for_parm (rtx parm_rtx, rtx mem)
{
if (GET_CODE (parm_rtx) == REG)
set_reg_attrs_from_mem (parm_rtx, mem);
/* Assign the RTX X to declaration T. */
void
-set_decl_rtl (t, x)
- tree t;
- rtx x;
+set_decl_rtl (tree t, rtx x)
{
DECL_CHECK (t)->decl.rtl = x;
if (!x)
return;
- /* For register, we maitain the reverse information too. */
+ /* For register, we maintain the reverse information too. */
if (GET_CODE (x) == REG)
REG_ATTRS (x) = get_reg_attrs (t, 0);
else if (GET_CODE (x) == SUBREG)
/* Identify REG (which may be a CONCAT) as a user register. */
void
-mark_user_reg (reg)
- rtx reg;
+mark_user_reg (rtx reg)
{
if (GET_CODE (reg) == CONCAT)
{
as ALIGN, if nonzero. */
void
-mark_reg_pointer (reg, align)
- rtx reg;
- int align;
+mark_reg_pointer (rtx reg, int align)
{
if (! REG_POINTER (reg))
{
/* Return 1 plus largest pseudo reg number used in the current function. */
int
-max_reg_num ()
+max_reg_num (void)
{
return reg_rtx_no;
}
/* Return 1 + the largest label number used so far in the current function. */
int
-max_label_num ()
+max_label_num (void)
{
if (last_label_num && label_num == base_label_num)
return last_label_num;
/* Return first label number used in this function (if any were used). */
int
-get_first_label_num ()
+get_first_label_num (void)
{
return first_label_num;
}
/* Return the final regno of X, which is a SUBREG of a hard
register. */
int
-subreg_hard_regno (x, check_mode)
- rtx x;
- int check_mode;
+subreg_hard_regno (rtx x, int check_mode)
{
enum machine_mode mode = GET_MODE (x);
unsigned int byte_offset, base_regno, final_regno;
abort ();
if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort ();
-
+#ifdef ENABLE_CHECKING
+ if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
+ SUBREG_BYTE (x), mode))
+ abort ();
+#endif
/* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
If this is not a case we can handle, return 0. */
rtx
-gen_lowpart_common (mode, x)
- enum machine_mode mode;
- rtx x;
+gen_lowpart_common (enum machine_mode mode, rtx x)
{
int msize = GET_MODE_SIZE (mode);
int xsize = GET_MODE_SIZE (GET_MODE (x));
else if (GET_CODE (x) == SUBREG || GET_CODE (x) == REG
|| GET_CODE (x) == CONCAT || GET_CODE (x) == CONST_VECTOR)
return simplify_gen_subreg (mode, x, GET_MODE (x), offset);
- else if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
- || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
- && GET_MODE (x) == VOIDmode)
+ else if (VECTOR_MODE_P (mode) && GET_MODE (x) == VOIDmode)
return simplify_gen_subreg (mode, x, int_mode_for_mode (mode), offset);
/* If X is a CONST_INT or a CONST_DOUBLE, extract the appropriate bits
from the low-order part of the constant. */
mode);
#endif
}
+ /* If MODE is a condition code and X is a CONST_INT, the value of X
+ must already have been "recognized" by the back-end, and we can
+ assume that it is valid for this mode. */
+ else if (GET_MODE_CLASS (mode) == MODE_CC
+ && GET_CODE (x) == CONST_INT)
+ return x;
/* Otherwise, we can't do this. */
return 0;
}
\f
+/* Return the constant real or imaginary part (which has mode MODE)
+ of a complex value X. The IMAGPART_P argument determines whether
+ the real or complex component should be returned. This function
+ returns NULL_RTX if the component isn't a constant. */
+
+static rtx
+gen_complex_constant_part (enum machine_mode mode, rtx x, int imagpart_p)
+{
+ tree decl, part;
+
+ if (GET_CODE (x) == MEM
+ && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
+ {
+ decl = SYMBOL_REF_DECL (XEXP (x, 0));
+ if (decl != NULL_TREE && TREE_CODE (decl) == COMPLEX_CST)
+ {
+ part = imagpart_p ? TREE_IMAGPART (decl) : TREE_REALPART (decl);
+ if (TREE_CODE (part) == REAL_CST
+ || TREE_CODE (part) == INTEGER_CST)
+ return expand_expr (part, NULL_RTX, mode, 0);
+ }
+ }
+ return NULL_RTX;
+}
+
/* Return the real part (which has mode MODE) of a complex value X.
This always comes at the low address in memory. */
rtx
-gen_realpart (mode, x)
- enum machine_mode mode;
- rtx x;
+gen_realpart (enum machine_mode mode, rtx x)
{
+ rtx part;
+
+ /* Handle complex constants. */
+ part = gen_complex_constant_part (mode, x, 0);
+ if (part != NULL_RTX)
+ return part;
+
if (WORDS_BIG_ENDIAN
&& GET_MODE_BITSIZE (mode) < BITS_PER_WORD
&& REG_P (x)
This always comes at the high address in memory. */
rtx
-gen_imagpart (mode, x)
- enum machine_mode mode;
- rtx x;
+gen_imagpart (enum machine_mode mode, rtx x)
{
+ rtx part;
+
+ /* Handle complex constants. */
+ part = gen_complex_constant_part (mode, x, 1);
+ if (part != NULL_RTX)
+ return part;
+
if (WORDS_BIG_ENDIAN)
return gen_lowpart (mode, x);
else if (! WORDS_BIG_ENDIAN
regardless of WORDS_BIG_ENDIAN. */
int
-subreg_realpart_p (x)
- rtx x;
+subreg_realpart_p (rtx x)
{
if (GET_CODE (x) != SUBREG)
abort ();
If X is a MEM whose address is a QUEUED, the value may be so also. */
rtx
-gen_lowpart (mode, x)
- enum machine_mode mode;
- rtx x;
+gen_lowpart (enum machine_mode mode, rtx x)
{
rtx result = gen_lowpart_common (mode, x);
/* The following exposes the use of "x" to CSE. */
if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
+ && SCALAR_INT_MODE_P (GET_MODE (x))
&& ! no_new_pseudos)
return gen_lowpart (mode, force_reg (GET_MODE (x), x));
This is used to access the imaginary part of a complex number. */
rtx
-gen_highpart (mode, x)
- enum machine_mode mode;
- rtx x;
+gen_highpart (enum machine_mode mode, rtx x)
{
unsigned int msize = GET_MODE_SIZE (mode);
rtx result;
/* Like gen_highpart, but accept mode of EXP operand in case EXP can
be VOIDmode constant. */
rtx
-gen_highpart_mode (outermode, innermode, exp)
- enum machine_mode outermode, innermode;
- rtx exp;
+gen_highpart_mode (enum machine_mode outermode, enum machine_mode innermode, rtx exp)
{
if (GET_MODE (exp) != VOIDmode)
{
of the value in mode INNERMODE stored in memory in target format. */
unsigned int
-subreg_lowpart_offset (outermode, innermode)
- enum machine_mode outermode, innermode;
+subreg_lowpart_offset (enum machine_mode outermode, enum machine_mode innermode)
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
/* Return offset in bytes to get OUTERMODE high part
of the value in mode INNERMODE stored in memory in target format. */
unsigned int
-subreg_highpart_offset (outermode, innermode)
- enum machine_mode outermode, innermode;
+subreg_highpart_offset (enum machine_mode outermode, enum machine_mode innermode)
{
unsigned int offset = 0;
int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
If X is not a SUBREG, always return 1 (it is its own low part!). */
int
-subreg_lowpart_p (x)
- rtx x;
+subreg_lowpart_p (rtx x)
{
if (GET_CODE (x) != SUBREG)
return 1;
Some places invoke this directly. */
rtx
-constant_subword (op, offset, mode)
- rtx op;
- int offset;
- enum machine_mode mode;
+constant_subword (rtx op, int offset, enum machine_mode mode)
{
int size_ratio = HOST_BITS_PER_WIDE_INT / BITS_PER_WORD;
HOST_WIDE_INT val;
*/
rtx
-operand_subword (op, offset, validate_address, mode)
- rtx op;
- unsigned int offset;
- int validate_address;
- enum machine_mode mode;
+operand_subword (rtx op, unsigned int offset, int validate_address, enum machine_mode mode)
{
if (mode == VOIDmode)
mode = GET_MODE (op);
MODE is the mode of OP, in case it is CONST_INT. */
rtx
-operand_subword_force (op, offset, mode)
- rtx op;
- unsigned int offset;
- enum machine_mode mode;
+operand_subword_force (rtx op, unsigned int offset, enum machine_mode mode)
{
rtx result = operand_subword (op, offset, 1, mode);
A test instruction is changed into a compare of 0 against the operand. */
void
-reverse_comparison (insn)
- rtx insn;
+reverse_comparison (rtx insn)
{
rtx body = PATTERN (insn);
rtx comp;
a NULL expression. */
static tree
-component_ref_for_mem_expr (ref)
- tree ref;
+component_ref_for_mem_expr (tree ref)
{
tree inner = TREE_OPERAND (ref, 0);
there is an offset outstanding on T that will be applied later. */
void
-set_mem_attributes_minus_bitpos (ref, t, objectp, bitpos)
- rtx ref;
- tree t;
- int objectp;
- HOST_WIDE_INT bitpos;
+set_mem_attributes_minus_bitpos (rtx ref, tree t, int objectp,
+ HOST_WIDE_INT bitpos)
{
HOST_WIDE_INT alias = MEM_ALIAS_SET (ref);
tree expr = MEM_EXPR (ref);
else if (TREE_CODE (t) == ARRAY_REF)
{
tree off_tree = size_zero_node;
+ /* We can't modify t, because we use it at the end of the
+ function. */
+ tree t2 = t;
do
{
- tree index = TREE_OPERAND (t, 1);
- tree array = TREE_OPERAND (t, 0);
+ tree index = TREE_OPERAND (t2, 1);
+ tree array = TREE_OPERAND (t2, 0);
tree domain = TYPE_DOMAIN (TREE_TYPE (array));
tree low_bound = (domain ? TYPE_MIN_VALUE (domain) : 0);
tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (array)));
/* If the index has a self-referential type, pass it to a
WITH_RECORD_EXPR; if the component size is, pass our
component to one. */
- if (! TREE_CONSTANT (index)
- && contains_placeholder_p (index))
- index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t);
- if (! TREE_CONSTANT (unit_size)
- && contains_placeholder_p (unit_size))
+ if (CONTAINS_PLACEHOLDER_P (index))
+ index = build (WITH_RECORD_EXPR, TREE_TYPE (index), index, t2);
+ if (CONTAINS_PLACEHOLDER_P (unit_size))
unit_size = build (WITH_RECORD_EXPR, sizetype,
unit_size, array);
index,
unit_size)),
off_tree));
- t = TREE_OPERAND (t, 0);
+ t2 = TREE_OPERAND (t2, 0);
}
- while (TREE_CODE (t) == ARRAY_REF);
+ while (TREE_CODE (t2) == ARRAY_REF);
- if (DECL_P (t))
+ if (DECL_P (t2))
{
- expr = t;
+ expr = t2;
offset = NULL;
if (host_integerp (off_tree, 1))
{
HOST_WIDE_INT ioff = tree_low_cst (off_tree, 1);
HOST_WIDE_INT aoff = (ioff & -ioff) * BITS_PER_UNIT;
- align = DECL_ALIGN (t);
+ align = DECL_ALIGN (t2);
if (aoff && (unsigned HOST_WIDE_INT) aoff < align)
align = aoff;
offset = GEN_INT (ioff);
apply_bitpos = bitpos;
}
}
- else if (TREE_CODE (t) == COMPONENT_REF)
+ else if (TREE_CODE (t2) == COMPONENT_REF)
{
- expr = component_ref_for_mem_expr (t);
+ expr = component_ref_for_mem_expr (t2);
if (host_integerp (off_tree, 1))
{
offset = GEN_INT (tree_low_cst (off_tree, 1));
the size we got from the type? */
}
else if (flag_argument_noalias > 1
- && TREE_CODE (t) == INDIRECT_REF
- && TREE_CODE (TREE_OPERAND (t, 0)) == PARM_DECL)
+ && TREE_CODE (t2) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (t2, 0)) == PARM_DECL)
{
- expr = t;
+ expr = t2;
offset = NULL;
}
}
}
}
- /* If we modified OFFSET based on T, then subtract the outstanding
+ /* If we modified OFFSET based on T, then subtract the outstanding
bit position offset. Similarly, increase the size of the accessed
object to contain the negative offset. */
if (apply_bitpos)
}
void
-set_mem_attributes (ref, t, objectp)
- rtx ref;
- tree t;
- int objectp;
+set_mem_attributes (rtx ref, tree t, int objectp)
{
set_mem_attributes_minus_bitpos (ref, t, objectp, 0);
}
/* Set the decl for MEM to DECL. */
void
-set_mem_attrs_from_reg (mem, reg)
- rtx mem;
- rtx reg;
+set_mem_attrs_from_reg (rtx mem, rtx reg)
{
MEM_ATTRS (mem)
= get_mem_attrs (MEM_ALIAS_SET (mem), REG_EXPR (reg),
/* Set the alias set of MEM to SET. */
void
-set_mem_alias_set (mem, set)
- rtx mem;
- HOST_WIDE_INT set;
+set_mem_alias_set (rtx mem, HOST_WIDE_INT set)
{
#ifdef ENABLE_CHECKING
/* If the new and old alias sets don't conflict, something is wrong. */
/* Set the alignment of MEM to ALIGN bits. */
void
-set_mem_align (mem, align)
- rtx mem;
- unsigned int align;
+set_mem_align (rtx mem, unsigned int align)
{
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
MEM_OFFSET (mem), MEM_SIZE (mem), align,
/* Set the expr for MEM to EXPR. */
void
-set_mem_expr (mem, expr)
- rtx mem;
- tree expr;
+set_mem_expr (rtx mem, tree expr)
{
MEM_ATTRS (mem)
= get_mem_attrs (MEM_ALIAS_SET (mem), expr, MEM_OFFSET (mem),
/* Set the offset of MEM to OFFSET. */
void
-set_mem_offset (mem, offset)
- rtx mem, offset;
+set_mem_offset (rtx mem, rtx offset)
{
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
offset, MEM_SIZE (mem), MEM_ALIGN (mem),
/* Set the size of MEM to SIZE. */
void
-set_mem_size (mem, size)
- rtx mem, size;
+set_mem_size (rtx mem, rtx size)
{
MEM_ATTRS (mem) = get_mem_attrs (MEM_ALIAS_SET (mem), MEM_EXPR (mem),
MEM_OFFSET (mem), size, MEM_ALIGN (mem),
attributes are not changed. */
static rtx
-change_address_1 (memref, mode, addr, validate)
- rtx memref;
- enum machine_mode mode;
- rtx addr;
- int validate;
+change_address_1 (rtx memref, enum machine_mode mode, rtx addr, int validate)
{
rtx new;
way we are changing MEMREF, so we only preserve the alias set. */
rtx
-change_address (memref, mode, addr)
- rtx memref;
- enum machine_mode mode;
- rtx addr;
+change_address (rtx memref, enum machine_mode mode, rtx addr)
{
rtx new = change_address_1 (memref, mode, addr, 1);
enum machine_mode mmode = GET_MODE (new);
and caller is responsible for adjusting MEMREF base register. */
rtx
-adjust_address_1 (memref, mode, offset, validate, adjust)
- rtx memref;
- enum machine_mode mode;
- HOST_WIDE_INT offset;
- int validate, adjust;
+adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
+ int validate, int adjust)
{
rtx addr = XEXP (memref, 0);
rtx new;
nonzero, the memory address is forced to be valid. */
rtx
-adjust_automodify_address_1 (memref, mode, addr, offset, validate)
- rtx memref;
- enum machine_mode mode;
- rtx addr;
- HOST_WIDE_INT offset;
- int validate;
+adjust_automodify_address_1 (rtx memref, enum machine_mode mode, rtx addr,
+ HOST_WIDE_INT offset, int validate)
{
memref = change_address_1 (memref, VOIDmode, addr, validate);
return adjust_address_1 (memref, mode, offset, validate, 0);
known to be in OFFSET (possibly 1). */
rtx
-offset_address (memref, offset, pow2)
- rtx memref;
- rtx offset;
- HOST_WIDE_INT pow2;
+offset_address (rtx memref, rtx offset, unsigned HOST_WIDE_INT pow2)
{
rtx new, addr = XEXP (memref, 0);
new = simplify_gen_binary (PLUS, Pmode, addr, offset);
/* At this point we don't know _why_ the address is invalid. It
- could have secondary memory refereces, multiplies or anything.
+ could have secondary memory references, multiplies or anything.
However, if we did go and rearrange things, we can wind up not
being able to recognize the magic around pic_offset_table_rtx.
we don't know. */
MEM_ATTRS (new)
= get_mem_attrs (MEM_ALIAS_SET (memref), MEM_EXPR (memref), 0, 0,
- MIN (MEM_ALIGN (memref),
- (unsigned HOST_WIDE_INT) pow2 * BITS_PER_UNIT),
+ MIN (MEM_ALIGN (memref), pow2 * BITS_PER_UNIT),
GET_MODE (new));
return new;
}
by putting something into a register. */
rtx
-replace_equiv_address (memref, addr)
- rtx memref;
- rtx addr;
+replace_equiv_address (rtx memref, rtx addr)
{
/* change_address_1 copies the memory attribute structure without change
and that's exactly what we want here. */
/* Likewise, but the reference is not required to be valid. */
rtx
-replace_equiv_address_nv (memref, addr)
- rtx memref;
- rtx addr;
+replace_equiv_address_nv (rtx memref, rtx addr)
{
return change_address_1 (memref, VOIDmode, addr, 0);
}
operations plus masking logic. */
rtx
-widen_memory_access (memref, mode, offset)
- rtx memref;
- enum machine_mode mode;
- HOST_WIDE_INT offset;
+widen_memory_access (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset)
{
rtx new = adjust_address_1 (memref, mode, offset, 1, 1);
tree expr = MEM_EXPR (new);
/* Return a newly created CODE_LABEL rtx with a unique label number. */
rtx
-gen_label_rtx ()
+gen_label_rtx (void)
{
return gen_rtx_CODE_LABEL (VOIDmode, 0, NULL_RTX, NULL_RTX,
- NULL, label_num++, NULL);
+ NULL, label_num++, NULL);
}
\f
/* For procedure integration. */
Used for an inline-procedure after copying the insn chain. */
void
-set_new_first_and_last_insn (first, last)
- rtx first, last;
+set_new_first_and_last_insn (rtx first, rtx last)
{
rtx insn;
This is used when belatedly compiling an inline function. */
void
-set_new_first_and_last_label_num (first, last)
- int first, last;
+set_new_first_and_last_label_num (int first, int last)
{
base_label_num = label_num;
first_label_num = first;
This is used when belatedly compiling an inline function. */
void
-set_new_last_label_num (last)
- int last;
+set_new_last_label_num (int last)
{
base_label_num = label_num;
last_label_num = last;
This is used after a nested function. */
void
-restore_emit_status (p)
- struct function *p ATTRIBUTE_UNUSED;
+restore_emit_status (struct function *p ATTRIBUTE_UNUSED)
{
last_label_num = 0;
}
structure. This routine should only be called once. */
void
-unshare_all_rtl (fndecl, insn)
- tree fndecl;
- rtx insn;
+unshare_all_rtl (tree fndecl, rtx insn)
{
tree decl;
should be done sparingly. */
void
-unshare_all_rtl_again (insn)
- rtx insn;
+unshare_all_rtl_again (rtx insn)
{
rtx p;
tree decl;
Assumes the mark bits are cleared at entry. */
static void
-unshare_all_rtl_1 (insn)
- rtx insn;
+unshare_all_rtl_1 (rtx insn)
{
for (; insn; insn = NEXT_INSN (insn))
if (INSN_P (insn))
/* Go through all virtual stack slots of a function and copy any
shared structure. */
static void
-unshare_all_decls (blk)
- tree blk;
+unshare_all_decls (tree blk)
{
tree t;
/* Go through all virtual stack slots of a function and mark them as
not shared. */
static void
-reset_used_decls (blk)
- tree blk;
+reset_used_decls (tree blk)
{
tree t;
either a MEM of an EXPR_LIST of MEMs. */
rtx
-copy_most_rtx (orig, may_share)
- rtx orig;
- rtx may_share;
+copy_most_rtx (rtx orig, rtx may_share)
{
rtx copy;
int i, j;
break;
case '0':
- /* Copy this through the wide int field; that's safest. */
- X0WINT (copy, i) = X0WINT (orig, i);
+ X0ANY (copy, i) = X0ANY (orig, i);
break;
default:
Recursively does the same for subexpressions. */
rtx
-copy_rtx_if_shared (orig)
- rtx orig;
+copy_rtx_if_shared (rtx orig)
{
rtx x = orig;
int i;
rtx copy;
copy = rtx_alloc (code);
- memcpy (copy, x,
- (sizeof (*copy) - sizeof (copy->fld)
- + sizeof (copy->fld[0]) * GET_RTX_LENGTH (code)));
+ memcpy (copy, x, RTX_SIZE (code));
x = copy;
copied = 1;
}
to look for shared sub-parts. */
void
-reset_used_flags (x)
- rtx x;
+reset_used_flags (rtx x)
{
int i, j;
enum rtx_code code;
OTHER must be valid as a SET_DEST. */
rtx
-make_safe_from (x, other)
- rtx x, other;
+make_safe_from (rtx x, rtx other)
{
while (1)
switch (GET_CODE (other))
/* Return the first insn of the current sequence or current function. */
rtx
-get_insns ()
+get_insns (void)
{
return first_insn;
}
/* Specify a new insn as the first in the chain. */
void
-set_first_insn (insn)
- rtx insn;
+set_first_insn (rtx insn)
{
if (PREV_INSN (insn) != 0)
abort ();
/* Return the last insn emitted in current sequence or current function. */
rtx
-get_last_insn ()
+get_last_insn (void)
{
return last_insn;
}
/* Specify a new insn as the last in the chain. */
void
-set_last_insn (insn)
- rtx insn;
+set_last_insn (rtx insn)
{
if (NEXT_INSN (insn) != 0)
abort ();
/* Return the last insn emitted, even if it is in a sequence now pushed. */
rtx
-get_last_insn_anywhere ()
+get_last_insn_anywhere (void)
{
struct sequence_stack *stack;
if (last_insn)
function. This routine looks inside SEQUENCEs. */
rtx
-get_first_nonnote_insn ()
+get_first_nonnote_insn (void)
{
rtx insn = first_insn;
function. This routine looks inside SEQUENCEs. */
rtx
-get_last_nonnote_insn ()
+get_last_nonnote_insn (void)
{
rtx insn = last_insn;
/* Return a number larger than any instruction's uid in this function. */
int
-get_max_uid ()
+get_max_uid (void)
{
return cur_insn_uid;
}
/* Renumber instructions so that no instruction UIDs are wasted. */
void
-renumber_insns (stream)
- FILE *stream;
+renumber_insns (FILE *stream)
{
rtx insn;
of the sequence. */
rtx
-next_insn (insn)
- rtx insn;
+next_insn (rtx insn)
{
if (insn)
{
of the sequence. */
rtx
-previous_insn (insn)
- rtx insn;
+previous_insn (rtx insn)
{
if (insn)
{
look inside SEQUENCEs. */
rtx
-next_nonnote_insn (insn)
- rtx insn;
+next_nonnote_insn (rtx insn)
{
while (insn)
{
not look inside SEQUENCEs. */
rtx
-prev_nonnote_insn (insn)
- rtx insn;
+prev_nonnote_insn (rtx insn)
{
while (insn)
{
SEQUENCEs. */
rtx
-next_real_insn (insn)
- rtx insn;
+next_real_insn (rtx insn)
{
while (insn)
{
SEQUENCEs. */
rtx
-prev_real_insn (insn)
- rtx insn;
+prev_real_insn (rtx insn)
{
while (insn)
{
return insn;
}
+/* Return the last CALL_INSN in the current list, or 0 if there is none.
+ This routine does not look inside SEQUENCEs. */
+
+rtx
+last_call_insn (void)
+{
+ rtx insn;
+
+ for (insn = get_last_insn ();
+ insn && GET_CODE (insn) != CALL_INSN;
+ insn = PREV_INSN (insn))
+ ;
+
+ return insn;
+}
+
/* Find the next insn after INSN that really does something. This routine
does not look inside SEQUENCEs. Until reload has completed, this is the
same as next_real_insn. */
int
-active_insn_p (insn)
- rtx insn;
+active_insn_p (rtx insn)
{
return (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN
|| (GET_CODE (insn) == INSN
}
rtx
-next_active_insn (insn)
- rtx insn;
+next_active_insn (rtx insn)
{
while (insn)
{
same as prev_real_insn. */
rtx
-prev_active_insn (insn)
- rtx insn;
+prev_active_insn (rtx insn)
{
while (insn)
{
/* Return the next CODE_LABEL after the insn INSN, or 0 if there is none. */
rtx
-next_label (insn)
- rtx insn;
+next_label (rtx insn)
{
while (insn)
{
/* Return the last CODE_LABEL before the insn INSN, or 0 if there is none. */
rtx
-prev_label (insn)
- rtx insn;
+prev_label (rtx insn)
{
while (insn)
{
and REG_CC_USER notes so we can find it. */
void
-link_cc0_insns (insn)
- rtx insn;
+link_cc0_insns (rtx insn)
{
rtx user = next_nonnote_insn (insn);
Return 0 if we can't find the insn. */
rtx
-next_cc0_user (insn)
- rtx insn;
+next_cc0_user (rtx insn)
{
rtx note = find_reg_note (insn, REG_CC_USER, NULL_RTX);
note, it is the previous insn. */
rtx
-prev_cc0_setter (insn)
- rtx insn;
+prev_cc0_setter (rtx insn)
{
rtx note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX);
/* Increment the label uses for all labels present in rtx. */
static void
-mark_label_nuses (x)
- rtx x;
+mark_label_nuses (rtx x)
{
enum rtx_code code;
int i, j;
returns TRIAL. If the insn to be returned can be split, it will be. */
rtx
-try_split (pat, trial, last)
- rtx pat, trial;
- int last;
+try_split (rtx pat, rtx trial, int last)
{
rtx before = PREV_INSN (trial);
rtx after = NEXT_INSN (trial);
rtx tem;
rtx note, seq;
int probability;
+ rtx insn_last, insn;
+ int njumps = 0;
if (any_condjump_p (trial)
&& (note = find_reg_note (trial, REG_BR_PROB, 0)))
after = NEXT_INSN (after);
}
- if (seq)
+ if (!seq)
+ return trial;
+
+ /* Avoid infinite loop if any insn of the result matches
+ the original pattern. */
+ insn_last = seq;
+ while (1)
{
- /* Sometimes there will be only one insn in that list, this case will
- normally arise only when we want it in turn to be split (SFmode on
- the 29k is an example). */
- if (NEXT_INSN (seq) != NULL_RTX)
- {
- rtx insn_last, insn;
- int njumps = 0;
+ if (INSN_P (insn_last)
+ && rtx_equal_p (PATTERN (insn_last), pat))
+ return trial;
+ if (!NEXT_INSN (insn_last))
+ break;
+ insn_last = NEXT_INSN (insn_last);
+ }
- /* Avoid infinite loop if any insn of the result matches
- the original pattern. */
- insn_last = seq;
- while (1)
+ /* Mark labels. */
+ for (insn = insn_last; insn ; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) == JUMP_INSN)
+ {
+ mark_jump_label (PATTERN (insn), insn, 0);
+ njumps++;
+ if (probability != -1
+ && any_condjump_p (insn)
+ && !find_reg_note (insn, REG_BR_PROB, 0))
{
- if (INSN_P (insn_last)
- && rtx_equal_p (PATTERN (insn_last), pat))
- return trial;
- if (NEXT_INSN (insn_last) == NULL_RTX)
- break;
- insn_last = NEXT_INSN (insn_last);
+ /* We can preserve the REG_BR_PROB notes only if exactly
+ one jump is created, otherwise the machine description
+ is responsible for this step using
+ split_branch_probability variable. */
+ if (njumps != 1)
+ abort ();
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_BR_PROB,
+ GEN_INT (probability),
+ REG_NOTES (insn));
}
+ }
+ }
+
+ /* If we are splitting a CALL_INSN, look for the CALL_INSN
+ in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
+ if (GET_CODE (trial) == CALL_INSN)
+ {
+ for (insn = insn_last; insn ; insn = PREV_INSN (insn))
+ if (GET_CODE (insn) == CALL_INSN)
+ {
+ rtx *p = &CALL_INSN_FUNCTION_USAGE (insn);
+ while (*p)
+ p = &XEXP (*p, 1);
+ *p = CALL_INSN_FUNCTION_USAGE (trial);
+ SIBLING_CALL_P (insn) = SIBLING_CALL_P (trial);
+ }
+ }
- /* Mark labels. */
+ /* Copy notes, particularly those related to the CFG. */
+ for (note = REG_NOTES (trial); note; note = XEXP (note, 1))
+ {
+ switch (REG_NOTE_KIND (note))
+ {
+ case REG_EH_REGION:
insn = insn_last;
while (insn != NULL_RTX)
{
- if (GET_CODE (insn) == JUMP_INSN)
- {
- mark_jump_label (PATTERN (insn), insn, 0);
- njumps++;
- if (probability != -1
- && any_condjump_p (insn)
- && !find_reg_note (insn, REG_BR_PROB, 0))
- {
- /* We can preserve the REG_BR_PROB notes only if exactly
- one jump is created, otherwise the machine description
- is responsible for this step using
- split_branch_probability variable. */
- if (njumps != 1)
- abort ();
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_BR_PROB,
- GEN_INT (probability),
- REG_NOTES (insn));
- }
- }
-
+ if (GET_CODE (insn) == CALL_INSN
+ || (flag_non_call_exceptions
+ && may_trap_p (PATTERN (insn))))
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_EH_REGION,
+ XEXP (note, 0),
+ REG_NOTES (insn));
insn = PREV_INSN (insn);
}
+ break;
- /* If we are splitting a CALL_INSN, look for the CALL_INSN
- in SEQ and copy our CALL_INSN_FUNCTION_USAGE to it. */
- if (GET_CODE (trial) == CALL_INSN)
+ case REG_NORETURN:
+ case REG_SETJMP:
+ case REG_ALWAYS_RETURN:
+ insn = insn_last;
+ while (insn != NULL_RTX)
{
- insn = insn_last;
- while (insn != NULL_RTX)
- {
- if (GET_CODE (insn) == CALL_INSN)
- CALL_INSN_FUNCTION_USAGE (insn)
- = CALL_INSN_FUNCTION_USAGE (trial);
-
- insn = PREV_INSN (insn);
- }
+ if (GET_CODE (insn) == CALL_INSN)
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
+ XEXP (note, 0),
+ REG_NOTES (insn));
+ insn = PREV_INSN (insn);
}
+ break;
- /* Copy notes, particularly those related to the CFG. */
- for (note = REG_NOTES (trial); note; note = XEXP (note, 1))
+ case REG_NON_LOCAL_GOTO:
+ insn = insn_last;
+ while (insn != NULL_RTX)
{
- switch (REG_NOTE_KIND (note))
- {
- case REG_EH_REGION:
- insn = insn_last;
- while (insn != NULL_RTX)
- {
- if (GET_CODE (insn) == CALL_INSN
- || (flag_non_call_exceptions
- && may_trap_p (PATTERN (insn))))
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_EH_REGION,
- XEXP (note, 0),
- REG_NOTES (insn));
- insn = PREV_INSN (insn);
- }
- break;
-
- case REG_NORETURN:
- case REG_SETJMP:
- case REG_ALWAYS_RETURN:
- insn = insn_last;
- while (insn != NULL_RTX)
- {
- if (GET_CODE (insn) == CALL_INSN)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
- XEXP (note, 0),
- REG_NOTES (insn));
- insn = PREV_INSN (insn);
- }
- break;
-
- case REG_NON_LOCAL_GOTO:
- insn = insn_last;
- while (insn != NULL_RTX)
- {
- if (GET_CODE (insn) == JUMP_INSN)
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
- XEXP (note, 0),
- REG_NOTES (insn));
- insn = PREV_INSN (insn);
- }
- break;
-
- default:
- break;
- }
+ if (GET_CODE (insn) == JUMP_INSN)
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_NOTE_KIND (note),
+ XEXP (note, 0),
+ REG_NOTES (insn));
+ insn = PREV_INSN (insn);
}
+ break;
- /* If there are LABELS inside the split insns increment the
- usage count so we don't delete the label. */
- if (GET_CODE (trial) == INSN)
- {
- insn = insn_last;
- while (insn != NULL_RTX)
- {
- if (GET_CODE (insn) == INSN)
- mark_label_nuses (PATTERN (insn));
+ default:
+ break;
+ }
+ }
- insn = PREV_INSN (insn);
- }
- }
+ /* If there are LABELS inside the split insns increment the
+ usage count so we don't delete the label. */
+ if (GET_CODE (trial) == INSN)
+ {
+ insn = insn_last;
+ while (insn != NULL_RTX)
+ {
+ if (GET_CODE (insn) == INSN)
+ mark_label_nuses (PATTERN (insn));
- tem = emit_insn_after_scope (seq, trial, INSN_SCOPE (trial));
+ insn = PREV_INSN (insn);
+ }
+ }
- delete_insn (trial);
- if (has_barrier)
- emit_barrier_after (tem);
+ tem = emit_insn_after_setloc (seq, trial, INSN_LOCATOR (trial));
- /* Recursively call try_split for each new insn created; by the
- time control returns here that insn will be fully split, so
- set LAST and continue from the insn after the one returned.
- We can't use next_active_insn here since AFTER may be a note.
- Ignore deleted insns, which can be occur if not optimizing. */
- for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem))
- if (! INSN_DELETED_P (tem) && INSN_P (tem))
- tem = try_split (PATTERN (tem), tem, 1);
- }
- /* Avoid infinite loop if the result matches the original pattern. */
- else if (rtx_equal_p (PATTERN (seq), pat))
- return trial;
- else
- {
- PATTERN (trial) = PATTERN (seq);
- INSN_CODE (trial) = -1;
- try_split (PATTERN (trial), trial, last);
- }
+ delete_insn (trial);
+ if (has_barrier)
+ emit_barrier_after (tem);
- /* Return either the first or the last insn, depending on which was
- requested. */
- return last
- ? (after ? PREV_INSN (after) : last_insn)
- : NEXT_INSN (before);
- }
+ /* Recursively call try_split for each new insn created; by the
+ time control returns here that insn will be fully split, so
+ set LAST and continue from the insn after the one returned.
+ We can't use next_active_insn here since AFTER may be a note.
+ Ignore deleted insns, which can be occur if not optimizing. */
+ for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem))
+ if (! INSN_DELETED_P (tem) && INSN_P (tem))
+ tem = try_split (PATTERN (tem), tem, 1);
- return trial;
+ /* Return either the first or the last insn, depending on which was
+ requested. */
+ return last
+ ? (after ? PREV_INSN (after) : last_insn)
+ : NEXT_INSN (before);
}
\f
/* Make and return an INSN rtx, initializing all its slots.
Store PATTERN in the pattern slots. */
rtx
-make_insn_raw (pattern)
- rtx pattern;
+make_insn_raw (rtx pattern)
{
rtx insn;
INSN_CODE (insn) = -1;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
- INSN_SCOPE (insn) = NULL;
+ INSN_LOCATOR (insn) = 0;
BLOCK_FOR_INSN (insn) = NULL;
#ifdef ENABLE_RTL_CHECKING
/* Like `make_insn_raw' but make a JUMP_INSN instead of an insn. */
static rtx
-make_jump_insn_raw (pattern)
- rtx pattern;
+make_jump_insn_raw (rtx pattern)
{
rtx insn;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
JUMP_LABEL (insn) = NULL;
- INSN_SCOPE (insn) = NULL;
+ INSN_LOCATOR (insn) = 0;
BLOCK_FOR_INSN (insn) = NULL;
return insn;
/* Like `make_insn_raw' but make a CALL_INSN instead of an insn. */
static rtx
-make_call_insn_raw (pattern)
- rtx pattern;
+make_call_insn_raw (rtx pattern)
{
rtx insn;
LOG_LINKS (insn) = NULL;
REG_NOTES (insn) = NULL;
CALL_INSN_FUNCTION_USAGE (insn) = NULL;
- INSN_SCOPE (insn) = NULL;
+ INSN_LOCATOR (insn) = 0;
BLOCK_FOR_INSN (insn) = NULL;
return insn;
INSN may be an INSN, JUMP_INSN, CALL_INSN, CODE_LABEL, BARRIER or NOTE. */
void
-add_insn (insn)
- rtx insn;
+add_insn (rtx insn)
{
PREV_INSN (insn) = last_insn;
NEXT_INSN (insn) = 0;
SEQUENCE. */
void
-add_insn_after (insn, after)
- rtx insn, after;
+add_insn_after (rtx insn, rtx after)
{
rtx next = NEXT_INSN (after);
basic_block bb;
SEQUENCE. */
void
-add_insn_before (insn, before)
- rtx insn, before;
+add_insn_before (rtx insn, rtx before)
{
rtx prev = PREV_INSN (before);
basic_block bb;
/* Remove an insn from its doubly-linked list. This function knows how
to handle sequences. */
void
-remove_insn (insn)
- rtx insn;
+remove_insn (rtx insn)
{
rtx next = NEXT_INSN (insn);
rtx prev = PREV_INSN (insn);
}
}
+/* Append CALL_FUSAGE to the CALL_INSN_FUNCTION_USAGE for CALL_INSN. */
+
+void
+add_function_usage_to (rtx call_insn, rtx call_fusage)
+{
+ if (! call_insn || GET_CODE (call_insn) != CALL_INSN)
+ abort ();
+
+ /* Put the register usage information on the CALL. If there is already
+ some usage information, put ours at the end. */
+ if (CALL_INSN_FUNCTION_USAGE (call_insn))
+ {
+ rtx link;
+
+ for (link = CALL_INSN_FUNCTION_USAGE (call_insn); XEXP (link, 1) != 0;
+ link = XEXP (link, 1))
+ ;
+
+ XEXP (link, 1) = call_fusage;
+ }
+ else
+ CALL_INSN_FUNCTION_USAGE (call_insn) = call_fusage;
+}
+
/* Delete all insns made since FROM.
FROM becomes the new last instruction. */
void
-delete_insns_since (from)
- rtx from;
+delete_insns_since (rtx from)
{
if (from == 0)
first_insn = 0;
called after delay-slot filling has been done. */
void
-reorder_insns_nobb (from, to, after)
- rtx from, to, after;
+reorder_insns_nobb (rtx from, rtx to, rtx after)
{
/* Splice this bunch out of where it is now. */
if (PREV_INSN (from))
/* Same as function above, but take care to update BB boundaries. */
void
-reorder_insns (from, to, after)
- rtx from, to, after;
+reorder_insns (rtx from, rtx to, rtx after)
{
rtx prev = PREV_INSN (from);
basic_block bb, bb2;
/* Return the line note insn preceding INSN. */
static rtx
-find_line_note (insn)
- rtx insn;
+find_line_note (rtx insn)
{
if (no_line_numbers)
return 0;
and FROM, and another one after TO. */
void
-reorder_insns_with_line_notes (from, to, after)
- rtx from, to, after;
+reorder_insns_with_line_notes (rtx from, rtx to, rtx after)
{
rtx from_line = find_line_note (from);
rtx after_line = find_line_note (after);
return;
if (from_line)
- emit_line_note_after (NOTE_SOURCE_FILE (from_line),
- NOTE_LINE_NUMBER (from_line),
- after);
+ emit_note_copy_after (from_line, after);
if (after_line)
- emit_line_note_after (NOTE_SOURCE_FILE (after_line),
- NOTE_LINE_NUMBER (after_line),
- to);
+ emit_note_copy_after (after_line, to);
}
/* Remove unnecessary notes from the instruction stream. */
void
-remove_unnecessary_notes ()
+remove_unnecessary_notes (void)
{
rtx block_stack = NULL_RTX;
rtx eh_stack = NULL_RTX;
/* Make X be output before the instruction BEFORE. */
rtx
-emit_insn_before (x, before)
- rtx x, before;
+emit_insn_before (rtx x, rtx before)
{
rtx last = before;
rtx insn;
and output it before the instruction BEFORE. */
rtx
-emit_jump_insn_before (x, before)
- rtx x, before;
+emit_jump_insn_before (rtx x, rtx before)
{
rtx insn, last = NULL_RTX;
and output it before the instruction BEFORE. */
rtx
-emit_call_insn_before (x, before)
- rtx x, before;
+emit_call_insn_before (rtx x, rtx before)
{
rtx last = NULL_RTX, insn;
and output it before the insn BEFORE. */
rtx
-emit_barrier_before (before)
- rtx before;
+emit_barrier_before (rtx before)
{
rtx insn = rtx_alloc (BARRIER);
/* Emit the label LABEL before the insn BEFORE. */
rtx
-emit_label_before (label, before)
- rtx label, before;
+emit_label_before (rtx label, rtx before)
{
/* This can be called twice for the same label as a result of the
confusion that follows a syntax error! So make it harmless. */
/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
rtx
-emit_note_before (subtype, before)
- int subtype;
- rtx before;
+emit_note_before (int subtype, rtx before)
{
rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
/* Helper for emit_insn_after, handles lists of instructions
efficiently. */
-static rtx emit_insn_after_1 PARAMS ((rtx, rtx));
+static rtx emit_insn_after_1 (rtx, rtx);
static rtx
-emit_insn_after_1 (first, after)
- rtx first, after;
+emit_insn_after_1 (rtx first, rtx after)
{
rtx last;
rtx after_after;
/* Make X be output after the insn AFTER. */
rtx
-emit_insn_after (x, after)
- rtx x, after;
+emit_insn_after (rtx x, rtx after)
{
rtx last = after;
as to act as if this insn were at FROM. */
void
-emit_insn_after_with_line_notes (x, after, from)
- rtx x, after, from;
+emit_insn_after_with_line_notes (rtx x, rtx after, rtx from)
{
rtx from_line = find_line_note (from);
rtx after_line = find_line_note (after);
rtx insn = emit_insn_after (x, after);
if (from_line)
- emit_line_note_after (NOTE_SOURCE_FILE (from_line),
- NOTE_LINE_NUMBER (from_line),
- after);
+ emit_note_copy_after (from_line, after);
if (after_line)
- emit_line_note_after (NOTE_SOURCE_FILE (after_line),
- NOTE_LINE_NUMBER (after_line),
- insn);
+ emit_note_copy_after (after_line, insn);
}
/* Make an insn of code JUMP_INSN with body X
and output it after the insn AFTER. */
rtx
-emit_jump_insn_after (x, after)
- rtx x, after;
+emit_jump_insn_after (rtx x, rtx after)
{
rtx last;
and output it after the instruction AFTER. */
rtx
-emit_call_insn_after (x, after)
- rtx x, after;
+emit_call_insn_after (rtx x, rtx after)
{
rtx last;
and output it after the insn AFTER. */
rtx
-emit_barrier_after (after)
- rtx after;
+emit_barrier_after (rtx after)
{
rtx insn = rtx_alloc (BARRIER);
/* Emit the label LABEL after the insn AFTER. */
rtx
-emit_label_after (label, after)
- rtx label, after;
+emit_label_after (rtx label, rtx after)
{
/* This can be called twice for the same label
as a result of the confusion that follows a syntax error!
/* Emit a note of subtype SUBTYPE after the insn AFTER. */
rtx
-emit_note_after (subtype, after)
- int subtype;
- rtx after;
+emit_note_after (int subtype, rtx after)
{
rtx note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
return note;
}
-/* Emit a line note for FILE and LINE after the insn AFTER. */
+/* Emit a copy of note ORIG after the insn AFTER. */
rtx
-emit_line_note_after (file, line, after)
- const char *file;
- int line;
- rtx after;
+emit_note_copy_after (rtx orig, rtx after)
{
rtx note;
- if (no_line_numbers && line > 0)
+ if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers)
{
cur_insn_uid++;
return 0;
note = rtx_alloc (NOTE);
INSN_UID (note) = cur_insn_uid++;
- NOTE_SOURCE_FILE (note) = file;
- NOTE_LINE_NUMBER (note) = line;
+ NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig);
+ NOTE_DATA (note) = NOTE_DATA (orig);
BLOCK_FOR_INSN (note) = NULL;
add_insn_after (note, after);
return note;
}
\f
-/* Like emit_insn_after, but set INSN_SCOPE according to SCOPE. */
+/* Like emit_insn_after, but set INSN_LOCATOR according to SCOPE. */
rtx
-emit_insn_after_scope (pattern, after, scope)
- rtx pattern, after;
- tree scope;
+emit_insn_after_setloc (rtx pattern, rtx after, int loc)
{
rtx last = emit_insn_after (pattern, after);
while (1)
{
if (active_insn_p (after))
- INSN_SCOPE (after) = scope;
+ INSN_LOCATOR (after) = loc;
if (after == last)
break;
after = NEXT_INSN (after);
return last;
}
-/* Like emit_jump_insn_after, but set INSN_SCOPE according to SCOPE. */
+/* Like emit_jump_insn_after, but set INSN_LOCATOR according to SCOPE. */
rtx
-emit_jump_insn_after_scope (pattern, after, scope)
- rtx pattern, after;
- tree scope;
+emit_jump_insn_after_setloc (rtx pattern, rtx after, int loc)
{
rtx last = emit_jump_insn_after (pattern, after);
while (1)
{
if (active_insn_p (after))
- INSN_SCOPE (after) = scope;
+ INSN_LOCATOR (after) = loc;
if (after == last)
break;
after = NEXT_INSN (after);
return last;
}
-/* Like emit_call_insn_after, but set INSN_SCOPE according to SCOPE. */
+/* Like emit_call_insn_after, but set INSN_LOCATOR according to SCOPE. */
rtx
-emit_call_insn_after_scope (pattern, after, scope)
- rtx pattern, after;
- tree scope;
+emit_call_insn_after_setloc (rtx pattern, rtx after, int loc)
{
rtx last = emit_call_insn_after (pattern, after);
while (1)
{
if (active_insn_p (after))
- INSN_SCOPE (after) = scope;
+ INSN_LOCATOR (after) = loc;
if (after == last)
break;
after = NEXT_INSN (after);
return last;
}
-/* Like emit_insn_before, but set INSN_SCOPE according to SCOPE. */
+/* Like emit_insn_before, but set INSN_LOCATOR according to SCOPE. */
rtx
-emit_insn_before_scope (pattern, before, scope)
- rtx pattern, before;
- tree scope;
+emit_insn_before_setloc (rtx pattern, rtx before, int loc)
{
rtx first = PREV_INSN (before);
rtx last = emit_insn_before (pattern, before);
while (1)
{
if (active_insn_p (first))
- INSN_SCOPE (first) = scope;
+ INSN_LOCATOR (first) = loc;
if (first == last)
break;
first = NEXT_INSN (first);
Returns the last insn emitted. */
rtx
-emit_insn (x)
- rtx x;
+emit_insn (rtx x)
{
rtx last = last_insn;
rtx insn;
and add it to the end of the doubly-linked list. */
rtx
-emit_jump_insn (x)
- rtx x;
+emit_jump_insn (rtx x)
{
rtx last = NULL_RTX, insn;
and add it to the end of the doubly-linked list. */
rtx
-emit_call_insn (x)
- rtx x;
+emit_call_insn (rtx x)
{
rtx insn;
/* Add the label LABEL to the end of the doubly-linked list. */
rtx
-emit_label (label)
- rtx label;
+emit_label (rtx label)
{
/* This can be called twice for the same label
as a result of the confusion that follows a syntax error!
and add it to the end of the doubly-linked list. */
rtx
-emit_barrier ()
+emit_barrier (void)
{
rtx barrier = rtx_alloc (BARRIER);
INSN_UID (barrier) = cur_insn_uid++;
return barrier;
}
-/* Make an insn of code NOTE
- with data-fields specified by FILE and LINE
- and add it to the end of the doubly-linked list,
- but only if line-numbers are desired for debugging info. */
+/* Make line numbering NOTE insn for LOCATION add it to the end
+ of the doubly-linked list, but only if line-numbers are desired for
+ debugging info and it doesn't match the previous one. */
rtx
-emit_line_note (file, line)
- const char *file;
- int line;
+emit_line_note (location_t location)
{
- set_file_and_line_for_stmt (file, line);
-
-#if 0
+ rtx note;
+
+ set_file_and_line_for_stmt (location);
+
+ if (location.file && last_location.file
+ && !strcmp (location.file, last_location.file)
+ && location.line == last_location.line)
+ return NULL_RTX;
+ last_location = location;
+
if (no_line_numbers)
- return 0;
-#endif
+ {
+ cur_insn_uid++;
+ return NULL_RTX;
+ }
- return emit_note (file, line);
+ note = emit_note (location.line);
+ NOTE_SOURCE_FILE (note) = location.file;
+
+ return note;
}
-/* Make an insn of code NOTE
- with data-fields specified by FILE and LINE
- and add it to the end of the doubly-linked list.
- If it is a line-number NOTE, omit it if it matches the previous one. */
+/* Emit a copy of note ORIG. */
rtx
-emit_note (file, line)
- const char *file;
- int line;
+emit_note_copy (rtx orig)
{
rtx note;
-
- if (line > 0)
- {
- if (file && last_filename && !strcmp (file, last_filename)
- && line == last_linenum)
- return 0;
- last_filename = file;
- last_linenum = line;
- }
-
- if (no_line_numbers && line > 0)
+
+ if (NOTE_LINE_NUMBER (orig) >= 0 && no_line_numbers)
{
cur_insn_uid++;
- return 0;
+ return NULL_RTX;
}
-
+
note = rtx_alloc (NOTE);
+
INSN_UID (note) = cur_insn_uid++;
- NOTE_SOURCE_FILE (note) = file;
- NOTE_LINE_NUMBER (note) = line;
+ NOTE_DATA (note) = NOTE_DATA (orig);
+ NOTE_LINE_NUMBER (note) = NOTE_LINE_NUMBER (orig);
BLOCK_FOR_INSN (note) = NULL;
add_insn (note);
+
return note;
}
-/* Emit a NOTE, and don't omit it even if LINE is the previous note. */
+/* Make an insn of code NOTE or type NOTE_NO
+ and add it to the end of the doubly-linked list. */
rtx
-emit_line_note_force (file, line)
- const char *file;
- int line;
+emit_note (int note_no)
{
- last_linenum = -1;
- return emit_line_note (file, line);
+ rtx note;
+
+ note = rtx_alloc (NOTE);
+ INSN_UID (note) = cur_insn_uid++;
+ NOTE_LINE_NUMBER (note) = note_no;
+ memset (&NOTE_DATA (note), 0, sizeof (NOTE_DATA (note)));
+ BLOCK_FOR_INSN (note) = NULL;
+ add_insn (note);
+ return note;
}
/* Cause next statement to emit a line note even if the line number
- has not changed. This is used at the beginning of a function. */
+ has not changed. */
void
-force_next_line_note ()
+force_next_line_note (void)
{
- last_linenum = -1;
+ last_location.line = -1;
}
/* Place a note of KIND on insn INSN with DATUM as the datum. If a
note of this type already exists, remove it first. */
rtx
-set_unique_reg_note (insn, kind, datum)
- rtx insn;
- enum reg_note kind;
- rtx datum;
+set_unique_reg_note (rtx insn, enum reg_note kind, rtx datum)
{
rtx note = find_reg_note (insn, kind, NULL_RTX);
The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */
enum rtx_code
-classify_insn (x)
- rtx x;
+classify_insn (rtx x)
{
if (GET_CODE (x) == CODE_LABEL)
return CODE_LABEL;
If X is a label, it is simply added into the insn chain. */
rtx
-emit (x)
- rtx x;
+emit (rtx x)
{
enum rtx_code code = classify_insn (x);
emitted in the middle of this sequence. */
void
-start_sequence ()
+start_sequence (void)
{
struct sequence_stack *tem;
free_sequence_stack = tem->next;
}
else
- tem = (struct sequence_stack *) ggc_alloc (sizeof (struct sequence_stack));
+ tem = ggc_alloc (sizeof (struct sequence_stack));
tem->next = seq_stack;
tem->first = first_insn;
information about how to use this function. */
void
-start_sequence_for_rtl_expr (t)
- tree t;
+start_sequence_for_rtl_expr (tree t)
{
start_sequence ();
start_sequence for more information about how to use this function. */
void
-push_to_sequence (first)
- rtx first;
+push_to_sequence (rtx first)
{
rtx last;
/* Set up the insn chain from a chain stort in FIRST to LAST. */
void
-push_to_full_sequence (first, last)
- rtx first, last;
+push_to_full_sequence (rtx first, rtx last)
{
start_sequence ();
first_insn = first;
as the current sequence, saving the previously current one. */
void
-push_topmost_sequence ()
+push_topmost_sequence (void)
{
struct sequence_stack *stack, *top = NULL;
insn chain, and restore the previous saved state. */
void
-pop_topmost_sequence ()
+pop_topmost_sequence (void)
{
struct sequence_stack *stack, *top = NULL;
information about deferred popping of arguments. */
void
-end_sequence ()
+end_sequence (void)
{
struct sequence_stack *tem = seq_stack;
and LAST. */
void
-end_full_sequence (first, last)
- rtx *first, *last;
+end_full_sequence (rtx *first, rtx *last)
{
*first = first_insn;
*last = last_insn;
/* Return 1 if currently emitting into a sequence. */
int
-in_sequence_p ()
+in_sequence_p (void)
{
return seq_stack != 0;
}
/* Put the various virtual registers into REGNO_REG_RTX. */
void
-init_virtual_regs (es)
- struct emit_status *es;
+init_virtual_regs (struct emit_status *es)
{
rtx *ptr = es->x_regno_reg_rtx;
ptr[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx;
SCRATCHes. */
rtx
-copy_insn_1 (orig)
- rtx orig;
+copy_insn_1 (rtx orig)
{
rtx copy;
int i, j;
all fields need copying, and then clear the fields that should
not be copied. That is the sensible default behavior, and forces
us to explicitly document why we are *not* copying a flag. */
- memcpy (copy, orig, sizeof (struct rtx_def) - sizeof (rtunion));
+ memcpy (copy, orig, RTX_HDR_SIZE);
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
{
- copy->fld[i] = orig->fld[i];
+ copy->u.fld[i] = orig->u.fld[i];
switch (*format_ptr++)
{
case 'e':
INSN doesn't really have to be a full INSN; it could be just the
pattern. */
rtx
-copy_insn (insn)
- rtx insn;
+copy_insn (rtx insn)
{
copy_insn_n_scratches = 0;
orig_asm_operands_vector = 0;
before generating rtl for each function. */
void
-init_emit ()
+init_emit (void)
{
struct function *f = cfun;
- f->emit = (struct emit_status *) ggc_alloc (sizeof (struct emit_status));
+ f->emit = ggc_alloc (sizeof (struct emit_status));
first_insn = NULL;
last_insn = NULL;
seq_rtl_expr = NULL;
cur_insn_uid = 1;
reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
- last_linenum = 0;
- last_filename = 0;
+ last_location.line = 0;
+ last_location.file = 0;
first_label_num = label_num;
last_label_num = 0;
seq_stack = NULL;
f->emit->regno_pointer_align_length = LAST_VIRTUAL_REGISTER + 101;
f->emit->regno_pointer_align
- = (unsigned char *) ggc_alloc_cleared (f->emit->regno_pointer_align_length
- * sizeof (unsigned char));
+ = ggc_alloc_cleared (f->emit->regno_pointer_align_length
+ * sizeof (unsigned char));
regno_reg_rtx
- = (rtx *) ggc_alloc (f->emit->regno_pointer_align_length * sizeof (rtx));
+ = ggc_alloc (f->emit->regno_pointer_align_length * sizeof (rtx));
/* Put copies of all the hard registers into regno_reg_rtx. */
memcpy (regno_reg_rtx,
/* Generate the constant 0. */
static rtx
-gen_const_vector_0 (mode)
- enum machine_mode mode;
+gen_const_vector_0 (enum machine_mode mode)
{
rtx tem;
rtvec v;
/* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when
all elements are zero. */
rtx
-gen_rtx_CONST_VECTOR (mode, v)
- enum machine_mode mode;
- rtvec v;
+gen_rtx_CONST_VECTOR (enum machine_mode mode, rtvec v)
{
rtx inner_zero = CONST0_RTX (GET_MODE_INNER (mode));
int i;
LINE_NUMBERS is nonzero if line numbers are to be generated. */
void
-init_emit_once (line_numbers)
- int line_numbers;
+init_emit_once (int line_numbers)
{
int i;
enum machine_mode mode;
enum machine_mode double_mode;
+ /* We need reg_raw_mode, so initialize the modes now. */
+ init_reg_modes_once ();
+
/* Initialize the CONST_INT, CONST_DOUBLE, and memory attribute hash
tables. */
const_int_htab = htab_create_ggc (37, const_int_htab_hash,
REAL_VALUE_FROM_INT (dconst0, 0, 0, double_mode);
REAL_VALUE_FROM_INT (dconst1, 1, 0, double_mode);
REAL_VALUE_FROM_INT (dconst2, 2, 0, double_mode);
+ REAL_VALUE_FROM_INT (dconst3, 3, 0, double_mode);
+ REAL_VALUE_FROM_INT (dconst10, 10, 0, double_mode);
REAL_VALUE_FROM_INT (dconstm1, -1, -1, double_mode);
+ REAL_VALUE_FROM_INT (dconstm2, -2, -1, double_mode);
+
+ dconsthalf = dconst1;
+ dconsthalf.exp--;
+
+ real_arithmetic (&dconstthird, RDIV_EXPR, &dconst1, &dconst3);
- for (i = 0; i <= 2; i++)
+ /* Initialize mathematical constants for constant folding builtins.
+ These constants need to be given to at least 160 bits precision. */
+ real_from_string (&dconstpi,
+ "3.1415926535897932384626433832795028841971693993751058209749445923078");
+ real_from_string (&dconste,
+ "2.7182818284590452353602874713526624977572470936999595749669676277241");
+
+ for (i = 0; i < (int) ARRAY_SIZE (const_tiny_rtx); i++)
{
REAL_VALUE_TYPE *r =
(i == 0 ? &dconst0 : i == 1 ? &dconst1 : &dconst2);
= gen_raw_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM);
#endif
-#ifdef STRUCT_VALUE
- struct_value_rtx = STRUCT_VALUE;
-#else
- struct_value_rtx = gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM);
-#endif
-
-#ifdef STRUCT_VALUE_INCOMING
- struct_value_incoming_rtx = STRUCT_VALUE_INCOMING;
-#else
-#ifdef STRUCT_VALUE_INCOMING_REGNUM
- struct_value_incoming_rtx
- = gen_rtx_REG (Pmode, STRUCT_VALUE_INCOMING_REGNUM);
-#else
- struct_value_incoming_rtx = struct_value_rtx;
-#endif
-#endif
-
#ifdef STATIC_CHAIN_REGNUM
static_chain_rtx = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
warnings about unreachable code. */
int
-force_line_numbers ()
+force_line_numbers (void)
{
int old = no_line_numbers;
}
void
-restore_line_number_status (old_value)
- int old_value;
+restore_line_number_status (int old_value)
{
no_line_numbers = old_value;
}
Care updating of libcall regions if present. */
rtx
-emit_copy_of_insn_after (insn, after)
- rtx insn, after;
+emit_copy_of_insn_after (rtx insn, rtx after)
{
rtx new;
rtx note1, note2, link;
/* Update LABEL_NUSES. */
mark_jump_label (PATTERN (new), new, 0);
- INSN_SCOPE (new) = INSN_SCOPE (insn);
+ INSN_LOCATOR (new) = INSN_LOCATOR (insn);
/* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
make them. */