summaryrefslogtreecommitdiff
path: root/gcc/genrecog.c
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1999-10-14 03:43:49 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>1999-10-14 03:43:49 +0000
commit0922b1b8057a504feec8f1326bb563ad7decf754 (patch)
treefe06a5500da62a2f74458666d1bd2734e008e04b /gcc/genrecog.c
parent226c8875bb1074e0dc0dd3f86ae71b81c5d8ad36 (diff)
downloadgcc-0922b1b8057a504feec8f1326bb563ad7decf754.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@29957 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/genrecog.c')
-rw-r--r--gcc/genrecog.c224
1 files changed, 184 insertions, 40 deletions
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index 0114bc17533..0be55586df3 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -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);