rtl.c (dump_and_abort): Remove.

* rtl.c (dump_and_abort): Remove.
        (fatal_with_file_and_line): New.
        (fatal_expected_char): New.
        (read_rtx_lineno, read_rtx_filename): New.
        (read_skip_spaces): Track line number.
        (read_name): Use fatal_with_file_and_line.
        (read_rtx): Use fatal_expected_char.  Track line number.
        * rtl.h (read_rtx_filename, read_rtx_lineno): Declare.

        * print-rtl.c (print_rtx): Don't special case LABEL_REF argument
        if it isn't a CODE_LABEL.

        * genattr.c (main): Set read_rtx_filename.
        * genattrtab.c (main): Likewise.
        * gencodes.c (main): Likewise.
        * genconfig.c (main): Likewise.
        * genemit.c (main): Likewise.
        * genextract.c (main): Likewise.
        * genflags.c (main): Likewise.
        * genopinit.c (main): Likewise.
        * genoutput.c (main): Likewise.
        * genpeep.c (main): Likewise.

        * genrecog.c (decision_test.u.insn): Add `lineno'.
        (pattern_lineno, error_count): New variables.
        (message_with_line): New.
        (add_to_sequence): Break out checking code to ...
        (validate_pattern): ... here.  Detect SET_DEST matching CONST_INT.
        (merge_insn): Use message_with_line.
        (make_insn_sequence): Use validate_pattern.  Record insn lineno.
        (main): Set read_rtx_filename, pattern_lineno.  Exit early on error.

From-SVN: r29957
This commit is contained in:
Richard Henderson 1999-10-13 20:43:49 -07:00 committed by Richard Henderson
parent a59f86402f
commit bcdaba58ff
15 changed files with 343 additions and 100 deletions

View File

@ -1,3 +1,37 @@
Wed Oct 13 20:35:16 1999 Richard Henderson <rth@cygnus.com>
* rtl.c (dump_and_abort): Remove.
(fatal_with_file_and_line): New.
(fatal_expected_char): New.
(read_rtx_lineno, read_rtx_filename): New.
(read_skip_spaces): Track line number.
(read_name): Use fatal_with_file_and_line.
(read_rtx): Use fatal_expected_char. Track line number.
* rtl.h (read_rtx_filename, read_rtx_lineno): Declare.
* print-rtl.c (print_rtx): Don't special case LABEL_REF argument
if it isn't a CODE_LABEL.
* genattr.c (main): Set read_rtx_filename.
* genattrtab.c (main): Likewise.
* gencodes.c (main): Likewise.
* genconfig.c (main): Likewise.
* genemit.c (main): Likewise.
* genextract.c (main): Likewise.
* genflags.c (main): Likewise.
* genopinit.c (main): Likewise.
* genoutput.c (main): Likewise.
* genpeep.c (main): Likewise.
* genrecog.c (decision_test.u.insn): Add `lineno'.
(pattern_lineno, error_count): New variables.
(message_with_line): New.
(add_to_sequence): Break out checking code to ...
(validate_pattern): ... here. Detect SET_DEST matching CONST_INT.
(merge_insn): Use message_with_line.
(make_insn_sequence): Use validate_pattern. Record insn lineno.
(main): Set read_rtx_filename, pattern_lineno. Exit early on error.
Wed Oct 13 22:01:35 1999 J"orn Rennecke <amylaar@cygnus.co.uk>
* expr.c (store_constructor): Clear union if constructor is empty.

View File

@ -251,6 +251,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
printf ("/* Generated automatically by the program `genattr'\n\
from the machine description file `md'. */\n\n");

View File

@ -6000,6 +6000,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
/* Set up true and false rtx's */
true_rtx = rtx_alloc (CONST_INT);

View File

@ -98,6 +98,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
printf ("/* Generated automatically by the program `gencodes'\n\
from the machine description file `md'. */\n\n");

View File

@ -297,6 +297,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
printf ("/* Generated automatically by the program `genconfig'\n\
from the machine description file `md'. */\n\n");

View File

@ -787,6 +787,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
/* Assign sequential codes to all entries in the machine description
in parallel with the tables in insn-output.c. */

View File

@ -400,6 +400,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
/* Assign sequential codes to all entries in the machine description
in parallel with the tables in insn-output.c. */

View File

@ -224,6 +224,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
printf ("/* Generated automatically by the program `genflags'\n\
from the machine description file `md'. */\n\n");

View File

@ -327,6 +327,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
printf ("/* Generated automatically by the program `genopinit'\n\
from the machine description file `md'. */\n\n");

View File

@ -907,6 +907,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
output_prologue ();
next_code_number = 0;

View File

@ -424,6 +424,7 @@ main (argc, argv)
perror (argv[1]);
return (FATAL_EXIT_CODE);
}
read_rtx_filename = argv[1];
printf ("/* Generated automatically by the program `genpeep'\n\
from the machine description file `md'. */\n\n");

View File

@ -115,6 +115,7 @@ struct decision_test
struct {
int code_number; /* Insn number matched. */
int lineno; /* Line number of the insn. */
int num_clobbers_to_add; /* Number of CLOBBERs to be added. */
} insn;
} u;
@ -170,6 +171,12 @@ static int next_index;
allocate in each subroutine we make. */
static int max_depth;
/* The line number of the start of the pattern currently being processed. */
static int pattern_lineno;
/* Count of errors. */
static int error_count;
/* This table contains a list of the rtl codes that can possibly match a
predicate defined in recog.c. The function `maybe_both_true' uses it to
@ -213,6 +220,8 @@ static struct decision *new_decision
PROTO((const char *, struct decision_head *));
static struct decision_test *new_decision_test
PROTO((enum decision_type, struct decision_test ***));
static void validate_pattern
PROTO((rtx, int));
static struct decision *add_to_sequence
PROTO((rtx, struct decision_head *, const char *, enum routine_type, int));
@ -284,6 +293,29 @@ static void debug_decision_2
extern void debug_decision
PROTO((struct decision *));
static void
message_with_line VPROTO ((int lineno, const char *msg, ...))
{
#ifndef ANSI_PROTOTYPES
int lineno;
const char *msg;
#endif
va_list ap;
VA_START (ap, msg);
#ifndef ANSI_PROTOTYPES
lineno = va_arg (ap, int);
msg = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
vfprintf (stderr, msg, ap);
fputc ('\n', stderr);
va_end (ap);
}
/* Create a new node in sequence after LAST. */
static struct decision *
@ -324,6 +356,142 @@ new_decision_test (type, pplace)
return test;
}
/* Check for various errors in patterns. */
static void
validate_pattern (pattern, set_dest)
rtx pattern;
int set_dest;
{
const char *fmt;
RTX_CODE code;
int i, j, len;
code = GET_CODE (pattern);
switch (code)
{
case MATCH_SCRATCH:
case MATCH_INSN:
return;
case MATCH_OPERAND:
{
const char *pred_name = XSTR (pattern, 1);
if (pred_name[0] != 0)
{
/* See if we know about this predicate and save its number. If
we do, and it only accepts one code, note that fact. The
predicate `const_int_operand' only tests for a CONST_INT, so
if we do so we can avoid calling it at all.
Finally, if we know that the predicate does not allow
CONST_INT, we know that the only way the predicate can match
is if the modes match (here we use the kludge of relying on
the fact that "address_operand" accepts CONST_INT; otherwise,
it would have to be a special case), so we can test the mode
(but we need not). This fact should considerably simplify the
generated code. */
for (i = 0; i < (int) NUM_KNOWN_PREDS; i++)
if (! strcmp (preds[i].name, pred_name))
break;
if (i < (int) NUM_KNOWN_PREDS)
{
int j, allows_const_int;
allows_const_int = 0;
for (j = 0; preds[i].codes[j] != 0; j++)
if (preds[i].codes[j] == CONST_INT)
{
allows_const_int = 1;
break;
}
if (allows_const_int && set_dest)
{
message_with_line (pattern_lineno,
"warning: `%s' accepts const_int,",
pred_name);
message_with_line (pattern_lineno,
" and used as destination of a set");
}
}
else
{
#ifdef PREDICATE_CODES
/* If the port has a list of the predicates it uses but
omits one, warn. */
message_with_line (pattern_lineno, "warning: `%s' not in PREDICATE_CODES", pred_name);
#endif
}
}
return;
}
case SET:
/* The operands of a SET must have the same mode unless one
is VOIDmode. */
if (GET_MODE (SET_SRC (pattern)) != VOIDmode
&& GET_MODE (SET_DEST (pattern)) != VOIDmode
&& GET_MODE (SET_SRC (pattern)) != GET_MODE (SET_DEST (pattern))
/* The mode of an ADDRESS_OPERAND is the mode of the memory
reference, not the mode of the address. */
&& ! (GET_CODE (SET_SRC (pattern)) == MATCH_OPERAND
&& ! strcmp (XSTR (SET_SRC (pattern), 1), "address_operand")))
{
message_with_line (pattern_lineno,
"mode mismatch in set: %smode vs %smode",
GET_MODE_NAME (GET_MODE (SET_DEST (pattern))),
GET_MODE_NAME (GET_MODE (SET_SRC (pattern))));
error_count++;
}
validate_pattern (SET_DEST (pattern), 1);
validate_pattern (SET_SRC (pattern), 0);
return;
case LABEL_REF:
if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
{
message_with_line (pattern_lineno,
"operand to label_ref %smode not VOIDmode",
GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
error_count++;
}
break;
default:
break;
}
fmt = GET_RTX_FORMAT (code);
len = GET_RTX_LENGTH (code);
for (i = 0; i < len; i++)
{
switch (fmt[i])
{
case 'e': case 'u':
validate_pattern (XEXP (pattern, i), 0);
break;
case 'E':
for (j = 0; j < XVECLEN (pattern, i); j++)
validate_pattern (XVECEXP (pattern, i, j), 0);
break;
case 'i': case 'w': case '0': case 's':
break;
default:
abort ();
}
}
}
/* Create a chain of nodes to verify that an rtl expression matches
PATTERN.
@ -465,15 +633,7 @@ add_to_sequence (pattern, last, position, insn_type, top)
}
}
else
{
test->u.pred.index = -1;
#ifdef PREDICATE_CODES
/* If the port has a list of the predicates it uses but
omits one, warn. */
fprintf (stderr, "Warning: `%s' not in PREDICATE_CODES\n",
pred_name);
#endif
}
test->u.pred.index = -1;
}
/* Can't enforce a mode if we allow const_int. */
@ -526,32 +686,6 @@ add_to_sequence (pattern, last, position, insn_type, top)
pattern = XEXP (pattern, 0);
goto restart;
case SET:
/* The operands of a SET must have the same mode unless one
is VOIDmode. */
if (GET_MODE (SET_SRC (pattern)) != VOIDmode
&& GET_MODE (SET_DEST (pattern)) != VOIDmode
&& GET_MODE (SET_SRC (pattern)) != GET_MODE (SET_DEST (pattern))
/* The mode of an ADDRESS_OPERAND is the mode of the memory
reference, not the mode of the address. */
&& ! (GET_CODE (SET_SRC (pattern)) == MATCH_OPERAND
&& ! strcmp (XSTR (SET_SRC (pattern), 1), "address_operand")))
{
print_rtl (stderr, pattern);
fputc ('\n', stderr);
fatal ("mode mismatch in SET");
}
break;
case LABEL_REF:
if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
{
print_rtl (stderr, pattern);
fputc ('\n', stderr);
fatal ("operand to LABEL_REF not VOIDmode");
}
break;
default:
break;
}
@ -966,11 +1100,12 @@ merge_accept_insn (oldd, addd)
}
else
{
fatal ("Two actions at one point in tree for insns \"%s\" (%d) and \"%s\" (%d)",
get_insn_name (old->u.insn.code_number),
old->u.insn.code_number,
get_insn_name (add->u.insn.code_number),
add->u.insn.code_number);
message_with_line (add->u.insn.lineno, "`%s' matches `%s'",
get_insn_name (add->u.insn.code_number),
get_insn_name (old->u.insn.code_number));
message_with_line (old->u.insn.lineno, "previous definition of `%s'",
get_insn_name (old->u.insn.code_number));
error_count++;
}
}
@ -2015,6 +2150,8 @@ make_insn_sequence (insn, type)
PUT_MODE (x, VOIDmode);
}
validate_pattern (x, 0);
memset(&head, 0, sizeof(head));
last = add_to_sequence (x, &head, "", type, 1);
@ -2037,6 +2174,7 @@ make_insn_sequence (insn, type)
test = new_decision_test (DT_accept_insn, &place);
test->u.insn.code_number = next_insn_code;
test->u.insn.lineno = pattern_lineno;
test->u.insn.num_clobbers_to_add = 0;
switch (type)
@ -2103,6 +2241,7 @@ make_insn_sequence (insn, type)
test = new_decision_test (DT_accept_insn, &place);
test->u.insn.code_number = next_insn_code;
test->u.insn.lineno = pattern_lineno;
test->u.insn.num_clobbers_to_add = XVECLEN (x, 0) - i;
merge_trees (&head, &clobber_head);
@ -2171,6 +2310,7 @@ main (argc, argv)
perror (argv[1]);
return FATAL_EXIT_CODE;
}
read_rtx_filename = argv[1];
next_insn_code = 0;
next_index = 0;
@ -2185,6 +2325,7 @@ main (argc, argv)
if (c == EOF)
break;
ungetc (c, infile);
pattern_lineno = read_rtx_lineno;
desc = read_rtx (infile);
if (GET_CODE (desc) == DEFINE_INSN)
@ -2209,6 +2350,9 @@ main (argc, argv)
next_index++;
}
if (error_count)
return FATAL_EXIT_CODE;
puts ("\n\n");
process_tree (&recog_tree, RECOG);

View File

@ -200,6 +200,7 @@ print_rtx (in_rtx)
break;
case 'e':
do_e:
indent += 2;
if (!sawclose)
fprintf (outfile, " ");
@ -298,6 +299,9 @@ print_rtx (in_rtx)
case 'u':
if (XEXP (in_rtx, i) != NULL)
{
if (GET_CODE (XEXP (in_rtx, i)) != CODE_LABEL)
goto do_e;
if (flag_dump_unnumbered)
fputc ('#', outfile);
else

154
gcc/rtl.c
View File

@ -259,7 +259,9 @@ const char * const reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "
"REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
"REG_EH_RETHROW", "REG_SAVE_NOTE" };
static void dump_and_abort PROTO((int, int, FILE *)) ATTRIBUTE_NORETURN;
static void fatal_with_file_and_line PVPROTO((FILE *, const char *, ...))
ATTRIBUTE_NORETURN;
static void fatal_expected_char PROTO((FILE *, int, int)) ATTRIBUTE_NORETURN;
static void read_name PROTO((char *, FILE *));
static const char *trim_filename PROTO((const char *));
@ -582,30 +584,64 @@ shallow_copy_rtx (orig)
/* Subroutines of read_rtx. */
/* The current line number for the file. */
int read_rtx_lineno = 1;
/* The filename for aborting with file and line. */
const char *read_rtx_filename = "<unknown>";
static void
fatal_with_file_and_line VPROTO((FILE *infile, const char *msg, ...))
{
#ifndef ANSI_PROTOTYPES
FILE *infile;
const char *msg;
#endif
va_list ap;
char context[64];
size_t i;
int c;
VA_START (ap, msg);
#ifndef ANSI_PROTOTYPES
infile = va_arg (ap, FILE *);
msg = va_arg (ap, const char *);
#endif
fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
vfprintf (stderr, msg, ap);
putc ('\n', stderr);
/* Gather some following context. */
for (i = 0; i < sizeof(context)-1; ++i)
{
c = getc (infile);
if (c == EOF)
break;
if (c == '\r' || c == '\n')
break;
context[i] = c;
}
context[i] = '\0';
fprintf (stderr, "%s:%d: following context is `%s'\n",
read_rtx_filename, read_rtx_lineno, context);
va_end (ap);
exit (1);
}
/* Dump code after printing a message. Used when read_rtx finds
invalid data. */
static void
dump_and_abort (expected_c, actual_c, infile)
int expected_c, actual_c;
fatal_expected_char (infile, expected_c, actual_c)
FILE *infile;
int expected_c, actual_c;
{
int c, i;
if (expected_c >= 0)
fprintf (stderr,
"Expected character %c. Found character %c.",
expected_c, actual_c);
fprintf (stderr, " At file position: %ld\n", ftell (infile));
fprintf (stderr, "Following characters are:\n\t");
for (i = 0; i < 200; i++)
{
c = getc (infile);
if (EOF == c) break;
putc (c, stderr);
}
fprintf (stderr, "Aborting.\n");
abort ();
fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
expected_c, actual_c);
}
/* Read chars from INFILE until a non-whitespace char
@ -618,33 +654,48 @@ read_skip_spaces (infile)
FILE *infile;
{
register int c;
while ((c = getc (infile)))
while (1)
{
if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
;
else if (c == ';')
c = getc (infile);
switch (c)
{
while ((c = getc (infile)) && c != '\n' && c != EOF)
;
}
else if (c == '/')
{
register int prevc;
c = getc (infile);
if (c != '*')
dump_and_abort ('*', c, infile);
case '\n':
read_rtx_lineno++;
break;
case ' ': case '\t': case '\f': case '\r':
break;
case ';':
do
c = getc (infile);
while (c != '\n' && c != EOF);
read_rtx_lineno++;
break;
case '/':
{
register int prevc;
c = getc (infile);
if (c != '*')
fatal_expected_char (infile, '*', c);
prevc = 0;
while ((c = getc (infile)) && c != EOF)
{
if (prevc == '*' && c == '/')
break;
prevc = c;
}
prevc = 0;
while ((c = getc (infile)) && c != EOF)
{
if (c == '\n')
read_rtx_lineno++;
else if (prevc == '*' && c == '/')
break;
prevc = c;
}
}
break;
default:
return c;
}
else break;
}
return c;
}
/* Read an rtx code name into the buffer STR[].
@ -675,10 +726,9 @@ read_name (str, infile)
c = getc (infile);
}
if (p == str)
{
fprintf (stderr, "missing name or number");
dump_and_abort (-1, -1, infile);
}
fatal_with_file_and_line (infile, "missing name or number");
if (c == '\n')
read_rtx_lineno++;
*p = 0;
}
@ -745,12 +795,12 @@ read_rtx (infile)
struct rtx_list
{
struct rtx_list *next;
rtx value; /* Value of this node... */
rtx value; /* Value of this node. */
};
c = read_skip_spaces (infile); /* Should be open paren. */
if (c != '(')
dump_and_abort ('(', c, infile);
fatal_expected_char (infile, '(', c);
read_name (tmp_char, infile);
@ -831,7 +881,7 @@ read_rtx (infile)
c = read_skip_spaces (infile);
if (c != '[')
dump_and_abort ('[', c, infile);
fatal_expected_char (infile, '[', c);
/* add expressions to a list, while keeping a count */
next_rtx = NULL;
@ -887,11 +937,13 @@ read_rtx (infile)
c = read_skip_spaces (infile);
}
if (c != '"')
dump_and_abort ('"', c, infile);
fatal_expected_char (infile, '"', c);
while (1)
{
c = getc (infile); /* Read the string */
if (c == '\n')
read_rtx_lineno++;
if (c == '\\')
{
c = getc (infile); /* Read the string */
@ -916,7 +968,7 @@ read_rtx (infile)
{
c = read_skip_spaces (infile);
if (c != ')')
dump_and_abort (')', c, infile);
fatal_expected_char (infile, ')', c);
}
XSTR (return_rtx, i) = stringbuf;
}
@ -959,7 +1011,7 @@ read_rtx (infile)
c = read_skip_spaces (infile);
if (c != ')')
dump_and_abort (')', c, infile);
fatal_expected_char (infile, ')', c);
return return_rtx;
}

View File

@ -963,10 +963,6 @@ extern rtx gen_rtx PVPROTO((enum rtx_code,
enum machine_mode, ...));
extern rtvec gen_rtvec PVPROTO((int, ...));
#ifdef BUFSIZ
extern rtx read_rtx PROTO((FILE *));
#endif
extern char *oballoc PROTO((int));
extern char *permalloc PROTO((int));
extern rtx rtx_alloc PROTO((RTX_CODE));
@ -1379,10 +1375,6 @@ extern void gcc_obstack_init PROTO ((struct obstack *));
extern void pop_obstacks PROTO ((void));
extern void push_obstacks PROTO ((struct obstack *,
struct obstack *));
#ifdef BUFSIZ
extern int read_skip_spaces PROTO ((FILE *));
#endif
/* In cse.c */
struct cse_basic_block_data;
extern int rtx_cost PROTO ((rtx, enum rtx_code));
@ -1642,7 +1634,6 @@ extern void rrotate_double PROTO ((HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT *));
/* In calls.c */
/* Emit library call. */
extern void emit_library_call PVPROTO ((rtx, int, enum machine_mode,
int, ...));
extern rtx emit_library_call_value PVPROTO((rtx, rtx, int,
@ -1662,6 +1653,14 @@ extern void init_varasm_once PROTO ((void));
extern void init_rtl PROTO ((void));
extern void rtx_free PROTO ((rtx));
#ifdef BUFSIZ
extern int read_skip_spaces PROTO ((FILE *));
extern rtx read_rtx PROTO ((FILE *));
#endif
extern const char *read_rtx_filename;
extern int read_rtx_lineno;
/* 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