/* Generate code from machine description to recognize rtl as insns.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
This file is part of GCC.
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)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but WITHOUT
License for more details.
You should have received a copy of the GNU General Public License
- 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. */
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
/* This program is used to produce insn-recog.c, which contains a
#include "tm.h"
#include "rtl.h"
#include "errors.h"
+#include "read-md.h"
#include "gensupport.h"
#define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
struct decision *last;
};
+/* These types are roughly in the order in which we'd like to test them. */
+enum decision_type
+{
+ DT_num_insns,
+ DT_mode, DT_code, DT_veclen,
+ DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
+ DT_const_int,
+ DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
+ DT_accept_op, DT_accept_insn
+};
+
/* A single test. The two accept types aren't tests per-se, but
their equality (or lack thereof) does affect tree merging so
it is convenient to keep them here. */
/* A linked list through the tests attached to a node. */
struct decision_test *next;
- /* These types are roughly in the order in which we'd like to test them. */
- enum decision_type
- {
- DT_num_insns,
- DT_mode, DT_code, DT_veclen,
- DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
- DT_const_int,
- DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
- DT_accept_op, DT_accept_insn
- } type;
+ enum decision_type type;
union
{
/* The line number of the start of the pattern currently being processed. */
static int pattern_lineno;
-
-/* Count of errors. */
-static int error_count;
\f
-/* Predicate handling.
+/* Predicate handling.
We construct from the machine description a table mapping each
predicate to a list of the rtl codes it can possibly match. The
break;
case IF_THEN_ELSE:
- /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
+ /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
compute_predicate_codes (XEXP (exp, 0), op0_codes);
compute_predicate_codes (XEXP (exp, 1), op1_codes);
compute_predicate_codes (XEXP (exp, 2), op2_codes);
if (*next_code == '\0')
{
- message_with_line (pattern_lineno, "empty match_code expression");
- error_count++;
+ error_with_line (pattern_lineno, "empty match_code expression");
break;
}
{
size_t n = next_code - code;
int found_it = 0;
-
+
for (i = 0; i < NUM_RTX_CODE; i++)
if (!strncmp (code, GET_RTX_NAME (i), n)
&& GET_RTX_NAME (i)[n] == '\0')
}
if (!found_it)
{
- message_with_line (pattern_lineno, "match_code \"%.*s\" matches nothing",
- (int) n, code);
- error_count ++;
+ error_with_line (pattern_lineno,
+ "match_code \"%.*s\" matches nothing",
+ (int) n, code);
for (i = 0; i < NUM_RTX_CODE; i++)
if (!strncasecmp (code, GET_RTX_NAME (i), n)
&& GET_RTX_NAME (i)[n] == '\0'
struct pred_data *p = lookup_predicate (XSTR (exp, 1));
if (!p)
{
- message_with_line (pattern_lineno,
- "reference to unknown predicate '%s'",
- XSTR (exp, 1));
- error_count++;
+ error_with_line (pattern_lineno,
+ "reference to unknown predicate '%s'",
+ XSTR (exp, 1));
break;
}
for (i = 0; i < NUM_RTX_CODE; i++)
break;
default:
- message_with_line (pattern_lineno,
- "'%s' cannot be used in a define_predicate expression",
- GET_RTX_NAME (GET_CODE (exp)));
- error_count++;
+ error_with_line (pattern_lineno,
+ "'%s' cannot be used in a define_predicate expression",
+ GET_RTX_NAME (GET_CODE (exp)));
memset (codes, I, NUM_RTX_CODE);
break;
}
static void
process_define_predicate (rtx desc)
{
- struct pred_data *pred = xcalloc (sizeof (struct pred_data), 1);
+ struct pred_data *pred = XCNEW (struct pred_data);
char codes[NUM_RTX_CODE];
- bool seen_one = false;
int i;
pred->name = XSTR (desc, 0);
for (i = 0; i < NUM_RTX_CODE; i++)
if (codes[i] != N)
- {
- pred->codes[i] = true;
- if (GET_RTX_CLASS (i) != RTX_CONST_OBJ)
- pred->allows_non_const = true;
- if (i != REG
- && i != SUBREG
- && i != MEM
- && i != CONCAT
- && i != PARALLEL
- && i != STRICT_LOW_PART)
- pred->allows_non_lvalue = true;
-
- if (seen_one)
- pred->singleton = UNKNOWN;
- else
- {
- pred->singleton = i;
- seen_one = true;
- }
- }
+ add_predicate_code (pred, (enum rtx_code) i);
+
add_predicate (pred);
}
#undef I
static struct decision *
new_decision (const char *position, struct decision_head *last)
{
- struct decision *new = xcalloc (1, sizeof (struct decision));
+ struct decision *new_decision = XCNEW (struct decision);
- new->success = *last;
- new->position = xstrdup (position);
- new->number = next_number++;
+ new_decision->success = *last;
+ new_decision->position = xstrdup (position);
+ new_decision->number = next_number++;
- last->first = last->last = new;
- return new;
+ last->first = last->last = new_decision;
+ return new_decision;
}
/* Create a new test and link it in at PLACE. */
struct decision_test **place = *pplace;
struct decision_test *test;
- test = xmalloc (sizeof (*test));
+ test = XNEW (struct decision_test);
test->next = *place;
test->type = type;
*place = test;
case MATCH_OP_DUP:
case MATCH_PAR_DUP:
if (find_operand (insn, XINT (pattern, 0), pattern) == pattern)
- {
- message_with_line (pattern_lineno,
- "operand %i duplicated before defined",
- XINT (pattern, 0));
- error_count++;
- }
+ error_with_line (pattern_lineno,
+ "operand %i duplicated before defined",
+ XINT (pattern, 0));
break;
case MATCH_OPERAND:
case MATCH_OPERATOR:
&& find_matching_operand (insn, XINT (pattern, 0)))
;
else
- {
- message_with_line (pattern_lineno,
- "operand %d missing in-out reload",
- XINT (pattern, 0));
- error_count++;
- }
- }
- else if (constraints0 != '=' && constraints0 != '+')
- {
- message_with_line (pattern_lineno,
- "operand %d missing output reload",
+ error_with_line (pattern_lineno,
+ "operand %d missing in-out reload",
XINT (pattern, 0));
- error_count++;
}
+ else if (constraints0 != '=' && constraints0 != '+')
+ error_with_line (pattern_lineno,
+ "operand %d missing output reload",
+ XINT (pattern, 0));
}
}
/* The operands of a SET must have the same mode unless one
is VOIDmode. */
else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode)
- {
- message_with_line (pattern_lineno,
- "mode mismatch in set: %smode vs %smode",
- GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
- error_count++;
- }
+ error_with_line (pattern_lineno,
+ "mode mismatch in set: %smode vs %smode",
+ GET_MODE_NAME (dmode), GET_MODE_NAME (smode));
/* If only one of the operands is VOIDmode, and PC or CC0 is
not involved, it's probably a mistake. */
&& GET_CODE (dest) != CC0
&& GET_CODE (src) != PC
&& GET_CODE (src) != CC0
- && GET_CODE (src) != CONST_INT)
+ && !CONST_INT_P (src)
+ && GET_CODE (src) != CALL)
{
const char *which;
which = (dmode == VOIDmode ? "destination" : "source");
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++;
- }
+ error_with_line (pattern_lineno,
+ "operand to label_ref %smode not VOIDmode",
+ GET_MODE_NAME (GET_MODE (XEXP (pattern, 0))));
break;
default:
enum routine_type insn_type, int top)
{
RTX_CODE code;
- struct decision *this, *sub;
+ struct decision *this_decision, *sub;
struct decision_test *test;
struct decision_test **place;
char *subpos;
if (depth > max_depth)
max_depth = depth;
- subpos = xmalloc (depth + 2);
+ subpos = XNEWVAR (char, depth + 2);
strcpy (subpos, position);
subpos[depth + 1] = 0;
- sub = this = new_decision (position, last);
- place = &this->tests;
+ sub = this_decision = new_decision (position, last);
+ place = &this_decision->tests;
restart:
mode = GET_MODE (pattern);
if (fmt[i] == 'i')
{
gcc_assert (i < 2);
-
+
if (!i)
{
test = new_decision_test (DT_elt_zero_int, &place);
before any of the nodes we may have added above. */
if (code != UNKNOWN)
{
- place = &this->tests;
+ place = &this_decision->tests;
test = new_decision_test (DT_code, &place);
test->u.code = code;
}
if (mode != VOIDmode)
{
- place = &this->tests;
+ place = &this_decision->tests;
test = new_decision_test (DT_mode, &place);
test->u.mode = mode;
}
/* If we didn't insert any tests or accept nodes, hork. */
- gcc_assert (this->tests);
+ gcc_assert (this_decision->tests);
ret:
free (subpos);
else if (d2->type == DT_pred && d2->u.pred.data)
{
bool common = false;
- enum rtx_code c;
+ int c;
for (c = 0; c < NUM_RTX_CODE; c++)
if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c])
}
else
{
- 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));
+ error_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++;
}
}
for (first = head->first; first && first->next; first = next)
{
enum decision_type type;
- struct decision *new, *old_last;
+ struct decision *new_dec, *old_last;
type = first->tests->type;
next = first->next;
below our first test. */
if (first->tests->next != NULL)
{
- new = new_decision (first->position, &first->success);
- new->tests = first->tests->next;
+ new_dec = new_decision (first->position, &first->success);
+ new_dec->tests = first->tests->next;
first->tests->next = NULL;
}
if (next->tests->next != NULL)
{
- new = new_decision (next->position, &next->success);
- new->tests = next->tests->next;
+ new_dec = new_decision (next->position, &next->success);
+ new_dec->tests = next->tests->next;
next->tests->next = NULL;
}
- new = next;
+ new_dec = next;
next = next->next;
- new->next = NULL;
- h.first = h.last = new;
+ new_dec->next = NULL;
+ h.first = h.last = new_dec;
merge_trees (head, &h);
}
int odepth = strlen (oldpos);
int ndepth = strlen (newpos);
int depth;
- int old_has_insn, new_has_insn;
/* Pop up as many levels as necessary. */
for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth)
continue;
- /* Hunt for the last [A-Z] in both strings. */
- for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
- if (ISUPPER (oldpos[old_has_insn]))
- break;
- for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
- if (ISUPPER (newpos[new_has_insn]))
- break;
-
/* Go down to desired level. */
while (depth < ndepth)
{
while (p && p->tests->type == DT_pred && p->tests->u.pred.data)
{
const struct pred_data *data = p->tests->u.pred.data;
- RTX_CODE c;
+ int c;
+
for (c = 0; c < NUM_RTX_CODE; c++)
if (codemap[c] && data->codes[c])
goto pred_done;
if (data->codes[c])
{
fputs (" case ", stdout);
- print_code (c);
+ print_code ((enum rtx_code) c);
fputs (":\n", stdout);
codemap[c] = 1;
}
#include \"function.h\"\n\
#include \"insn-config.h\"\n\
#include \"recog.h\"\n\
-#include \"real.h\"\n\
#include \"output.h\"\n\
#include \"flags.h\"\n\
#include \"hard-reg-set.h\"\n\
#include \"resource.h\"\n\
+#include \"diagnostic-core.h\"\n\
#include \"toplev.h\"\n\
#include \"reload.h\"\n\
+#include \"regs.h\"\n\
+#include \"tm-constrs.h\"\n\
\n");
puts ("\n\
if (i != XVECLEN (x, 0))
{
- rtx new;
+ rtx new_rtx;
struct decision_head clobber_head;
/* Build a similar insn without the clobbers. */
if (i == 1)
- new = XVECEXP (x, 0, 0);
+ new_rtx = XVECEXP (x, 0, 0);
else
{
int j;
- new = rtx_alloc (PARALLEL);
- XVEC (new, 0) = rtvec_alloc (i);
+ new_rtx = rtx_alloc (PARALLEL);
+ XVEC (new_rtx, 0) = rtvec_alloc (i);
for (j = i - 1; j >= 0; j--)
- XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
+ XVECEXP (new_rtx, 0, j) = XVECEXP (x, 0, j);
}
/* Recognize it. */
memset (&clobber_head, 0, sizeof(clobber_head));
- last = add_to_sequence (new, &clobber_head, "", type, 1);
+ last = add_to_sequence (new_rtx, &clobber_head, "", type, 1);
/* Find the end of the test chain on the last node. */
for (test = last->tests; test->next; test = test->next)
memset (&split_tree, 0, sizeof split_tree);
memset (&peephole2_tree, 0, sizeof peephole2_tree);
- if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
+ if (!init_rtx_reader_args (argc, argv))
return (FATAL_EXIT_CODE);
next_insn_code = 0;
}
}
- if (error_count || have_error)
+ if (have_error)
return FATAL_EXIT_CODE;
puts ("\n\n");
debug_decision_0 (n, indent + 2, maxdepth - 1);
}
-void
+DEBUG_FUNCTION void
debug_decision (struct decision *d)
{
debug_decision_0 (d, 0, 1000000);
}
-void
+DEBUG_FUNCTION void
debug_decision_list (struct decision *d)
{
while (d)