/* Register Transfer Language (RTL) definitions for GNU C-Compiler
- Copyright (C) 1987, 91-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 91-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
#ifndef _RTL_H
#define _RTL_H
+struct function;
+
#include "machmode.h"
#undef FFS /* Some systems predefine this symbol; don't let it interfere. */
#define NUM_RTX_CODE ((int)LAST_AND_UNUSED_RTX_CODE)
/* The cast here, saves many elsewhere. */
-extern int rtx_length[];
+extern const int rtx_length[];
#define GET_RTX_LENGTH(CODE) (rtx_length[(int) (CODE)])
-extern char *rtx_name[];
+extern const char * const rtx_name[];
#define GET_RTX_NAME(CODE) (rtx_name[(int) (CODE)])
-extern char *rtx_format[];
+extern const char * const rtx_format[];
#define GET_RTX_FORMAT(CODE) (rtx_format[(int) (CODE)])
-extern char rtx_class[];
+extern const char rtx_class[];
#define GET_RTX_CLASS(CODE) (rtx_class[(int) (CODE)])
\f
/* The flags and bitfields of an ADDR_DIFF_VEC. BASE is the base label
addr_diff_vec_flags rt_addr_diff_vec_flags;
struct bitmap_head_def *rtbit;
union tree_node *rttree;
+ struct basic_block_def *bb;
} rtunion;
/* RTL expression ("rtx"). */
{
#ifdef ONLY_INT_FIELDS
#ifdef CODE_FIELD_BUG
- unsigned int code : 16;
+ unsigned int code : 15;
#else
unsigned short code;
#endif
#else
/* The kind of expression this is. */
- enum rtx_code code : 16;
+ enum rtx_code code : 15;
#endif
+
+ /* Used by the garbage collector. */
+ unsigned gc_mark : 1;
+
/* The kind of value the expression has. */
#ifdef ONLY_INT_FIELDS
int mode : 8;
#else
enum machine_mode mode : 8;
#endif
- /* 1 in an INSN if it can alter flow of control
- within this function. Not yet used! */
+ /* LINK_COST_ZERO in an INSN_LIST. */
unsigned int jump : 1;
- /* 1 in an INSN if it can call another function. Not yet used! */
+ /* LINK_COST_FREE in an INSN_LIST. */
unsigned int call : 1;
/* 1 in a MEM or REG if value of this expression will never change
during the current function, even though it is not
In a REG, nonzero means this reg refers to the return value
of the current function. */
unsigned integrated : 1;
- /* Nonzero if this rtx is related to the call frame, either changing how
- we compute the frame address or saving and restoring registers in
- the prologue and epilogue. */
+ /* 1 in an INSN or a SET if this rtx is related to the call frame,
+ either changing how we compute the frame address or saving and
+ restoring registers in the prologue and epilogue.
+ 1 in a MEM if the MEM refers to a scalar, rather than a member of
+ an aggregate. */
unsigned frame_related : 1;
+
/* The first element of the operands of this rtx.
The number of operands and their types are controlled
by the `code' field, according to rtl.def. */
rtunion fld[1];
} *rtx;
-#include "gansidecl.h"
-
#define NULL_RTX (rtx) 0
/* Define macros to access the `code' field of the rtx. */
typedef struct rtvec_def{
int num_elem; /* number of elements */
- rtunion elem[1];
+ int gc_mark;
+ struct rtx_def *elem[1];
} *rtvec;
#define NULL_RTVEC (rtvec) 0
#define GET_NUM_ELEM(RTVEC) ((RTVEC)->num_elem)
#define PUT_NUM_ELEM(RTVEC, NUM) ((RTVEC)->num_elem = (NUM))
-#define RTVEC_ELT(RTVEC, I) ((RTVEC)->elem[(I)].rtx)
-
/* 1 if X is a REG. */
#define REG_P(X) (GET_CODE (X) == REG)
/* General accessor macros for accessing the fields of an rtx. */
-#define XEXP(RTX, N) ((RTX)->fld[N].rtx)
-#define XINT(RTX, N) ((RTX)->fld[N].rtint)
-#define XWINT(RTX, N) ((RTX)->fld[N].rtwint)
-#define XSTR(RTX, N) ((RTX)->fld[N].rtstr)
-#define XVEC(RTX, N) ((RTX)->fld[N].rtvec)
-#define XVECLEN(RTX, N) ((RTX)->fld[N].rtvec->num_elem)
-#define XVECEXP(RTX,N,M)((RTX)->fld[N].rtvec->elem[M].rtx)
-#define XBITMAP(RTX, N) ((RTX)->fld[N].rtbit)
-#define XTREE(RTX, N) ((RTX)->fld[N].rttree)
+#if defined ENABLE_CHECKING && (__GNUC__ > 2 || __GNUC_MINOR__ > 6)
+/* The bit with a star outside the statement expr and an & inside is
+ so that N can be evaluated only once. */
+#define RTL_CHECK1(RTX, N, C1) \
+(*({ rtx _rtx = (RTX); int _n = (N); \
+ enum rtx_code _code = GET_CODE (_rtx); \
+ if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
+ rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ if (GET_RTX_FORMAT(_code)[_n] != C1) \
+ rtl_check_failed_type1 (_rtx, _n, C1, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ &_rtx->fld[_n]; }))
+
+#define RTL_CHECK2(RTX, N, C1, C2) \
+(*({ rtx _rtx = (RTX); int _n = (N); \
+ enum rtx_code _code = GET_CODE (_rtx); \
+ if (_n < 0 || _n >= GET_RTX_LENGTH (_code)) \
+ rtl_check_failed_bounds (_rtx, _n, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ if (GET_RTX_FORMAT(_code)[_n] != C1 \
+ && GET_RTX_FORMAT(_code)[_n] != C2) \
+ rtl_check_failed_type2 (_rtx, _n, C1, C2, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ &_rtx->fld[_n]; }))
+
+#define RTL_CHECKC1(RTX, N, C) \
+(*({ rtx _rtx = (RTX); int _n = (N); \
+ if (GET_CODE (_rtx) != C) \
+ rtl_check_failed_code1 (_rtx, C, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ &_rtx->fld[_n]; }))
+
+#define RTL_CHECKC2(RTX, N, C1, C2) \
+(*({ rtx _rtx = (RTX); int _n = (N); \
+ enum rtx_code _code = GET_CODE (_rtx); \
+ if (_code != C1 && _code != C2) \
+ rtl_check_failed_code2 (_rtx, C1, C2, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ &_rtx->fld[_n]; }))
+
+#define RTVEC_ELT(RTVEC, I) \
+(*({ rtvec _rtvec = (RTVEC); int _i = (I); \
+ if (_i < 0 || _i >= GET_NUM_ELEM (_rtvec)) \
+ rtvec_check_failed_bounds (_rtvec, _i, __FILE__, __LINE__, \
+ __PRETTY_FUNCTION__); \
+ &_rtvec->elem[_i]; }))
+
+extern void rtl_check_failed_bounds PROTO((rtx, int,
+ const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+extern void rtl_check_failed_type1 PROTO((rtx, int, int,
+ const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+extern void rtl_check_failed_type2 PROTO((rtx, int, int, int,
+ const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+extern void rtl_check_failed_code1 PROTO((rtx, enum rtx_code,
+ const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+extern void rtl_check_failed_code2 PROTO((rtx, enum rtx_code, enum rtx_code,
+ const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+extern void rtvec_check_failed_bounds PROTO((rtvec, int,
+ const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+
+#else /* not ENABLE_CHECKING */
+
+#define RTL_CHECK1(RTX, N, C1) ((RTX)->fld[N])
+#define RTL_CHECK2(RTX, N, C1, C2) ((RTX)->fld[N])
+#define RTL_CHECKC1(RTX, N, C) ((RTX)->fld[N])
+#define RTL_CHECKC2(RTX, N, C1, C2) ((RTX)->fld[N])
+#define RTVEC_ELT(RTVEC, I) ((RTVEC)->elem[I])
+
+#endif
+#define XWINT(RTX, N) (RTL_CHECK1(RTX, N, 'w').rtwint)
+#define XINT(RTX, N) (RTL_CHECK2(RTX, N, 'i', 'n').rtint)
+#define XSTR(RTX, N) (RTL_CHECK2(RTX, N, 's', 'S').rtstr)
+#define XEXP(RTX, N) (RTL_CHECK2(RTX, N, 'e', 'u').rtx)
+#define XVEC(RTX, N) (RTL_CHECK2(RTX, N, 'E', 'V').rtvec)
+#define XMODE(RTX, N) (RTL_CHECK1(RTX, N, 'M').rttype)
+#define XBITMAP(RTX, N) (RTL_CHECK1(RTX, N, 'b').rtbit)
+#define XTREE(RTX, N) (RTL_CHECK1(RTX, N, 't').rttree)
+#define XBBDEF(RTX, N) (RTL_CHECK1(RTX, N, 'B').bb)
+
+#define XVECEXP(RTX, N, M) RTVEC_ELT (XVEC (RTX, N), M)
+#define XVECLEN(RTX, N) GET_NUM_ELEM (XVEC (RTX, N))
+
+/* These are like XWINT, etc. except that they expect a '0' field instead
+ of the normal type code. */
+
+#define X0WINT(RTX, N) (RTL_CHECK1(RTX, N, '0').rtwint)
+#define X0INT(RTX, N) (RTL_CHECK1(RTX, N, '0').rtint)
+#define X0STR(RTX, N) (RTL_CHECK1(RTX, N, '0').rtstr)
+#define X0EXP(RTX, N) (RTL_CHECK1(RTX, N, '0').rtx)
+#define X0VEC(RTX, N) (RTL_CHECK1(RTX, N, '0').rtvec)
+#define X0MODE(RTX, N) (RTL_CHECK1(RTX, N, '0').rttype)
+#define X0BITMAP(RTX, N) (RTL_CHECK1(RTX, N, '0').rtbit)
+#define X0TREE(RTX, N) (RTL_CHECK1(RTX, N, '0').rttree)
+#define X0BBDEF(RTX, N) (RTL_CHECK1(RTX, N, '0').bb)
+#define X0ADVFLAGS(RTX, N) (RTL_CHECK1(RTX, N, '0').rt_addr_diff_vec_flags)
+
+#define XCWINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtwint)
+#define XCINT(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtint)
+#define XCSTR(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtstr)
+#define XCEXP(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtx)
+#define XCVEC(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtvec)
+#define XCMODE(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rttype)
+#define XCBITMAP(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rtbit)
+#define XCTREE(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rttree)
+#define XCBBDEF(RTX, N, C) (RTL_CHECKC1(RTX, N, C).bb)
+#define XCADVFLAGS(RTX, N, C) (RTL_CHECKC1(RTX, N, C).rt_addr_diff_vec_flags)
+
+#define XCVECEXP(RTX, N, M, C) RTVEC_ELT (XCVEC (RTX, N, C), M)
+#define XCVECLEN(RTX, N, C) GET_NUM_ELEM (XCVEC (RTX, N, C))
+
+#define XC2EXP(RTX, N, C1, C2) (RTL_CHECKC2(RTX, N, C1, C2).rtx)
\f
/* ACCESS MACROS for particular fields of insns. */
/* Holds a unique number for each insn.
These are not necessarily sequentially increasing. */
-#define INSN_UID(INSN) ((INSN)->fld[0].rtint)
+#define INSN_UID(INSN) XINT(INSN, 0)
/* Chain insns together in sequence. */
-#define PREV_INSN(INSN) ((INSN)->fld[1].rtx)
-#define NEXT_INSN(INSN) ((INSN)->fld[2].rtx)
+#define PREV_INSN(INSN) XEXP(INSN, 1)
+#define NEXT_INSN(INSN) XEXP(INSN, 2)
/* The body of an insn. */
-#define PATTERN(INSN) ((INSN)->fld[3].rtx)
+#define PATTERN(INSN) XEXP(INSN, 3)
/* Code number of instruction, from when it was recognized.
-1 means this instruction has not been recognized yet. */
-#define INSN_CODE(INSN) ((INSN)->fld[4].rtint)
+#define INSN_CODE(INSN) XINT(INSN, 4)
/* Set up in flow.c; empty before then.
Holds a chain of INSN_LIST rtx's whose first operands point at
previous insns with direct data-flow connections to this one.
That means that those insns set variables whose next use is in this insn.
They are always in the same basic block as this insn. */
-#define LOG_LINKS(INSN) ((INSN)->fld[5].rtx)
+#define LOG_LINKS(INSN) XEXP(INSN, 5)
/* 1 if insn has been deleted. */
#define INSN_DELETED_P(INSN) ((INSN)->volatil)
REG_FRAME_RELATED_EXPR is attached to insns that are RTX_FRAME_RELATED_P,
but are too complex for DWARF to interpret what they imply. The attached
rtx is used instead of intuition. */
+/* REG_EH_REGION is used to indicate what exception region an INSN
+ belongs in. This can be used to indicate what region a call may throw
+ to. a REGION of 0 indicates that a call cannot throw at all.
+ a REGION of -1 indicates that it cannot throw, nor will it execute
+ a non-local goto.
+ REG_EH_RETHROW is used to indicate that a call is actually a
+ call to rethrow, and specifies the rethrow symbol for the region
+ the rethrow is targetting. This provides a way to generate the
+ non standard flow edges required for a rethrow. */
+
-#define REG_NOTES(INSN) ((INSN)->fld[6].rtx)
+#define REG_NOTES(INSN) XEXP(INSN, 6)
-#define ADDR_DIFF_VEC_FLAGS(RTX) ((RTX)->fld[4].rt_addr_diff_vec_flags)
+#define ADDR_DIFF_VEC_FLAGS(RTX) X0ADVFLAGS(RTX, 4)
/* Don't forget to change reg_note_name in rtl.c. */
enum reg_note { REG_DEAD = 1, REG_INC = 2, REG_EQUIV = 3, REG_WAS_0 = 4,
REG_DEP_ANTI = 14, REG_DEP_OUTPUT = 15, REG_BR_PROB = 16,
REG_EXEC_COUNT = 17, REG_NOALIAS = 18, REG_SAVE_AREA = 19,
REG_BR_PRED = 20, REG_EH_CONTEXT = 21,
- REG_FRAME_RELATED_EXPR = 22 };
+ REG_FRAME_RELATED_EXPR = 22, REG_EH_REGION = 23,
+ REG_EH_RETHROW = 24 };
/* The base value for branch probability notes. */
#define REG_BR_PROB_BASE 10000
/* Names for REG_NOTE's in EXPR_LIST insn's. */
-extern char *reg_note_name[];
+extern const char * const reg_note_name[];
#define GET_REG_NOTE_NAME(MODE) (reg_note_name[(int) (MODE)])
/* This field is only present on CALL_INSNs. It holds a chain of EXPR_LIST of
CLOBBER expressions document the registers explicitly clobbered
by this CALL_INSN.
Pseudo registers can not be mentioned in this list. */
-#define CALL_INSN_FUNCTION_USAGE(INSN) ((INSN)->fld[7].rtx)
+#define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7)
/* The label-number of a code-label. The assembler label
is made from `L' and the label-number printed in decimal.
Label numbers are unique in a compilation. */
-#define CODE_LABEL_NUMBER(INSN) ((INSN)->fld[3].rtint)
+#define CODE_LABEL_NUMBER(INSN) XINT(INSN, 3)
#define LINE_NUMBER NOTE
The NOTE_INSN_RANGE_{START,END} and NOTE_INSN_LIVE notes record their
information as a rtx in the field. */
-#define NOTE_SOURCE_FILE(INSN) ((INSN)->fld[3].rtstr)
-#define NOTE_BLOCK_NUMBER(INSN) ((INSN)->fld[3].rtint)
-#define NOTE_RANGE_INFO(INSN) ((INSN)->fld[3].rtx)
-#define NOTE_LIVE_INFO(INSN) ((INSN)->fld[3].rtx)
-
-/* If the NOTE_BLOCK_NUMBER field gets a -1, it means create a new
- block node for a live range block. */
-#define NOTE_BLOCK_LIVE_RANGE_BLOCK -1
+#define NOTE_SOURCE_FILE(INSN) XCSTR(INSN, 3, NOTE)
+#define NOTE_BLOCK(INSN) XCTREE(INSN, 3, NOTE)
+#define NOTE_EH_HANDLER(INSN) XCINT(INSN, 3, NOTE)
+#define NOTE_RANGE_INFO(INSN) XCEXP(INSN, 3, NOTE)
+#define NOTE_LIVE_INFO(INSN) XCEXP(INSN, 3, NOTE)
+#define NOTE_BASIC_BLOCK(INSN) XCBBDEF(INSN, 3, NOTE)
/* In a NOTE that is a line number, this is the line number.
Other kinds of NOTEs are identified by negative numbers here. */
-#define NOTE_LINE_NUMBER(INSN) ((INSN)->fld[4].rtint)
+#define NOTE_LINE_NUMBER(INSN) XCINT(INSN, 4, NOTE)
/* Codes that appear in the NOTE_LINE_NUMBER field
for kinds of notes that are not line numbers.
#define NOTE_INSN_RANGE_END -18
/* Record which registers are currently live. */
#define NOTE_INSN_LIVE -19
-
-#if 0 /* These are not used, and I don't know what they were for. --rms. */
-#define NOTE_DECL_NAME(INSN) ((INSN)->fld[3].rtstr)
-#define NOTE_DECL_CODE(INSN) ((INSN)->fld[4].rtint)
-#define NOTE_DECL_RTL(INSN) ((INSN)->fld[5].rtx)
-#define NOTE_DECL_IDENTIFIER(INSN) ((INSN)->fld[6].rtint)
-#define NOTE_DECL_TYPE(INSN) ((INSN)->fld[7].rtint)
-#endif /* 0 */
+/* Record the struct for the following basic block. */
+#define NOTE_INSN_BASIC_BLOCK -20
/* Names for NOTE insn's other than line numbers. */
-extern char *note_insn_name[];
+extern const char * const note_insn_name[];
#define GET_NOTE_INSN_NAME(NOTE_CODE) (note_insn_name[-(NOTE_CODE)])
/* The name of a label, in case it corresponds to an explicit label
in the input source code. */
-#define LABEL_NAME(LABEL) ((LABEL)->fld[4].rtstr)
+#define LABEL_NAME(RTX) XCSTR(RTX, 4, CODE_LABEL)
/* In jump.c, each label contains a count of the number
of LABEL_REFs that point at it, so unused labels can be deleted. */
-#define LABEL_NUSES(LABEL) ((LABEL)->fld[5].rtint)
+#define LABEL_NUSES(RTX) XCINT(RTX, 5, CODE_LABEL)
/* The original regno this ADDRESSOF was built for. */
-#define ADDRESSOF_REGNO(RTX) ((RTX)->fld[1].rtint)
+#define ADDRESSOF_REGNO(RTX) XCINT(RTX, 1, ADDRESSOF)
/* The variable in the register we took the address of. */
-#define ADDRESSOF_DECL(X) ((tree) XEXP ((X), 2))
-#define SET_ADDRESSOF_DECL(X, T) (XEXP ((X), 2) = (rtx) (T))
+#define ADDRESSOF_DECL(RTX) XCTREE(RTX, 2, ADDRESSOF)
/* In jump.c, each JUMP_INSN can point to a label that it can jump to,
so that if the JUMP_INSN is deleted, the label's LABEL_NUSES can
be decremented and possibly the label can be deleted. */
-#define JUMP_LABEL(INSN) ((INSN)->fld[7].rtx)
+#define JUMP_LABEL(INSN) XCEXP(INSN, 7, JUMP_INSN)
/* Once basic blocks are found in flow.c,
each CODE_LABEL starts a chain that goes through
all the LABEL_REFs that jump to that label.
The chain eventually winds up at the CODE_LABEL; it is circular. */
-#define LABEL_REFS(LABEL) ((LABEL)->fld[6].rtx)
+#define LABEL_REFS(LABEL) XCEXP(LABEL, 6, CODE_LABEL)
\f
/* This is the field in the LABEL_REF through which the circular chain
of references to a particular label is linked.
This chain is set up in flow.c. */
-#define LABEL_NEXTREF(REF) ((REF)->fld[1].rtx)
+#define LABEL_NEXTREF(REF) XCEXP(REF, 1, LABEL_REF)
/* Once basic blocks are found in flow.c,
Each LABEL_REF points to its containing instruction with this field. */
-#define CONTAINING_INSN(RTX) ((RTX)->fld[2].rtx)
+#define CONTAINING_INSN(RTX) XCEXP(RTX, 2, LABEL_REF)
/* For a REG rtx, REGNO extracts the register number. */
-#define REGNO(RTX) ((RTX)->fld[0].rtint)
+#define REGNO(RTX) XCINT(RTX, 0, REG)
/* For a REG rtx, REG_FUNCTION_VALUE_P is nonzero if the reg
is the current function's return value. */
/* For a CONST_INT rtx, INTVAL extracts the integer. */
-#define INTVAL(RTX) ((RTX)->fld[0].rtwint)
+#define INTVAL(RTX) XCWINT(RTX, 0, CONST_INT)
/* For a SUBREG rtx, SUBREG_REG extracts the value we want a subreg of.
SUBREG_WORD extracts the word-number. */
-#define SUBREG_REG(RTX) ((RTX)->fld[0].rtx)
-#define SUBREG_WORD(RTX) ((RTX)->fld[1].rtint)
+#define SUBREG_REG(RTX) XCEXP(RTX, 0, SUBREG)
+#define SUBREG_WORD(RTX) XCINT(RTX, 1, SUBREG)
/* 1 if the REG contained in SUBREG_REG is already known to be
sign- or zero-extended from the mode of the SUBREG to the mode of
/* Access various components of an ASM_OPERANDS rtx. */
-#define ASM_OPERANDS_TEMPLATE(RTX) XSTR ((RTX), 0)
-#define ASM_OPERANDS_OUTPUT_CONSTRAINT(RTX) XSTR ((RTX), 1)
-#define ASM_OPERANDS_OUTPUT_IDX(RTX) XINT ((RTX), 2)
-#define ASM_OPERANDS_INPUT_VEC(RTX) XVEC ((RTX), 3)
-#define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XVEC ((RTX), 4)
-#define ASM_OPERANDS_INPUT(RTX, N) XVECEXP ((RTX), 3, (N))
-#define ASM_OPERANDS_INPUT_LENGTH(RTX) XVECLEN ((RTX), 3)
-#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) XSTR (XVECEXP ((RTX), 4, (N)), 0)
-#define ASM_OPERANDS_INPUT_MODE(RTX, N) GET_MODE (XVECEXP ((RTX), 4, (N)))
-#define ASM_OPERANDS_SOURCE_FILE(RTX) XSTR ((RTX), 5)
-#define ASM_OPERANDS_SOURCE_LINE(RTX) XINT ((RTX), 6)
+#define ASM_OPERANDS_TEMPLATE(RTX) XCSTR ((RTX), 0, ASM_OPERANDS)
+#define ASM_OPERANDS_OUTPUT_CONSTRAINT(RTX) XCSTR ((RTX), 1, ASM_OPERANDS)
+#define ASM_OPERANDS_OUTPUT_IDX(RTX) XCINT ((RTX), 2, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_VEC(RTX) XCVEC ((RTX), 3, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XCVEC ((RTX), 4, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT(RTX, N) XCVECEXP ((RTX), 3, (N), ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_LENGTH(RTX) XCVECLEN ((RTX), 3, ASM_OPERANDS)
+#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) XSTR (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS), 0)
+#define ASM_OPERANDS_INPUT_MODE(RTX, N) GET_MODE (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS))
+#define ASM_OPERANDS_SOURCE_FILE(RTX) XCSTR ((RTX), 5, ASM_OPERANDS)
+#define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT ((RTX), 6, ASM_OPERANDS)
/* For a MEM rtx, 1 if it's a volatile reference.
Also in an ASM_OPERANDS rtx. */
#define MEM_VOLATILE_P(RTX) ((RTX)->volatil)
-/* For a MEM rtx, 1 if it refers to a field of an aggregate. */
+/* For a MEM rtx, 1 if it refers to a field of an aggregate. If zero,
+ RTX may or may not refer to a field of an aggregate. */
#define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct)
+/* For a MEM rtx, 1 if it refers to a scalar. If zero, RTX may or may
+ not refer to a scalar.*/
+#define MEM_SCALAR_P(RTX) ((RTX)->frame_related)
+
+/* Copy the MEM_VOLATILE_P, MEM_IN_STRUCT_P, and MEM_SCALAR_P
+ attributes from RHS to LHS. */
+#define MEM_COPY_ATTRIBUTES(LHS, RHS) \
+ (MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
+ MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
+ MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS))
+
+/* If VAL is non-zero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
+ RTX. Otherwise, vice versa. Use this macro only when you are
+ *sure* that you know that the MEM is in a structure, or is a
+ scalar. VAL is evaluated only once. */
+#define MEM_SET_IN_STRUCT_P(RTX, VAL) \
+ ((VAL) ? (MEM_IN_STRUCT_P (RTX) = 1, MEM_SCALAR_P (RTX) = 0) \
+ : (MEM_IN_STRUCT_P (RTX) = 0, MEM_SCALAR_P (RTX) = 1))
+
/* For a MEM rtx, the alias set. If 0, this MEM is not in any alias
set, and may alias anything. Otherwise, the MEM can only alias
MEMs in the same alias set. This value is set in a
some front-ends, these numbers may correspond in some way to types,
or other language-level entities, but they need not, and the
back-end makes no such assumptions. */
-#define MEM_ALIAS_SET(RTX) (XINT (RTX, 1))
+#define MEM_ALIAS_SET(RTX) XCINT(RTX, 1, MEM)
/* For a LABEL_REF, 1 means that this reference is to a label outside the
loop containing the reference. */
/* For a SET rtx, SET_DEST is the place that is set
and SET_SRC is the value it is set to. */
-#define SET_DEST(RTX) ((RTX)->fld[0].rtx)
-#define SET_SRC(RTX) ((RTX)->fld[1].rtx)
+#define SET_DEST(RTX) XC2EXP(RTX, 0, SET, CLOBBER)
+#define SET_SRC(RTX) XCEXP(RTX, 1, SET)
/* For a TRAP_IF rtx, TRAP_CONDITION is an expression. */
-#define TRAP_CONDITION(RTX) ((RTX)->fld[0].rtx)
-#define TRAP_CODE(RTX) (RTX)->fld[1].rtx
+#define TRAP_CONDITION(RTX) XCEXP(RTX, 0, TRAP_IF)
+#define TRAP_CODE(RTX) XCEXP(RTX, 1, TRAP_IF)
/* 1 in a SYMBOL_REF if it addresses this function's constants pool. */
#define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging)
/* Flag in a SYMBOL_REF for machine-specific purposes. */
#define SYMBOL_REF_FLAG(RTX) ((RTX)->volatil)
+/* 1 in a SYMBOL_REF if it represents a symbol which might have to change
+ if its inlined or unrolled. */
+#define SYMBOL_REF_NEED_ADJUST(RTX) ((RTX)->in_struct)
+
/* 1 means a SYMBOL_REF has been the library function in emit_library_call. */
#define SYMBOL_REF_USED(RTX) ((RTX)->used)
-/* For an INLINE_HEADER rtx, FIRST_FUNCTION_INSN is the first insn
- of the function that is not involved in copying parameters to
- pseudo-registers. FIRST_PARM_INSN is the very first insn of
- the function, including the parameter copying.
- We keep this around in case we must splice
- this function into the assembly code at the end of the file.
- FIRST_LABELNO is the first label number used by the function (inclusive).
- LAST_LABELNO is the last label used by the function (exclusive).
- MAX_REGNUM is the largest pseudo-register used by that function.
- FUNCTION_ARGS_SIZE is the size of the argument block in the stack.
- POPS_ARGS is the number of bytes of input arguments popped by the function
- STACK_SLOT_LIST is the list of stack slots.
- FORCED_LABELS is the list of labels whose address was taken.
- FUNCTION_FLAGS are where single-bit flags are saved.
- OUTGOING_ARGS_SIZE is the size of the largest outgoing stack parameter list.
- ORIGINAL_ARG_VECTOR is a vector of the original DECL_RTX values
- for the function arguments.
- ORIGINAL_DECL_INITIAL is a pointer to the original DECL_INITIAL for the
- function.
- INLINE_REGNO_REG_RTX, INLINE_REGNO_POINTER_FLAG, and
- INLINE_REGNO_POINTER_ALIGN are pointers to the corresponding arrays.
-
- We want this to lay down like an INSN. The PREV_INSN field
- is always NULL. The NEXT_INSN field always points to the
- first function insn of the function being squirreled away. */
-
-#define FIRST_FUNCTION_INSN(RTX) ((RTX)->fld[2].rtx)
-#define FIRST_PARM_INSN(RTX) ((RTX)->fld[3].rtx)
-#define FIRST_LABELNO(RTX) ((RTX)->fld[4].rtint)
-#define LAST_LABELNO(RTX) ((RTX)->fld[5].rtint)
-#define MAX_PARMREG(RTX) ((RTX)->fld[6].rtint)
-#define MAX_REGNUM(RTX) ((RTX)->fld[7].rtint)
-#define FUNCTION_ARGS_SIZE(RTX) ((RTX)->fld[8].rtint)
-#define POPS_ARGS(RTX) ((RTX)->fld[9].rtint)
-#define STACK_SLOT_LIST(RTX) ((RTX)->fld[10].rtx)
-#define FORCED_LABELS(RTX) ((RTX)->fld[11].rtx)
-#define FUNCTION_FLAGS(RTX) ((RTX)->fld[12].rtint)
-#define OUTGOING_ARGS_SIZE(RTX) ((RTX)->fld[13].rtint)
-#define ORIGINAL_ARG_VECTOR(RTX) ((RTX)->fld[14].rtvec)
-#define ORIGINAL_DECL_INITIAL(RTX) ((RTX)->fld[15].rtx)
-#define INLINE_REGNO_REG_RTX(RTX) ((RTX)->fld[16].rtvec)
-#define INLINE_REGNO_POINTER_FLAG(RTX) ((RTX)->fld[17].rtstr)
-#define INLINE_REGNO_POINTER_ALIGN(RTX) ((RTX)->fld[18].rtstr)
-#define PARMREG_STACK_LOC(RTX) ((RTX)->fld[19].rtvec)
-
-/* In FUNCTION_FLAGS we save some variables computed when emitting the code
- for the function and which must be `or'ed into the current flag values when
- insns from that function are being inlined. */
-
-/* These ought to be an enum, but non-ANSI compilers don't like that. */
-#define FUNCTION_FLAGS_CALLS_ALLOCA 01
-#define FUNCTION_FLAGS_CALLS_SETJMP 02
-#define FUNCTION_FLAGS_RETURNS_STRUCT 04
-#define FUNCTION_FLAGS_RETURNS_PCC_STRUCT 010
-#define FUNCTION_FLAGS_NEEDS_CONTEXT 020
-#define FUNCTION_FLAGS_HAS_NONLOCAL_LABEL 040
-#define FUNCTION_FLAGS_RETURNS_POINTER 0100
-#define FUNCTION_FLAGS_USES_CONST_POOL 0200
-#define FUNCTION_FLAGS_CALLS_LONGJMP 0400
-#define FUNCTION_FLAGS_USES_PIC_OFFSET_TABLE 01000
-
/* Define a macro to look for REG_INC notes,
but save time on machines where they never exist. */
#define AUTO_INC_DEC
#endif
+#ifndef HAVE_PRE_INCREMENT
+#define HAVE_PRE_INCREMENT 0
+#endif
+
+#ifndef HAVE_PRE_DECREMENT
+#define HAVE_PRE_DECREMENT 0
+#endif
+
+#ifndef HAVE_POST_INCREMENT
+#define HAVE_POST_INCREMENT 0
+#endif
+
+#ifndef HAVE_POST_DECREMENT
+#define HAVE_POST_DECREMENT 0
+#endif
+
+
+/* Some architectures do not have complete pre/post increment/decrement
+ instruction sets, or only move some modes efficiently. These macros
+ allow us to tune autoincrement generation. */
+
+#ifndef USE_LOAD_POST_INCREMENT
+#define USE_LOAD_POST_INCREMENT(MODE) HAVE_POST_INCREMENT
+#endif
+
+#ifndef USE_LOAD_POST_DECREMENT
+#define USE_LOAD_POST_DECREMENT(MODE) HAVE_POST_DECREMENT
+#endif
+
+#ifndef USE_LOAD_PRE_INCREMENT
+#define USE_LOAD_PRE_INCREMENT(MODE) HAVE_PRE_INCREMENT
+#endif
+
+#ifndef USE_LOAD_PRE_DECREMENT
+#define USE_LOAD_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
+#endif
+
+#ifndef USE_STORE_POST_INCREMENT
+#define USE_STORE_POST_INCREMENT(MODE) HAVE_POST_INCREMENT
+#endif
+
+#ifndef USE_STORE_POST_DECREMENT
+#define USE_STORE_POST_DECREMENT(MODE) HAVE_POST_DECREMENT
+#endif
+
+#ifndef USE_STORE_PRE_INCREMENT
+#define USE_STORE_PRE_INCREMENT(MODE) HAVE_PRE_INCREMENT
+#endif
+
+#ifndef USE_STORE_PRE_DECREMENT
+#define USE_STORE_PRE_DECREMENT(MODE) HAVE_PRE_DECREMENT
+#endif
+
+
/* Accessors for RANGE_INFO. */
/* For RANGE_{START,END} notes return the RANGE_START note. */
-#define RANGE_INFO_NOTE_START(INSN) (XEXP (INSN, 0))
+#define RANGE_INFO_NOTE_START(INSN) XCEXP (INSN, 0, RANGE_INFO)
/* For RANGE_{START,END} notes return the RANGE_START note. */
-#define RANGE_INFO_NOTE_END(INSN) (XEXP (INSN, 1))
+#define RANGE_INFO_NOTE_END(INSN) XCEXP (INSN, 1, RANGE_INFO)
/* For RANGE_{START,END} notes, return the vector containing the registers used
in the range. */
-#define RANGE_INFO_REGS(INSN) (XVEC (INSN, 2))
-#define RANGE_INFO_REGS_REG(INSN, N) (XVECEXP (INSN, 2, N))
-#define RANGE_INFO_NUM_REGS(INSN) (XVECLEN (INSN, 2))
+#define RANGE_INFO_REGS(INSN) XCVEC (INSN, 2, RANGE_INFO)
+#define RANGE_INFO_REGS_REG(INSN, N) XCVECEXP (INSN, 2, N, RANGE_INFO)
+#define RANGE_INFO_NUM_REGS(INSN) XCVECLEN (INSN, 2, RANGE_INFO)
/* For RANGE_{START,END} notes, the number of calls within the range. */
-#define RANGE_INFO_NCALLS(INSN) (XINT (INSN, 3))
+#define RANGE_INFO_NCALLS(INSN) XCINT (INSN, 3, RANGE_INFO)
/* For RANGE_{START,END} notes, the number of insns within the range. */
-#define RANGE_INFO_NINSNS(INSN) (XINT (INSN, 4))
+#define RANGE_INFO_NINSNS(INSN) XCINT (INSN, 4, RANGE_INFO)
/* For RANGE_{START,END} notes, a unique # to identify this range. */
-#define RANGE_INFO_UNIQUE(INSN) (XINT (INSN, 5))
+#define RANGE_INFO_UNIQUE(INSN) XCINT (INSN, 5, RANGE_INFO)
/* For RANGE_{START,END} notes, the basic block # the range starts with. */
-#define RANGE_INFO_BB_START(INSN) (XINT (INSN, 6))
+#define RANGE_INFO_BB_START(INSN) XCINT (INSN, 6, RANGE_INFO)
/* For RANGE_{START,END} notes, the basic block # the range ends with. */
-#define RANGE_INFO_BB_END(INSN) (XINT (INSN, 7))
+#define RANGE_INFO_BB_END(INSN) XCINT (INSN, 7, RANGE_INFO)
/* For RANGE_{START,END} notes, the loop depth the range is in. */
-#define RANGE_INFO_LOOP_DEPTH(INSN) (XINT (INSN, 8))
+#define RANGE_INFO_LOOP_DEPTH(INSN) XCINT (INSN, 8, RANGE_INFO)
/* For RANGE_{START,END} notes, the bitmap of live registers at the start
of the range. */
-#define RANGE_INFO_LIVE_START(INSN) (XBITMAP (INSN, 9))
+#define RANGE_INFO_LIVE_START(INSN) XCBITMAP (INSN, 9, RANGE_INFO)
/* For RANGE_{START,END} notes, the bitmap of live registers at the end
of the range. */
-#define RANGE_INFO_LIVE_END(INSN) (XBITMAP (INSN, 10))
+#define RANGE_INFO_LIVE_END(INSN) XCBITMAP (INSN, 10, RANGE_INFO)
/* For RANGE_START notes, the marker # of the start of the range. */
-#define RANGE_INFO_MARKER_START(INSN) (XINT (INSN, 11))
+#define RANGE_INFO_MARKER_START(INSN) XCINT (INSN, 11, RANGE_INFO)
/* For RANGE_START notes, the marker # of the end of the range. */
-#define RANGE_INFO_MARKER_END(INSN) (XINT (INSN, 12))
+#define RANGE_INFO_MARKER_END(INSN) XCINT (INSN, 12, RANGE_INFO)
/* Original pseudo register # for a live range note. */
-#define RANGE_REG_PSEUDO(INSN,N) (XINT (XVECEXP (INSN, 2, N), 0))
+#define RANGE_REG_PSEUDO(INSN,N) XCINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 0, REG)
/* Pseudo register # original register is copied into or -1. */
-#define RANGE_REG_COPY(INSN,N) (XINT (XVECEXP (INSN, 2, N), 1))
+#define RANGE_REG_COPY(INSN,N) XCINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 1, REG)
/* How many times a register in a live range note was referenced. */
-#define RANGE_REG_REFS(INSN,N) (XINT (XVECEXP (INSN, 2, N), 2))
+#define RANGE_REG_REFS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 2)
/* How many times a register in a live range note was set. */
-#define RANGE_REG_SETS(INSN,N) (XINT (XVECEXP (INSN, 2, N), 3))
+#define RANGE_REG_SETS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 3)
/* How many times a register in a live range note died. */
-#define RANGE_REG_DEATHS(INSN,N) (XINT (XVECEXP (INSN, 2, N), 4))
+#define RANGE_REG_DEATHS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 4)
/* Whether the original value is needed to be copied into the range register at
the start of the range. */
-#define RANGE_REG_COPY_FLAGS(INSN,N) (XINT (XVECEXP (INSN, 2, N), 5))
+#define RANGE_REG_COPY_FLAGS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 5)
/* # of insns the register copy is live over. */
-#define RANGE_REG_LIVE_LENGTH(INSN,N) (XINT (XVECEXP (INSN, 2, N), 6))
+#define RANGE_REG_LIVE_LENGTH(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 6)
/* # of calls the register copy is live over. */
-#define RANGE_REG_N_CALLS(INSN,N) (XINT (XVECEXP (INSN, 2, N), 7))
+#define RANGE_REG_N_CALLS(INSN,N) XINT (XCVECEXP (INSN, 2, N, RANGE_INFO), 7)
/* DECL_NODE pointer of the declaration if the register is a user defined
variable. */
-#define RANGE_REG_SYMBOL_NODE(INSN,N) (XTREE (XVECEXP (INSN, 2, N), 8))
+#define RANGE_REG_SYMBOL_NODE(INSN,N) XTREE (XCVECEXP (INSN, 2, N, RANGE_INFO), 8)
/* BLOCK_NODE pointer to the block the variable is declared in if the
register is a user defined variable. */
-#define RANGE_REG_BLOCK_NODE(INSN,N) (XTREE (XVECEXP (INSN, 2, N), 9))
+#define RANGE_REG_BLOCK_NODE(INSN,N) XTREE (XCVECEXP (INSN, 2, N, RANGE_INFO), 9)
/* EXPR_LIST of the distinct ranges a variable is in. */
#define RANGE_VAR_LIST(INSN) (XEXP (INSN, 0))
/* For a NOTE_INSN_LIVE note, the original basic block number. */
#define RANGE_LIVE_ORIG_BLOCK(INSN) (XINT (INSN, 1))
\f
+/* Nonzero if we need to distinguish between the return value of this function
+ and the return value of a function called by this function. This helps
+ integrate.c.
+ This is 1 until after the rtl generation pass. */
+extern int rtx_equal_function_value_matters;
+
/* Generally useful functions. */
/* The following functions accept a wide integer argument. Rather than
plus_constant_for_output_wide (X, (HOST_WIDE_INT) (C))
/* In explow.c */
+extern HOST_WIDE_INT trunc_int_for_mode PROTO((HOST_WIDE_INT,
+ enum machine_mode));
extern rtx plus_constant_wide PROTO((rtx, HOST_WIDE_INT));
extern rtx plus_constant_for_output_wide PROTO((rtx, HOST_WIDE_INT));
extern void optimize_save_area_alloca PROTO((rtx));
extern rtx read_rtx PROTO((FILE *));
#endif
-#if 0
-/* At present, don't prototype xrealloc, since all of the callers don't
- cast their pointers to char *, and all of the xrealloc's don't use
- void * yet. */
-extern char *xmalloc PROTO((size_t));
-extern char *xcalloc PROTO((size_t, size_t));
-extern char *xrealloc PROTO((void *, size_t));
-#else
-extern char *xmalloc ();
-extern char *xcalloc ();
-extern char *xrealloc ();
-#endif
-
extern char *oballoc PROTO((int));
extern char *permalloc PROTO((int));
extern rtx rtx_alloc PROTO((RTX_CODE));
extern rtx copy_rtx PROTO((rtx));
extern rtx copy_rtx_if_shared PROTO((rtx));
extern rtx copy_most_rtx PROTO((rtx, rtx));
+extern rtx shallow_copy_rtx PROTO((rtx));
extern rtvec gen_rtvec_v PROTO((int, rtx *));
-extern rtvec gen_rtvec_vv PROTO((int, rtunion *));
extern rtx gen_reg_rtx PROTO((enum machine_mode));
extern rtx gen_label_rtx PROTO((void));
-extern rtx gen_inline_header_rtx PROTO((rtx, rtx, int, int, int, int,
- int, int, rtx, rtx, int, int,
- rtvec, rtx,
- rtvec, char *, char *, rtvec));
extern rtx gen_lowpart_common PROTO((enum machine_mode, rtx));
extern rtx gen_lowpart PROTO((enum machine_mode, rtx));
extern rtx gen_lowpart_if_possible PROTO((enum machine_mode, rtx));
extern rtx convert_memory_address PROTO((enum machine_mode, rtx));
extern rtx memory_address PROTO((enum machine_mode, rtx));
extern rtx get_insns PROTO((void));
+extern const char *get_insn_name PROTO((int));
extern rtx get_last_insn PROTO((void));
extern rtx get_last_insn_anywhere PROTO((void));
extern void start_sequence PROTO((void));
extern rtx force_reg PROTO((enum machine_mode, rtx));
extern rtx get_pool_constant PROTO((rtx));
extern enum machine_mode get_pool_mode PROTO((rtx));
+extern rtx get_pool_constant_for_function PROTO((struct function *, rtx));
+extern enum machine_mode get_pool_mode_for_function PROTO((struct function *, rtx));
extern int get_pool_offset PROTO((rtx));
extern rtx simplify_subtraction PROTO((rtx));
extern rtx assign_stack_local PROTO((enum machine_mode,
extern rtx emit_jump_insn_before PROTO((rtx, rtx));
extern rtx emit_call_insn_before PROTO((rtx, rtx));
extern rtx emit_barrier_before PROTO((rtx));
+extern rtx emit_label_before PROTO((rtx, rtx));
extern rtx emit_note_before PROTO((int, rtx));
extern rtx emit_insn_after PROTO((rtx, rtx));
extern rtx emit_jump_insn_after PROTO((rtx, rtx));
extern rtx simplify_binary_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx));
extern rtx simplify_ternary_operation PROTO((enum rtx_code, enum machine_mode, enum machine_mode, rtx, rtx, rtx));
extern rtx simplify_relational_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx));
-extern rtx nonlocal_label_rtx_list PROTO((void));
extern rtx gen_move_insn PROTO((rtx, rtx));
extern rtx gen_jump PROTO((rtx));
extern rtx gen_beq PROTO((rtx));
extern rtx eliminate_constant_term PROTO((rtx, rtx *));
extern rtx expand_complex_abs PROTO((enum machine_mode, rtx, rtx, int));
extern enum machine_mode choose_hard_reg_mode PROTO((int, int));
-extern int rtx_varies_p PROTO((rtx));
-extern int may_trap_p PROTO((rtx));
-extern int side_effects_p PROTO((rtx));
-extern int volatile_refs_p PROTO((rtx));
-extern int volatile_insn_p PROTO((rtx));
-extern void remove_note PROTO((rtx, rtx));
-extern int refers_to_regno_p PROTO((int, int, rtx, rtx *));
-extern int reg_overlap_mentioned_p PROTO((rtx, rtx));
+extern void set_unique_reg_note PROTO((rtx, enum reg_note, rtx));
/* Functions in rtlanal.c */
extern int reg_used_between_p PROTO((rtx, rtx, rtx));
extern int reg_referenced_between_p PROTO((rtx, rtx, rtx));
extern int reg_set_between_p PROTO((rtx, rtx, rtx));
+extern int regs_set_between_p PROTO((rtx, rtx, rtx));
extern int modified_between_p PROTO((rtx, rtx, rtx));
extern int no_labels_between_p PROTO((rtx, rtx));
+extern int no_jumps_between_p PROTO((rtx, rtx));
extern int modified_in_p PROTO((rtx, rtx));
extern int reg_set_p PROTO((rtx, rtx));
extern rtx single_set PROTO((rtx));
-extern rtx find_last_value PROTO((rtx, rtx *, rtx));
+extern int multiple_sets PROTO((rtx));
+extern rtx find_last_value PROTO((rtx, rtx *, rtx, int));
extern int refers_to_regno_p PROTO((int, int, rtx, rtx *));
extern int reg_overlap_mentioned_p PROTO((rtx, rtx));
-extern rtx find_use_as_address PROTO((rtx, rtx, HOST_WIDE_INT));
-extern void note_stores PROTO((rtx, void (*)()));
+extern void note_stores PROTO((rtx, void (*)(rtx, rtx)));
extern rtx reg_set_last PROTO((rtx, rtx));
extern int rtx_equal_p PROTO((rtx, rtx));
extern int dead_or_set_p PROTO((rtx, rtx));
extern int volatile_refs_p PROTO((rtx));
extern int volatile_insn_p PROTO((rtx));
extern int may_trap_p PROTO((rtx));
-extern int inequality_comparison_p PROTO((rtx));
+extern int inequality_comparisons_p PROTO ((rtx));
extern rtx replace_rtx PROTO((rtx, rtx, rtx));
extern rtx replace_regs PROTO((rtx, rtx *, int, int));
extern int computed_jump_p PROTO((rtx));
typedef int (*rtx_function) PROTO((rtx *, void *));
extern int for_each_rtx PROTO((rtx *, rtx_function, void *));
+extern rtx regno_use_in PROTO((int, rtx));
+extern int auto_inc_p PROTO((rtx));
+extern void remove_node_from_expr_list PROTO((rtx, rtx *));
+extern int insns_safe_to_move_p PROTO((rtx, rtx, rtx *));
+
+/* flow.c */
+
+extern rtx find_use_as_address PROTO((rtx, rtx, HOST_WIDE_INT));
+void init_EXPR_INSN_LIST_cache PROTO((void));
+void free_EXPR_LIST_list PROTO((rtx *));
+void free_INSN_LIST_list PROTO((rtx *));
+void free_EXPR_LIST_node PROTO((rtx));
+void free_INSN_LIST_node PROTO((rtx));
+rtx alloc_INSN_LIST PROTO((rtx, rtx));
+rtx alloc_EXPR_LIST PROTO((int, rtx, rtx));
+
+/* regclass.c */
/* Maximum number of parallel sets and clobbers in any insn in this fn.
Always at least 3, since the combiner could put that many togetherm
extern int max_parallel;
+/* Free up register info memory. */
+extern void free_reg_info PROTO((void));
+
+/* recog.c */
extern int asm_noperands PROTO((rtx));
-extern char *decode_asm_operands PROTO((rtx, rtx *, rtx **, char **, enum machine_mode *));
+extern char *decode_asm_operands PROTO((rtx, rtx *, rtx **,
+ const char **,
+ enum machine_mode *));
extern enum reg_class reg_preferred_class PROTO((int));
extern enum reg_class reg_alternate_class PROTO((int));
extern rtx get_first_nonparm_insn PROTO((void));
-/* Standard pieces of rtx, to be substituted directly into things. */
-#define pc_rtx (&global_rtl.pc_val)
-#define cc0_rtx (&global_rtl.cc0_val)
+extern void split_block_insns PROTO((int, int));
+extern void update_flow_info PROTO((rtx, rtx, rtx, rtx));
#define MAX_SAVED_CONST_INT 64
-extern struct rtx_def const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
+extern rtx const_int_rtx[MAX_SAVED_CONST_INT * 2 + 1];
-#define const0_rtx (&const_int_rtx[MAX_SAVED_CONST_INT])
-#define const1_rtx (&const_int_rtx[MAX_SAVED_CONST_INT+1])
-#define const2_rtx (&const_int_rtx[MAX_SAVED_CONST_INT+2])
-#define constm1_rtx (&const_int_rtx[MAX_SAVED_CONST_INT-1])
+#define const0_rtx (const_int_rtx[MAX_SAVED_CONST_INT])
+#define const1_rtx (const_int_rtx[MAX_SAVED_CONST_INT+1])
+#define const2_rtx (const_int_rtx[MAX_SAVED_CONST_INT+2])
+#define constm1_rtx (const_int_rtx[MAX_SAVED_CONST_INT-1])
extern rtx const_true_rtx;
extern rtx const_tiny_rtx[3][(int) MAX_MACHINE_MODE];
#define CONST1_RTX(MODE) (const_tiny_rtx[1][(int) (MODE)])
#define CONST2_RTX(MODE) (const_tiny_rtx[2][(int) (MODE)])
-extern struct _global_rtl
+/* If HARD_FRAME_POINTER_REGNUM is defined, then a special dummy reg
+ is used to represent the frame pointer. This is because the
+ hard frame pointer and the automatic variables are separated by an amount
+ that cannot be determined until after register allocation. We can assume
+ that in this case ELIMINABLE_REGS will be defined, one action of which
+ will be to eliminate FRAME_POINTER_REGNUM into HARD_FRAME_POINTER_REGNUM. */
+#ifndef HARD_FRAME_POINTER_REGNUM
+#define HARD_FRAME_POINTER_REGNUM FRAME_POINTER_REGNUM
+#endif
+
+/* Index labels for global_rtl. */
+enum global_rtl_index
{
- struct rtx_def pc_val, cc0_val;
- struct rtx_def stack_pointer_val, frame_pointer_val;
- struct rtx_def hard_frame_pointer_val;
- struct rtx_def arg_pointer_val;
- struct rtx_def virtual_incoming_args_val;
- struct rtx_def virtual_stack_vars_val;
- struct rtx_def virtual_stack_dynamic_val;
- struct rtx_def virtual_outgoing_args_val;
- struct rtx_def virtual_cfa_val;
-} global_rtl;
+ GR_PC,
+ GR_CC0,
+ GR_STACK_POINTER,
+ GR_FRAME_POINTER,
+/* For register elimination to work properly these hard_frame_pointer_rtx,
+ frame_pointer_rtx, and arg_pointer_rtx must be the same if they refer to
+ the same register. */
+#if FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
+ GR_ARG_POINTER = GR_FRAME_POINTER,
+#endif
+#if HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM
+ GR_HARD_FRAME_POINTER = GR_FRAME_POINTER,
+#else
+ GR_HARD_FRAME_POINTER,
+#endif
+#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
+#if HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
+ GR_ARG_POINTER = GR_HARD_FRAME_POINTER,
+#else
+ GR_ARG_POINTER,
+#endif
+#endif
+ GR_VIRTUAL_INCOMING_ARGS,
+ GR_VIRTUAL_STACK_ARGS,
+ GR_VIRTUAL_STACK_DYNAMIC,
+ GR_VIRTUAL_OUTGOING_ARGS,
+ GR_VIRTUAL_CFA,
+
+ GR_MAX
+};
+
+/* Pointers to standard pieces of rtx are stored here. */
+extern rtx global_rtl[GR_MAX];
+
+/* Standard pieces of rtx, to be substituted directly into things. */
+#define pc_rtx (global_rtl[GR_PC])
+#define cc0_rtx (global_rtl[GR_CC0])
/* All references to certain hard regs, except those created
by allocating pseudo regs into them (when that's possible),
go through these unique rtx objects. */
-#define stack_pointer_rtx (&global_rtl.stack_pointer_val)
-#define frame_pointer_rtx (&global_rtl.frame_pointer_val)
+#define stack_pointer_rtx (global_rtl[GR_STACK_POINTER])
+#define frame_pointer_rtx (global_rtl[GR_FRAME_POINTER])
+#define hard_frame_pointer_rtx (global_rtl[GR_HARD_FRAME_POINTER])
+#define arg_pointer_rtx (global_rtl[GR_ARG_POINTER])
extern rtx pic_offset_table_rtx;
extern rtx struct_value_rtx;
add to this list, modify special_rtx in gengenrtl.c as well. You
should also modify gen_rtx to use the special function. */
+extern rtx gen_rtx_CONST_DOUBLE PROTO((enum machine_mode, rtx,
+ HOST_WIDE_INT, HOST_WIDE_INT));
extern rtx gen_rtx_CONST_INT PROTO((enum machine_mode, HOST_WIDE_INT));
extern rtx gen_rtx_REG PROTO((enum machine_mode, int));
extern rtx gen_rtx_MEM PROTO((enum machine_mode, rtx));
and without prototypes. */
#define GEN_INT(N) gen_rtx_CONST_INT (VOIDmode, (HOST_WIDE_INT) (N))
-
-/* If HARD_FRAME_POINTER_REGNUM is defined, then a special dummy reg
- is used to represent the frame pointer. This is because the
- hard frame pointer and the automatic variables are separated by an amount
- that cannot be determined until after register allocation. We can assume
- that in this case ELIMINABLE_REGS will be defined, one action of which
- will be to eliminate FRAME_POINTER_REGNUM into HARD_FRAME_POINTER_REGNUM. */
-#ifndef HARD_FRAME_POINTER_REGNUM
-#define HARD_FRAME_POINTER_REGNUM FRAME_POINTER_REGNUM
-#endif
-
-/* For register elimination to work properly these hard_frame_pointer_rtx,
- frame_pointer_rtx, and arg_pointer_rtx must be the same if they refer to
- the same register. */
-#if HARD_FRAME_POINTER_REGNUM == FRAME_POINTER_REGNUM
-#define hard_frame_pointer_rtx (&global_rtl.frame_pointer_val)
-#else
-#define hard_frame_pointer_rtx (&global_rtl.hard_frame_pointer_val)
-#endif
-
-#if FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
-#define arg_pointer_rtx (&global_rtl.frame_pointer_val)
-#else
-#if HARD_FRAME_POINTER_REGNUM == ARG_POINTER_REGNUM
-#define arg_pointer_rtx (&global_rtl.hard_frame_pointer_val)
-#else
-#define arg_pointer_rtx (&global_rtl.arg_pointer_val)
-#endif
-#endif
-
/* Virtual registers are used during RTL generation to refer to locations into
the stack frame when the actual location isn't known until RTL generation
is complete. The routine instantiate_virtual_regs replaces these with
either by the caller or by the callee when pretending it was passed by the
caller. */
-#define virtual_incoming_args_rtx (&global_rtl.virtual_incoming_args_val)
+#define virtual_incoming_args_rtx (global_rtl[GR_VIRTUAL_INCOMING_ARGS])
#define VIRTUAL_INCOMING_ARGS_REGNUM (FIRST_VIRTUAL_REGISTER)
variable on the stack. Otherwise, it points to the first variable on
the stack. */
-#define virtual_stack_vars_rtx (&global_rtl.virtual_stack_vars_val)
+#define virtual_stack_vars_rtx (global_rtl[GR_VIRTUAL_STACK_ARGS])
#define VIRTUAL_STACK_VARS_REGNUM ((FIRST_VIRTUAL_REGISTER) + 1)
immediately after the stack pointer has been adjusted by the amount
desired. */
-#define virtual_stack_dynamic_rtx (&global_rtl.virtual_stack_dynamic_val)
+#define virtual_stack_dynamic_rtx (global_rtl[GR_VIRTUAL_STACK_DYNAMIC])
#define VIRTUAL_STACK_DYNAMIC_REGNUM ((FIRST_VIRTUAL_REGISTER) + 2)
be written when the stack is pre-pushed (arguments pushed using push
insns always use sp). */
-#define virtual_outgoing_args_rtx (&global_rtl.virtual_outgoing_args_val)
+#define virtual_outgoing_args_rtx (global_rtl[GR_VIRTUAL_OUTGOING_ARGS])
#define VIRTUAL_OUTGOING_ARGS_REGNUM ((FIRST_VIRTUAL_REGISTER) + 3)
frame pointer nor stack pointer are necessarily fixed relative to
the CFA until after reload. */
-#define virtual_cfa_rtx (&global_rtl.virtual_cfa_val)
+#define virtual_cfa_rtx (global_rtl[GR_VIRTUAL_CFA])
#define VIRTUAL_CFA_REGNUM ((FIRST_VIRTUAL_REGISTER) + 4)
#define STORE_FLAG_VALUE 1
#endif
+/* Nonzero after the second flow pass has completed.
+ Set to 1 or 0 by toplev.c */
+extern int flow2_completed;
+
/* Nonzero after end of reload pass.
- Set to 1 or 0 by toplev.c. */
+ Set to 1 or 0 by reload1.c. */
extern int reload_completed;
the same indirect address eventually. */
extern int cse_not_expected;
-/* Indexed by pseudo register number, gives the rtx for that pseudo.
- Allocated in parallel with regno_pointer_flag. */
-extern rtx *regno_reg_rtx;
-
-/* Vector indexed by regno; contain the alignment in bytes and type
- pointed to for a register that contains a pointer, if known. */
-extern char *regno_pointer_align;
-#define REGNO_POINTER_ALIGN(REGNO) regno_pointer_align[REGNO]
+/* Set to nonzero before life analysis to indicate that it is unsafe to
+ generate any new pseudo registers. */
+extern int no_new_pseudos;
/* Translates rtx code to tree code, for those codes needed by
REAL_ARITHMETIC. The function returns an int because the caller may not
extern int rtx_to_tree_code PROTO((enum rtx_code));
-/* In rtlanal.c */
-extern int reg_set_p PROTO ((rtx, rtx));
-extern int reg_mentioned_p PROTO ((rtx, rtx));
-extern int reg_referenced_p PROTO ((rtx, rtx));
-extern int reg_used_between_p PROTO ((rtx, rtx, rtx));
-extern int reg_set_p PROTO ((rtx, rtx));
-extern int reg_referenced_between_p PROTO ((rtx, rtx, rtx));
-extern int reg_set_between_p PROTO ((rtx, rtx, rtx));
-extern int rtx_unstable_p PROTO ((rtx));
-extern int rtx_addr_varies_p PROTO ((rtx));
-extern int rtx_equal_p PROTO ((rtx, rtx));
-extern int inequality_comparisons_p PROTO ((rtx));
-extern int dead_or_set_p PROTO ((rtx, rtx));
-extern int dead_or_set_regno_p PROTO ((rtx, int));
-extern int no_labels_between_p PROTO ((rtx, rtx));
-extern int modified_between_p PROTO ((rtx, rtx, rtx));
-extern int modified_in_p PROTO ((rtx, rtx));
-
/* In tree.c */
extern void obfree PROTO ((char *));
struct obstack;
/* In jump.c */
extern int comparison_dominates_p PROTO ((enum rtx_code, enum rtx_code));
extern int condjump_p PROTO ((rtx));
+extern rtx condjump_label PROTO ((rtx));
extern int simplejump_p PROTO ((rtx));
+extern int returnjump_p PROTO ((rtx));
+extern int onlyjump_p PROTO ((rtx));
extern int sets_cc0_p PROTO ((rtx));
extern int invert_jump PROTO ((rtx, rtx));
extern int rtx_renumbered_equal_p PROTO ((rtx, rtx));
extern int true_regnum PROTO ((rtx));
extern int redirect_jump PROTO ((rtx, rtx));
extern void jump_optimize PROTO ((rtx, int, int, int));
+extern void rebuild_jump_labels PROTO ((rtx));
extern void thread_jumps PROTO ((rtx, int, int));
extern int redirect_exp PROTO ((rtx *, rtx, rtx, rtx));
extern int rtx_equal_for_thread_p PROTO ((rtx, rtx, rtx));
extern int can_reverse_comparison_p PROTO ((rtx, rtx));
extern void delete_for_peephole PROTO ((rtx, rtx));
extern int condjump_in_parallel_p PROTO ((rtx));
+extern void never_reached_warning PROTO ((rtx));
/* Flags for jump_optimize() */
#define JUMP_CROSS_JUMP 1
extern int get_max_uid PROTO ((void));
extern int in_sequence_p PROTO ((void));
extern void force_next_line_note PROTO ((void));
+extern void clear_emit_caches PROTO ((void));
extern void init_emit PROTO ((void));
extern void init_emit_once PROTO ((int));
extern void push_topmost_sequence PROTO ((void));
extern void reverse_comparison PROTO ((rtx));
extern void set_new_first_and_last_insn PROTO ((rtx, rtx));
extern void set_new_first_and_last_label_num PROTO ((int, int));
+extern void set_new_last_label_num PROTO ((int));
extern void unshare_all_rtl PROTO ((rtx));
extern void set_last_insn PROTO ((rtx));
extern void link_cc0_insns PROTO ((rtx));
extern void add_insn PROTO ((rtx));
extern void add_insn_before PROTO ((rtx, rtx));
extern void add_insn_after PROTO ((rtx, rtx));
+extern void remove_insn PROTO ((rtx));
extern void reorder_insns_with_line_notes PROTO ((rtx, rtx, rtx));
extern void emit_insn_after_with_line_notes PROTO ((rtx, rtx, rtx));
extern enum rtx_code classify_insn PROTO ((rtx));
-extern void init_virtual_regs PROTO ((void));
extern rtx emit PROTO ((rtx));
/* Query and clear/ restore no_line_numbers. This is used by the
switch / case handling in stmt.c to give proper line numbers in
#ifdef BUFSIZ
extern void schedule_insns PROTO ((FILE *));
#endif
-#ifdef HAIFA
-extern void fix_sched_param PROTO ((char *, char *));
-#endif
+extern void fix_sched_param PROTO ((const char *, const char *));
/* In print-rtl.c */
extern void debug_rtx PROTO ((rtx));
/* In loop.c */
extern void init_loop PROTO ((void));
+extern rtx libcall_other_reg PROTO ((rtx, rtx));
#ifdef BUFSIZ
extern void loop_optimize PROTO ((rtx, FILE *, int, int));
#endif
/* In function.c */
extern void reposition_prologue_and_epilogue_notes PROTO ((rtx));
extern void thread_prologue_and_epilogue_insns PROTO ((rtx));
+extern int prologue_epilogue_contains PROTO ((rtx));
extern void use_variable PROTO ((rtx));
extern HOST_WIDE_INT get_frame_size PROTO ((void));
extern void preserve_rtl_expr_result PROTO ((rtx));
/* In reload.c */
extern int operands_match_p PROTO ((rtx, rtx));
extern int safe_from_earlyclobber PROTO ((rtx, rtx));
-extern int strict_memory_address_p PROTO ((enum machine_mode, rtx));
-
-/* In recog.c */
-extern int memory_address_p PROTO ((enum machine_mode, rtx));
-extern int constrain_operands PROTO ((int, int));
-extern int mode_dependent_address_p PROTO ((rtx));
-extern void init_recog_no_volatile PROTO ((void));
-extern int offsettable_memref_p PROTO ((rtx));
-extern int offsettable_nonstrict_memref_p PROTO ((rtx));
-extern int reg_fits_class_p PROTO ((rtx, register enum reg_class,
- int, enum machine_mode));
-extern int check_asm_operands PROTO ((rtx));
-extern int address_operand PROTO ((rtx, enum machine_mode));
-extern int const_int_operand PROTO ((rtx, enum machine_mode));
-extern int const_double_operand PROTO ((rtx, enum machine_mode));
-extern int general_operand PROTO ((rtx, enum machine_mode));
-extern int immediate_operand PROTO ((rtx, enum machine_mode));
-extern int nonimmediate_operand PROTO ((rtx, enum machine_mode));
-extern int memory_operand PROTO ((rtx, enum machine_mode));
-extern int nonmemory_operand PROTO ((rtx, enum machine_mode));
-extern int push_operand PROTO ((rtx, enum machine_mode));
-extern int register_operand PROTO ((rtx, enum machine_mode));
-extern int scratch_operand PROTO ((rtx, enum machine_mode));
-extern int indirect_operand PROTO ((rtx, enum machine_mode));
-extern int mode_independent_operand PROTO ((rtx, enum machine_mode));
-extern int comparison_operator PROTO ((rtx, enum machine_mode));
-extern void init_recog_no_volatile PROTO ((void));
-extern void init_recog PROTO ((void));
-extern int validate_replace_rtx PROTO ((rtx, rtx, rtx));
-extern int offsettable_address_p PROTO ((int, enum machine_mode, rtx));
-extern int next_insn_tests_no_inequality PROTO ((rtx));
-extern int recog_memoized PROTO ((rtx));
-extern int validate_change PROTO ((rtx, rtx *, rtx, int));
-extern int apply_change_group PROTO ((void));
-extern void cancel_changes PROTO ((int));
-extern int num_validated_changes PROTO ((void));
-
-/* In insn-recog.c */
-extern int recog PROTO ((rtx, rtx, int *));
/* In stmt.c */
+extern void set_file_and_line_for_stmt PROTO ((char *, int));
extern void expand_null_return PROTO((void));
extern void emit_jump PROTO ((rtx));
extern int preserve_subexpressions_p PROTO ((void));
#endif
/* In flow.c */
-extern void allocate_for_life_analysis PROTO ((void));
-extern void recompute_reg_usage PROTO ((rtx));
+extern void allocate_bb_life_data PROTO ((void));
+extern void allocate_reg_life_data PROTO ((void));
+extern void recompute_reg_usage PROTO ((rtx, int));
#ifdef BUFSIZ
+extern void print_rtl_with_bb PROTO ((FILE *, rtx));
extern void dump_flow_info PROTO ((FILE *));
#endif
+extern void free_bb_mem PROTO ((void));
+extern void replace_insns PROTO ((rtx, rtx, rtx, rtx));
/* In expmed.c */
extern void init_expmed PROTO ((void));
/* In gcse.c */
#ifdef BUFSIZ
-extern void gcse_main PROTO ((rtx, FILE *));
+extern int gcse_main PROTO ((rtx, FILE *));
#endif
/* In global.c */
#ifdef BUFSIZ
extern void dump_local_alloc PROTO ((FILE *));
#endif
-extern void local_alloc PROTO ((void));
+extern int local_alloc PROTO ((void));
+extern int function_invariant_p PROTO ((rtx));
/* In reload1.c */
extern void reload_cse_regs PROTO ((rtx));
extern void init_caller_save PROTO ((void));
/* In profile.c */
-extern void init_branch_prob PROTO ((char *));
+extern void init_branch_prob PROTO ((const char *));
#ifdef BUFSIZ
extern void branch_prob PROTO ((rtx, FILE *));
extern void end_branch_prob PROTO ((FILE *));
#ifdef BUFSIZ
extern void reg_to_stack PROTO ((rtx, FILE *));
#endif
-extern int stack_regs_mentioned_p PROTO ((rtx));
/* In fold-const.c */
extern int add_double PROTO ((HOST_WIDE_INT, HOST_WIDE_INT,
extern void bss_section PROTO ((void));
extern int in_data_section PROTO ((void));
extern int supports_one_only PROTO ((void));
+extern void init_varasm_once PROTO ((void));
/* In rtl.c */
extern void init_rtl PROTO ((void));
extern void rtx_free PROTO ((rtx));
+/* Redefine abort to report an internal error w/o coredump, and
+ reporting the location of the error in the source file. This logic
+ is duplicated in rtl.h and tree.h because every file that needs the
+ special abort includes one or both. toplev.h gets too few files,
+ system.h gets too many. */
+
+extern void fancy_abort PROTO((const char *, int, const char *))
+ ATTRIBUTE_NORETURN;
+#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+#define abort() fancy_abort (__FILE__, __LINE__, 0)
+#else
+#define abort() fancy_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__)
+#endif
+
/* In alias.c */
extern int true_dependence PROTO ((rtx, enum machine_mode, rtx,
int (*)(rtx)));
extern int read_dependence PROTO ((rtx, rtx));
extern int anti_dependence PROTO ((rtx, rtx));
extern int output_dependence PROTO ((rtx, rtx));
+extern void mark_constant_function PROTO ((void));
extern void init_alias_once PROTO ((void));
extern void init_alias_analysis PROTO ((void));
extern void end_alias_analysis PROTO ((void));
extern void record_base_value PROTO ((int, rtx, int));
+extern void record_alias_subset PROTO ((int, int));
+extern rtx addr_side_effect_eval PROTO ((rtx, int, int));
+
+#ifdef STACK_REGS
+extern int stack_regs_mentioned PROTO((rtx insn));
+#endif
+
+extern void delete_null_pointer_checks PROTO ((rtx));
#endif /* _RTL_H */