/* RTL utility routines.
- Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* This file is compiled twice: once for the generator programs
+ once for the compiler. */
+#ifdef GENERATOR_FILE
+#include "bconfig.h"
+#else
#include "config.h"
+#endif
+
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "rtl.h"
#include "real.h"
#include "ggc.h"
-#include "errors.h"
-
-\f
-/* Calculate the format for CONST_DOUBLE. This depends on the relative
- widths of HOST_WIDE_INT and REAL_VALUE_TYPE.
-
- We need to go out to e0wwwww, since REAL_ARITHMETIC assumes 16-bits
- per element in REAL_VALUE_TYPE.
-
- This is duplicated in gengenrtl.c.
-
- A number of places assume that there are always at least two 'w'
- slots in a CONST_DOUBLE, so we provide them even if one would suffice. */
-
-#ifdef REAL_ARITHMETIC
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 96
-# define REAL_WIDTH \
- (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# else
-# if MAX_LONG_DOUBLE_TYPE_SIZE == 128
-# define REAL_WIDTH \
- (19*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# else
-# if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
-# define REAL_WIDTH \
- (7*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
-# endif
-# endif
-# endif
-#endif /* REAL_ARITHMETIC */
-
-#ifndef REAL_WIDTH
-# if HOST_BITS_PER_WIDE_INT*2 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 2
-# else
-# if HOST_BITS_PER_WIDE_INT*3 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 3
-# else
-# if HOST_BITS_PER_WIDE_INT*4 >= MAX_LONG_DOUBLE_TYPE_SIZE
-# define REAL_WIDTH 4
-# endif
-# endif
-# endif
-#endif /* REAL_WIDTH */
-
-#if REAL_WIDTH == 1
-# define CONST_DOUBLE_FORMAT "e0ww"
+#ifdef GENERATOR_FILE
+# include "errors.h"
#else
-# if REAL_WIDTH == 2
-# define CONST_DOUBLE_FORMAT "e0ww"
-# else
-# if REAL_WIDTH == 3
-# define CONST_DOUBLE_FORMAT "e0www"
-# else
-# if REAL_WIDTH == 4
-# define CONST_DOUBLE_FORMAT "e0wwww"
-# else
-# if REAL_WIDTH == 5
-# define CONST_DOUBLE_FORMAT "e0wwwww"
-# else
-# define CONST_DOUBLE_FORMAT /* nothing - will cause syntax error */
-# endif
-# endif
-# endif
-# endif
+# include "toplev.h"
#endif
+\f
/* Indexed by rtx code, gives number of operands for an rtx with that code.
Does NOT include rtx header data (code and links). */
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) sizeof FORMAT - 1 ,
-const int rtx_length[NUM_RTX_CODE + 1] = {
+const unsigned char rtx_length[NUM_RTX_CODE] = {
#include "rtl.def"
};
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME ,
-const char * const rtx_name[] = {
+const char * const rtx_name[NUM_RTX_CODE] = {
#include "rtl.def" /* rtl expressions are documented here */
};
#undef DEF_RTL_EXPR
-/* Indexed by machine mode, gives the name of that machine mode.
- This name does not include the letters "mode". */
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) NAME,
-
-const char * const mode_name[] = {
-#include "machmode.def"
-};
-
-#undef DEF_MACHMODE
-
-/* Indexed by machine mode, gives the class mode for GET_MODE_CLASS. */
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) CLASS,
-
-const enum mode_class mode_class[] = {
-#include "machmode.def"
-};
-
-#undef DEF_MACHMODE
-
-/* Indexed by machine mode, gives the length of the mode, in bits.
- GET_MODE_BITSIZE uses this. */
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) BITSIZE,
-
-const unsigned int mode_bitsize[] = {
-#include "machmode.def"
-};
-
-#undef DEF_MACHMODE
-
-/* Indexed by machine mode, gives the length of the mode, in bytes.
- GET_MODE_SIZE uses this. */
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) SIZE,
-
-const unsigned int mode_size[] = {
-#include "machmode.def"
-};
-
-#undef DEF_MACHMODE
-
-/* Indexed by machine mode, gives the length of the mode's subunit.
- GET_MODE_UNIT_SIZE uses this. */
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) UNIT,
-
-const unsigned int mode_unit_size[] = {
-#include "machmode.def" /* machine modes are documented here */
-};
-
-#undef DEF_MACHMODE
-
-/* Indexed by machine mode, gives next wider natural mode
- (QI -> HI -> SI -> DI, etc.) Widening multiply instructions
- use this. */
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) \
- (unsigned char) WIDER,
-
-const unsigned char mode_wider_mode[] = {
-#include "machmode.def" /* machine modes are documented here */
-};
-
-#undef DEF_MACHMODE
-
-#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) \
- ((BITSIZE) >= HOST_BITS_PER_WIDE_INT) ? ~(unsigned HOST_WIDE_INT)0 : ((unsigned HOST_WIDE_INT) 1 << (BITSIZE)) - 1,
-
-/* Indexed by machine mode, gives mask of significant bits in mode. */
-
-const unsigned HOST_WIDE_INT mode_mask_array[] = {
-#include "machmode.def"
-};
-
-/* Indexed by mode class, gives the narrowest mode for each class.
- The Q modes are always of width 1 (2 for complex) - it is impossible
- for any mode to be narrower.
-
- Note that we use QImode instead of BImode for MODE_INT, since
- otherwise the middle end will try to use it for bitfields in
- structures and the like, which we do not want. Only the target
- md file should generate BImode widgets. */
-
-const enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS] = {
- /* MODE_RANDOM */ VOIDmode,
- /* MODE_INT */ QImode,
- /* MODE_FLOAT */ QFmode,
- /* MODE_PARTIAL_INT */ PQImode,
- /* MODE_CC */ CCmode,
- /* MODE_COMPLEX_INT */ CQImode,
- /* MODE_COMPLEX_FLOAT */ QCmode,
- /* MODE_VECTOR_INT */ V2QImode,
- /* MODE_VECTOR_FLOAT */ V2SFmode
-};
-
-
/* Indexed by rtx code, gives a sequence of operand-types for
rtx's of that code. The sequence is a C string in which
each character describes one operand. */
-const char * const rtx_format[] = {
+const char * const rtx_format[NUM_RTX_CODE] = {
/* "*" undefined.
can cause a warning message
"0" field is unused (or used in a phase-dependent manner)
"u" a pointer to another insn
prints the uid of the insn.
"b" is a pointer to a bitmap header.
- "t" is a tree pointer. */
+ "B" is a basic block pointer.
+ "t" is a tree pointer. */
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT ,
#include "rtl.def" /* rtl expressions are defined here */
/* Indexed by rtx code, gives a character representing the "class" of
that rtx code. See rtl.def for documentation on the defined classes. */
-const char rtx_class[] = {
+const enum rtx_class rtx_class[NUM_RTX_CODE] = {
#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS,
#include "rtl.def" /* rtl expressions are defined here */
#undef DEF_RTL_EXPR
};
+/* Indexed by rtx code, gives the size of the rtx in bytes. */
+
+const unsigned char rtx_code_size[NUM_RTX_CODE] = {
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \
+ ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE \
+ ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \
+ : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)),
+
+#include "rtl.def"
+#undef DEF_RTL_EXPR
+};
+
+/* Make sure all NOTE_INSN_* values are negative. */
+extern char NOTE_INSN_MAX_isnt_negative_adjust_NOTE_INSN_BIAS
+[NOTE_INSN_MAX < 0 ? 1 : -1];
+
/* Names for kinds of NOTEs and REG_NOTEs. */
const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS] =
{
- "", "NOTE_INSN_DELETED",
- "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
- "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
- "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
- "NOTE_INSN_FUNCTION_END",
- "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
- "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
- "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
- "NOTE_INSN_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_BEG",
- "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
- "NOTE_INSN_BASIC_BLOCK", "NOTE_INSN_EXPECTED_VALUE"
+ "",
+#define DEF_INSN_NOTE(NAME) #NAME,
+#include "insn-notes.def"
+#undef DEF_INSN_NOTE
};
-const char * const reg_note_name[] =
+const char * const reg_note_name[REG_NOTE_MAX] =
{
- "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_EQUAL",
- "REG_WAS_0", "REG_RETVAL", "REG_LIBCALL", "REG_NONNEG",
- "REG_NO_CONFLICT", "REG_UNUSED", "REG_CC_SETTER", "REG_CC_USER",
- "REG_LABEL", "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
- "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
- "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
- "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
- "REG_NON_LOCAL_GOTO", "REG_SETJMP"
+#define DEF_REG_NOTE(NAME) #NAME,
+#include "reg-notes.def"
+#undef DEF_REG_NOTE
};
+#ifdef GATHER_STATISTICS
+static int rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE];
+static int rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE];
+static int rtvec_alloc_counts;
+static int rtvec_alloc_sizes;
+#endif
+
\f
/* Allocate an rtx vector of N elements.
Store the length, and initialize all elements to zero. */
rtvec
-rtvec_alloc (n)
- int n;
+rtvec_alloc (int n)
{
rtvec rt;
rt = ggc_alloc_rtvec (n);
- /* clear out the vector */
+ /* Clear out the vector. */
memset (&rt->elem[0], 0, n * sizeof (rtx));
PUT_NUM_ELEM (rt, n);
+
+#ifdef GATHER_STATISTICS
+ rtvec_alloc_counts++;
+ rtvec_alloc_sizes += n * sizeof (rtx);
+#endif
+
return rt;
}
+/* Return the number of bytes occupied by rtx value X. */
+
+unsigned int
+rtx_size (rtx x)
+{
+ if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x))
+ return RTX_HDR_SIZE + sizeof (struct block_symbol);
+ return RTX_CODE_SIZE (GET_CODE (x));
+}
+
/* Allocate an rtx of code CODE. The CODE is stored in the rtx;
all the rest is initialized to zero. */
rtx
-rtx_alloc (code)
- RTX_CODE code;
+rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL)
{
rtx rt;
- int n = GET_RTX_LENGTH (code);
- rt = ggc_alloc_rtx (n);
+ rt = (rtx) ggc_alloc_zone_pass_stat (RTX_CODE_SIZE (code), &rtl_zone);
/* We want to clear everything up to the FLD array. Normally, this
is one int, but we don't want to assume that and it isn't very
portable anyway; this is. */
- memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
+ memset (rt, 0, RTX_HDR_SIZE);
PUT_CODE (rt, code);
+
+#ifdef GATHER_STATISTICS
+ rtx_alloc_counts[code]++;
+ rtx_alloc_sizes[code] += RTX_CODE_SIZE (code);
+#endif
+
return rt;
}
except for those few rtx codes that are sharable. */
rtx
-copy_rtx (orig)
- register rtx orig;
+copy_rtx (rtx orig)
{
- register rtx copy;
- register int i, j;
- register RTX_CODE code;
- register const char *format_ptr;
+ rtx copy;
+ int i, j;
+ RTX_CODE code;
+ const char *format_ptr;
code = GET_CODE (orig);
switch (code)
{
case REG:
- case QUEUED:
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
case SYMBOL_REF:
case CODE_LABEL:
case PC:
case CC0:
case SCRATCH:
/* SCRATCH must be shared because they represent distinct values. */
- case ADDRESSOF:
return orig;
+ case CLOBBER:
+ if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER)
+ return orig;
+ break;
case CONST:
/* CONST can be shared if it contains a SYMBOL_REF. If it contains
break;
}
- copy = rtx_alloc (code);
-
- /* Copy the various flags, and other information. We assume that
- all fields need copying, and then clear the fields that should
+ /* Copy the various flags, fields, and other information. We assume
+ that 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));
+ copy = shallow_copy_rtx (orig);
/* We do not copy the USED flag, which is used as a mark bit during
walks over the RTL. */
- copy->used = 0;
+ RTX_FLAG (copy, used) = 0;
/* We do not copy FRAME_RELATED for INSNs. */
- if (GET_RTX_CLASS (code) == 'i')
- copy->frame_related = 0;
- copy->jump = orig->jump;
- copy->call = orig->call;
-
- format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
-
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
- {
- copy->fld[i] = orig->fld[i];
- switch (*format_ptr++)
- {
- case 'e':
- if (XEXP (orig, i) != NULL)
- XEXP (copy, i) = copy_rtx (XEXP (orig, i));
- break;
-
- case 'E':
- case 'V':
- if (XVEC (orig, i) != NULL)
- {
- XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
- for (j = 0; j < XVECLEN (copy, i); j++)
- XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
- }
- break;
-
- case 't':
- case 'w':
- case 'i':
- case 's':
- case 'S':
- case 'T':
- case 'u':
- case '0':
- /* These are left unchanged. */
- break;
-
- default:
- abort ();
- }
- }
- return copy;
-}
-
-/* Similar to `copy_rtx' except that if MAY_SHARE is present, it is
- placed in the result directly, rather than being copied. */
-
-rtx
-copy_most_rtx (orig, may_share)
- register rtx orig;
- register rtx may_share;
-{
- register rtx copy;
- register int i, j;
- register RTX_CODE code;
- register const char *format_ptr;
-
- if (orig == may_share)
- return orig;
-
- code = GET_CODE (orig);
-
- switch (code)
- {
- case REG:
- case QUEUED:
- case CONST_INT:
- case CONST_DOUBLE:
- case SYMBOL_REF:
- case CODE_LABEL:
- case PC:
- case CC0:
- return orig;
- default:
- break;
- }
-
- copy = rtx_alloc (code);
- PUT_MODE (copy, GET_MODE (orig));
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
- copy->frame_related = orig->frame_related;
+ if (INSN_P (orig))
+ RTX_FLAG (copy, frame_related) = 0;
+ RTX_FLAG (copy, jump) = RTX_FLAG (orig, jump);
+ RTX_FLAG (copy, call) = RTX_FLAG (orig, call);
format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
- {
- switch (*format_ptr++)
- {
- case 'e':
- XEXP (copy, i) = XEXP (orig, i);
- if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share)
- XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
- break;
-
- case 'u':
- XEXP (copy, i) = XEXP (orig, i);
- break;
-
- case 'E':
- case 'V':
- XVEC (copy, i) = XVEC (orig, i);
- if (XVEC (orig, i) != NULL)
- {
- XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
- for (j = 0; j < XVECLEN (copy, i); j++)
- XVECEXP (copy, i, j)
- = copy_most_rtx (XVECEXP (orig, i, j), may_share);
- }
- break;
-
- case 'w':
- XWINT (copy, i) = XWINT (orig, i);
- break;
-
- case 'n':
- case 'i':
- XINT (copy, i) = XINT (orig, i);
- break;
-
- case 't':
- XTREE (copy, i) = XTREE (orig, i);
- break;
-
- case 's':
- case 'S':
- XSTR (copy, i) = XSTR (orig, i);
- break;
-
- case '0':
- /* Copy this through the wide int field; that's safest. */
- X0WINT (copy, i) = X0WINT (orig, i);
- break;
-
- default:
- abort ();
- }
- }
+ switch (*format_ptr++)
+ {
+ case 'e':
+ if (XEXP (orig, i) != NULL)
+ XEXP (copy, i) = copy_rtx (XEXP (orig, i));
+ break;
+
+ case 'E':
+ case 'V':
+ if (XVEC (orig, i) != NULL)
+ {
+ XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
+ for (j = 0; j < XVECLEN (copy, i); j++)
+ XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j));
+ }
+ break;
+
+ case 't':
+ case 'w':
+ case 'i':
+ case 's':
+ case 'S':
+ case 'T':
+ case 'u':
+ case 'B':
+ case '0':
+ /* These are left unchanged. */
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
return copy;
}
/* Create a new copy of an rtx. Only copy just one level. */
+
rtx
-shallow_copy_rtx (orig)
- rtx orig;
+shallow_copy_rtx_stat (rtx orig MEM_STAT_DECL)
{
- register int i;
- register RTX_CODE code = GET_CODE (orig);
- register rtx copy = rtx_alloc (code);
-
- PUT_MODE (copy, GET_MODE (orig));
- copy->in_struct = orig->in_struct;
- copy->volatil = orig->volatil;
- copy->unchanging = orig->unchanging;
- copy->integrated = orig->integrated;
- copy->frame_related = orig->frame_related;
-
- for (i = 0; i < GET_RTX_LENGTH (code); i++)
- copy->fld[i] = orig->fld[i];
+ unsigned int size;
+ rtx copy;
+ size = rtx_size (orig);
+ copy = (rtx) ggc_alloc_zone_pass_stat (size, &rtl_zone);
+ memcpy (copy, orig, size);
return copy;
}
\f
-/* This is 1 until after the rtl generation pass. */
-int rtx_equal_function_value_matters;
-
/* Nonzero when we are generating CONCATs. */
int generating_concat_p;
+
+/* Nonzero when we are expanding trees to RTL. */
+int currently_expanding_to_rtl;
+
\f
/* Return 1 if X and Y are identical-looking rtx's.
This is the Lisp function EQUAL for rtx arguments. */
int
-rtx_equal_p (x, y)
- rtx x, y;
+rtx_equal_p (rtx x, rtx y)
{
- register int i;
- register int j;
- register enum rtx_code code;
- register const char *fmt;
+ int i;
+ int j;
+ enum rtx_code code;
+ const char *fmt;
if (x == y)
return 1;
switch (code)
{
case REG:
- /* Until rtl generation is complete, don't consider a reference to the
- return register of the current function the same as the return from a
- called function. This eases the job of function integration. Once the
- distinction is no longer needed, they can be considered equivalent. */
- return (REGNO (x) == REGNO (y)
- && (! rtx_equal_function_value_matters
- || REG_FUNCTION_VALUE_P (x) == REG_FUNCTION_VALUE_P (y)));
+ return (REGNO (x) == REGNO (y));
case LABEL_REF:
return XEXP (x, 0) == XEXP (y, 0);
}
/* Compare the elements. If any pair of corresponding elements
- fail to match, return 0 for the whole things. */
+ fail to match, return 0 for the whole thing. */
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
case 'S':
case 's':
- if (strcmp (XSTR (x, i), XSTR (y, i)))
+ if ((XSTR (x, i) || XSTR (y, i))
+ && (! XSTR (x, i) || ! XSTR (y, i)
+ || strcmp (XSTR (x, i), XSTR (y, i))))
return 0;
break;
contain anything but integers and other rtx's,
except for within LABEL_REFs and SYMBOL_REFs. */
default:
- abort ();
+ gcc_unreachable ();
}
}
return 1;
}
+
+void
+dump_rtx_statistics (void)
+{
+#ifdef GATHER_STATISTICS
+ int i;
+ int total_counts = 0;
+ int total_sizes = 0;
+ fprintf (stderr, "\nRTX Kind Count Bytes\n");
+ fprintf (stderr, "---------------------------------------\n");
+ for (i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++)
+ if (rtx_alloc_counts[i])
+ {
+ fprintf (stderr, "%-20s %7d %10d\n", GET_RTX_NAME (i),
+ rtx_alloc_counts[i], rtx_alloc_sizes[i]);
+ total_counts += rtx_alloc_counts[i];
+ total_sizes += rtx_alloc_sizes[i];
+ }
+ if (rtvec_alloc_counts)
+ {
+ fprintf (stderr, "%-20s %7d %10d\n", "rtvec",
+ rtvec_alloc_counts, rtvec_alloc_sizes);
+ total_counts += rtvec_alloc_counts;
+ total_sizes += rtvec_alloc_sizes;
+ }
+ fprintf (stderr, "---------------------------------------\n");
+ fprintf (stderr, "%-20s %7d %10d\n",
+ "Total", total_counts, total_sizes);
+ fprintf (stderr, "---------------------------------------\n");
+#endif
+}
\f
#if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
void
-rtl_check_failed_bounds (r, n, file, line, func)
- rtx r;
- int n;
- const char *file;
- int line;
- const char *func;
+rtl_check_failed_bounds (rtx r, int n, const char *file, int line,
+ const char *func)
{
internal_error
- ("RTL check: access of elt %d of `%s' with last elt %d in %s, at %s:%d",
+ ("RTL check: access of elt %d of '%s' with last elt %d in %s, at %s:%d",
n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1,
func, trim_filename (file), line);
}
void
-rtl_check_failed_type1 (r, n, c1, file, line, func)
- rtx r;
- int n;
- int c1;
- const char *file;
- int line;
- const char *func;
+rtl_check_failed_type1 (rtx r, int n, int c1, const char *file, int line,
+ const char *func)
{
internal_error
("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d",
}
void
-rtl_check_failed_type2 (r, n, c1, c2, file, line, func)
- rtx r;
- int n;
- int c1;
- int c2;
- const char *file;
- int line;
- const char *func;
+rtl_check_failed_type2 (rtx r, int n, int c1, int c2, const char *file,
+ int line, const char *func)
{
internal_error
("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d",
}
void
-rtl_check_failed_code1 (r, code, file, line, func)
- rtx r;
- enum rtx_code code;
- const char *file;
- int line;
- const char *func;
+rtl_check_failed_code1 (rtx r, enum rtx_code code, const char *file,
+ int line, const char *func)
{
- internal_error ("RTL check: expected code `%s', have `%s' in %s, at %s:%d",
+ internal_error ("RTL check: expected code '%s', have '%s' in %s, at %s:%d",
GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func,
trim_filename (file), line);
}
void
-rtl_check_failed_code2 (r, code1, code2, file, line, func)
- rtx r;
- enum rtx_code code1, code2;
- const char *file;
- int line;
- const char *func;
+rtl_check_failed_code2 (rtx r, enum rtx_code code1, enum rtx_code code2,
+ const char *file, int line, const char *func)
{
internal_error
- ("RTL check: expected code `%s' or `%s', have `%s' in %s, at %s:%d",
+ ("RTL check: expected code '%s' or '%s', have '%s' in %s, at %s:%d",
GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)),
func, trim_filename (file), line);
}
+void
+rtl_check_failed_code_mode (rtx r, enum rtx_code code, enum machine_mode mode,
+ bool not_mode, const char *file, int line,
+ const char *func)
+{
+ internal_error ((not_mode
+ ? ("RTL check: expected code '%s' and not mode '%s', "
+ "have code '%s' and mode '%s' in %s, at %s:%d")
+ : ("RTL check: expected code '%s' and mode '%s', "
+ "have code '%s' and mode '%s' in %s, at %s:%d")),
+ GET_RTX_NAME (code), GET_MODE_NAME (mode),
+ GET_RTX_NAME (GET_CODE (r)), GET_MODE_NAME (GET_MODE (r)),
+ func, trim_filename (file), line);
+}
+
+/* Report that line LINE of FILE tried to access the block symbol fields
+ of a non-block symbol. FUNC is the function that contains the line. */
+
+void
+rtl_check_failed_block_symbol (const char *file, int line, const char *func)
+{
+ internal_error
+ ("RTL check: attempt to treat non-block symbol as a block symbol "
+ "in %s, at %s:%d", func, trim_filename (file), line);
+}
+
/* XXX Maybe print the vector? */
void
-rtvec_check_failed_bounds (r, n, file, line, func)
- rtvec r;
- int n;
- const char *file;
- int line;
- const char *func;
+rtvec_check_failed_bounds (rtvec r, int n, const char *file, int line,
+ const char *func)
{
internal_error
("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d",
n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
}
#endif /* ENABLE_RTL_CHECKING */
+
+#if defined ENABLE_RTL_FLAG_CHECKING
+void
+rtl_check_failed_flag (const char *name, rtx r, const char *file,
+ int line, const char *func)
+{
+ internal_error
+ ("RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d",
+ name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line);
+}
+#endif /* ENABLE_RTL_FLAG_CHECKING */