genpreds.c (process_define_predicate): Move most processing to gensupport.c.
gcc/ * genpreds.c (process_define_predicate): Move most processing to gensupport.c. Continue to validate the expression. * genrecog.c (did_you_mean_codes, compute_predicate_codes) (process_define_predicate): Move processing to gensupport.c. (main): Remove DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE cases. * gensupport.c (did_you_mean_codes): Moved from genrecog.c. (compute_predicate_codes): Moved from genrecog.c. Add lineno argument. (valid_predicate_name_p): New function, split out from old genpreds.c:process_define_predicate. (process_define_predicate): New function, combining code from old genpreds.c and genrecog.c functions. (process_rtx): Call it for DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE. From-SVN: r172315
This commit is contained in:
parent
6308e208c2
commit
77059241d8
|
@ -1,3 +1,20 @@
|
||||||
|
2011-04-12 Richard Sandiford <richard.sandiford@linaro.org>
|
||||||
|
|
||||||
|
* genpreds.c (process_define_predicate): Move most processing
|
||||||
|
to gensupport.c. Continue to validate the expression.
|
||||||
|
* genrecog.c (did_you_mean_codes, compute_predicate_codes)
|
||||||
|
(process_define_predicate): Move processing to gensupport.c.
|
||||||
|
(main): Remove DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE cases.
|
||||||
|
* gensupport.c (did_you_mean_codes): Moved from genrecog.c.
|
||||||
|
(compute_predicate_codes): Moved from genrecog.c. Add lineno
|
||||||
|
argument.
|
||||||
|
(valid_predicate_name_p): New function, split out from old
|
||||||
|
genpreds.c:process_define_predicate.
|
||||||
|
(process_define_predicate): New function, combining code from
|
||||||
|
old genpreds.c and genrecog.c functions.
|
||||||
|
(process_rtx): Call it for DEFINE_PREDICATE and
|
||||||
|
DEFINE_SPECIAL_PREDICATE.
|
||||||
|
|
||||||
2011-04-12 Richard Sandiford <richard.sandiford@linaro.org>
|
2011-04-12 Richard Sandiford <richard.sandiford@linaro.org>
|
||||||
|
|
||||||
* config/arm/arm.c (arm_print_operand): Use MEM_SIZE to get the
|
* config/arm/arm.c (arm_print_operand): Use MEM_SIZE to get the
|
||||||
|
|
|
@ -93,34 +93,7 @@ validate_exp (rtx exp, const char *name, int lineno)
|
||||||
static void
|
static void
|
||||||
process_define_predicate (rtx defn, int lineno)
|
process_define_predicate (rtx defn, int lineno)
|
||||||
{
|
{
|
||||||
struct pred_data *pred;
|
validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno);
|
||||||
const char *p;
|
|
||||||
|
|
||||||
if (!ISALPHA (XSTR (defn, 0)[0]) && XSTR (defn, 0)[0] != '_')
|
|
||||||
goto bad_name;
|
|
||||||
for (p = XSTR (defn, 0) + 1; *p; p++)
|
|
||||||
if (!ISALNUM (*p) && *p != '_')
|
|
||||||
goto bad_name;
|
|
||||||
|
|
||||||
if (validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pred = XCNEW (struct pred_data);
|
|
||||||
pred->name = XSTR (defn, 0);
|
|
||||||
pred->exp = XEXP (defn, 1);
|
|
||||||
pred->c_block = XSTR (defn, 2);
|
|
||||||
|
|
||||||
if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
|
|
||||||
pred->special = true;
|
|
||||||
|
|
||||||
add_predicate (pred);
|
|
||||||
return;
|
|
||||||
|
|
||||||
bad_name:
|
|
||||||
error_with_line (lineno,
|
|
||||||
"%s: predicate name must be a valid C function name",
|
|
||||||
XSTR (defn, 0));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a predicate, if it has an embedded C block, write the block
|
/* Given a predicate, if it has an embedded C block, write the block
|
||||||
|
|
218
gcc/genrecog.c
218
gcc/genrecog.c
|
@ -170,219 +170,6 @@ static int max_depth;
|
||||||
|
|
||||||
/* The line number of the start of the pattern currently being processed. */
|
/* The line number of the start of the pattern currently being processed. */
|
||||||
static int pattern_lineno;
|
static int pattern_lineno;
|
||||||
|
|
||||||
/* 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
|
|
||||||
function 'maybe_both_true' uses it to deduce that there are no
|
|
||||||
expressions that can be matches by certain pairs of tree nodes.
|
|
||||||
Also, if a predicate can match only one code, we can hardwire that
|
|
||||||
code into the node testing the predicate.
|
|
||||||
|
|
||||||
Some predicates are flagged as special. validate_pattern will not
|
|
||||||
warn about modeless match_operand expressions if they have a
|
|
||||||
special predicate. Predicates that allow only constants are also
|
|
||||||
treated as special, for this purpose.
|
|
||||||
|
|
||||||
validate_pattern will warn about predicates that allow non-lvalues
|
|
||||||
when they appear in destination operands.
|
|
||||||
|
|
||||||
Calculating the set of rtx codes that can possibly be accepted by a
|
|
||||||
predicate expression EXP requires a three-state logic: any given
|
|
||||||
subexpression may definitively accept a code C (Y), definitively
|
|
||||||
reject a code C (N), or may have an indeterminate effect (I). N
|
|
||||||
and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
|
|
||||||
truth tables.
|
|
||||||
|
|
||||||
a b a&b a|b
|
|
||||||
Y Y Y Y
|
|
||||||
N Y N Y
|
|
||||||
N N N N
|
|
||||||
I Y I Y
|
|
||||||
I N N I
|
|
||||||
I I I I
|
|
||||||
|
|
||||||
We represent Y with 1, N with 0, I with 2. If any code is left in
|
|
||||||
an I state by the complete expression, we must assume that that
|
|
||||||
code can be accepted. */
|
|
||||||
|
|
||||||
#define N 0
|
|
||||||
#define Y 1
|
|
||||||
#define I 2
|
|
||||||
|
|
||||||
#define TRISTATE_AND(a,b) \
|
|
||||||
((a) == I ? ((b) == N ? N : I) : \
|
|
||||||
(b) == I ? ((a) == N ? N : I) : \
|
|
||||||
(a) && (b))
|
|
||||||
|
|
||||||
#define TRISTATE_OR(a,b) \
|
|
||||||
((a) == I ? ((b) == Y ? Y : I) : \
|
|
||||||
(b) == I ? ((a) == Y ? Y : I) : \
|
|
||||||
(a) || (b))
|
|
||||||
|
|
||||||
#define TRISTATE_NOT(a) \
|
|
||||||
((a) == I ? I : !(a))
|
|
||||||
|
|
||||||
/* 0 means no warning about that code yet, 1 means warned. */
|
|
||||||
static char did_you_mean_codes[NUM_RTX_CODE];
|
|
||||||
|
|
||||||
/* Recursively calculate the set of rtx codes accepted by the
|
|
||||||
predicate expression EXP, writing the result to CODES. */
|
|
||||||
static void
|
|
||||||
compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
|
|
||||||
{
|
|
||||||
char op0_codes[NUM_RTX_CODE];
|
|
||||||
char op1_codes[NUM_RTX_CODE];
|
|
||||||
char op2_codes[NUM_RTX_CODE];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
switch (GET_CODE (exp))
|
|
||||||
{
|
|
||||||
case AND:
|
|
||||||
compute_predicate_codes (XEXP (exp, 0), op0_codes);
|
|
||||||
compute_predicate_codes (XEXP (exp, 1), op1_codes);
|
|
||||||
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
||||||
codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IOR:
|
|
||||||
compute_predicate_codes (XEXP (exp, 0), op0_codes);
|
|
||||||
compute_predicate_codes (XEXP (exp, 1), op1_codes);
|
|
||||||
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
||||||
codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
|
|
||||||
break;
|
|
||||||
case NOT:
|
|
||||||
compute_predicate_codes (XEXP (exp, 0), op0_codes);
|
|
||||||
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
||||||
codes[i] = TRISTATE_NOT (op0_codes[i]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IF_THEN_ELSE:
|
|
||||||
/* 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);
|
|
||||||
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
||||||
codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
|
|
||||||
TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
|
|
||||||
op2_codes[i]));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MATCH_CODE:
|
|
||||||
/* MATCH_CODE allows a specified list of codes. However, if it
|
|
||||||
does not apply to the top level of the expression, it does not
|
|
||||||
constrain the set of codes for the top level. */
|
|
||||||
if (XSTR (exp, 1)[0] != '\0')
|
|
||||||
{
|
|
||||||
memset (codes, Y, NUM_RTX_CODE);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset (codes, N, NUM_RTX_CODE);
|
|
||||||
{
|
|
||||||
const char *next_code = XSTR (exp, 0);
|
|
||||||
const char *code;
|
|
||||||
|
|
||||||
if (*next_code == '\0')
|
|
||||||
{
|
|
||||||
error_with_line (pattern_lineno, "empty match_code expression");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((code = scan_comma_elt (&next_code)) != 0)
|
|
||||||
{
|
|
||||||
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')
|
|
||||||
{
|
|
||||||
codes[i] = Y;
|
|
||||||
found_it = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found_it)
|
|
||||||
{
|
|
||||||
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'
|
|
||||||
&& !did_you_mean_codes[i])
|
|
||||||
{
|
|
||||||
did_you_mean_codes[i] = 1;
|
|
||||||
message_with_line (pattern_lineno, "(did you mean \"%s\"?)", GET_RTX_NAME (i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MATCH_OPERAND:
|
|
||||||
/* MATCH_OPERAND disallows the set of codes that the named predicate
|
|
||||||
disallows, and is indeterminate for the codes that it does allow. */
|
|
||||||
{
|
|
||||||
struct pred_data *p = lookup_predicate (XSTR (exp, 1));
|
|
||||||
if (!p)
|
|
||||||
{
|
|
||||||
error_with_line (pattern_lineno,
|
|
||||||
"reference to unknown predicate '%s'",
|
|
||||||
XSTR (exp, 1));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
||||||
codes[i] = p->codes[i] ? I : N;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case MATCH_TEST:
|
|
||||||
/* (match_test WHATEVER) is completely indeterminate. */
|
|
||||||
memset (codes, I, NUM_RTX_CODE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef TRISTATE_OR
|
|
||||||
#undef TRISTATE_AND
|
|
||||||
#undef TRISTATE_NOT
|
|
||||||
|
|
||||||
/* Process a define_predicate expression: compute the set of predicates
|
|
||||||
that can be matched, and record this as a known predicate. */
|
|
||||||
static void
|
|
||||||
process_define_predicate (rtx desc)
|
|
||||||
{
|
|
||||||
struct pred_data *pred = XCNEW (struct pred_data);
|
|
||||||
char codes[NUM_RTX_CODE];
|
|
||||||
int i;
|
|
||||||
|
|
||||||
pred->name = XSTR (desc, 0);
|
|
||||||
if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
|
|
||||||
pred->special = 1;
|
|
||||||
|
|
||||||
compute_predicate_codes (XEXP (desc, 1), codes);
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_RTX_CODE; i++)
|
|
||||||
if (codes[i] != N)
|
|
||||||
add_predicate_code (pred, (enum rtx_code) i);
|
|
||||||
|
|
||||||
add_predicate (pred);
|
|
||||||
}
|
|
||||||
#undef I
|
|
||||||
#undef N
|
|
||||||
#undef Y
|
|
||||||
|
|
||||||
|
|
||||||
static struct decision *new_decision
|
static struct decision *new_decision
|
||||||
(const char *, struct decision_head *);
|
(const char *, struct decision_head *);
|
||||||
|
@ -2716,11 +2503,6 @@ main (int argc, char **argv)
|
||||||
|
|
||||||
switch (GET_CODE (desc))
|
switch (GET_CODE (desc))
|
||||||
{
|
{
|
||||||
case DEFINE_PREDICATE:
|
|
||||||
case DEFINE_SPECIAL_PREDICATE:
|
|
||||||
process_define_predicate (desc);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DEFINE_INSN:
|
case DEFINE_INSN:
|
||||||
h = make_insn_sequence (desc, RECOG);
|
h = make_insn_sequence (desc, RECOG);
|
||||||
merge_trees (&recog_tree, &h);
|
merge_trees (&recog_tree, &h);
|
||||||
|
|
244
gcc/gensupport.c
244
gcc/gensupport.c
|
@ -109,6 +109,247 @@ gen_rtx_CONST_INT (enum machine_mode ARG_UNUSED (mode),
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
function 'maybe_both_true' uses it to deduce that there are no
|
||||||
|
expressions that can be matches by certain pairs of tree nodes.
|
||||||
|
Also, if a predicate can match only one code, we can hardwire that
|
||||||
|
code into the node testing the predicate.
|
||||||
|
|
||||||
|
Some predicates are flagged as special. validate_pattern will not
|
||||||
|
warn about modeless match_operand expressions if they have a
|
||||||
|
special predicate. Predicates that allow only constants are also
|
||||||
|
treated as special, for this purpose.
|
||||||
|
|
||||||
|
validate_pattern will warn about predicates that allow non-lvalues
|
||||||
|
when they appear in destination operands.
|
||||||
|
|
||||||
|
Calculating the set of rtx codes that can possibly be accepted by a
|
||||||
|
predicate expression EXP requires a three-state logic: any given
|
||||||
|
subexpression may definitively accept a code C (Y), definitively
|
||||||
|
reject a code C (N), or may have an indeterminate effect (I). N
|
||||||
|
and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
|
||||||
|
truth tables.
|
||||||
|
|
||||||
|
a b a&b a|b
|
||||||
|
Y Y Y Y
|
||||||
|
N Y N Y
|
||||||
|
N N N N
|
||||||
|
I Y I Y
|
||||||
|
I N N I
|
||||||
|
I I I I
|
||||||
|
|
||||||
|
We represent Y with 1, N with 0, I with 2. If any code is left in
|
||||||
|
an I state by the complete expression, we must assume that that
|
||||||
|
code can be accepted. */
|
||||||
|
|
||||||
|
#define N 0
|
||||||
|
#define Y 1
|
||||||
|
#define I 2
|
||||||
|
|
||||||
|
#define TRISTATE_AND(a,b) \
|
||||||
|
((a) == I ? ((b) == N ? N : I) : \
|
||||||
|
(b) == I ? ((a) == N ? N : I) : \
|
||||||
|
(a) && (b))
|
||||||
|
|
||||||
|
#define TRISTATE_OR(a,b) \
|
||||||
|
((a) == I ? ((b) == Y ? Y : I) : \
|
||||||
|
(b) == I ? ((a) == Y ? Y : I) : \
|
||||||
|
(a) || (b))
|
||||||
|
|
||||||
|
#define TRISTATE_NOT(a) \
|
||||||
|
((a) == I ? I : !(a))
|
||||||
|
|
||||||
|
/* 0 means no warning about that code yet, 1 means warned. */
|
||||||
|
static char did_you_mean_codes[NUM_RTX_CODE];
|
||||||
|
|
||||||
|
/* Recursively calculate the set of rtx codes accepted by the
|
||||||
|
predicate expression EXP, writing the result to CODES. LINENO is
|
||||||
|
the line number on which the directive containing EXP appeared. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
compute_predicate_codes (rtx exp, int lineno, char codes[NUM_RTX_CODE])
|
||||||
|
{
|
||||||
|
char op0_codes[NUM_RTX_CODE];
|
||||||
|
char op1_codes[NUM_RTX_CODE];
|
||||||
|
char op2_codes[NUM_RTX_CODE];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch (GET_CODE (exp))
|
||||||
|
{
|
||||||
|
case AND:
|
||||||
|
compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
|
||||||
|
compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
|
||||||
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
||||||
|
codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IOR:
|
||||||
|
compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
|
||||||
|
compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
|
||||||
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
||||||
|
codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
|
||||||
|
break;
|
||||||
|
case NOT:
|
||||||
|
compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
|
||||||
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
||||||
|
codes[i] = TRISTATE_NOT (op0_codes[i]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IF_THEN_ELSE:
|
||||||
|
/* a ? b : c accepts the same codes as (a & b) | (!a & c). */
|
||||||
|
compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
|
||||||
|
compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
|
||||||
|
compute_predicate_codes (XEXP (exp, 2), lineno, op2_codes);
|
||||||
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
||||||
|
codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
|
||||||
|
TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
|
||||||
|
op2_codes[i]));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MATCH_CODE:
|
||||||
|
/* MATCH_CODE allows a specified list of codes. However, if it
|
||||||
|
does not apply to the top level of the expression, it does not
|
||||||
|
constrain the set of codes for the top level. */
|
||||||
|
if (XSTR (exp, 1)[0] != '\0')
|
||||||
|
{
|
||||||
|
memset (codes, Y, NUM_RTX_CODE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset (codes, N, NUM_RTX_CODE);
|
||||||
|
{
|
||||||
|
const char *next_code = XSTR (exp, 0);
|
||||||
|
const char *code;
|
||||||
|
|
||||||
|
if (*next_code == '\0')
|
||||||
|
{
|
||||||
|
error_with_line (lineno, "empty match_code expression");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((code = scan_comma_elt (&next_code)) != 0)
|
||||||
|
{
|
||||||
|
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')
|
||||||
|
{
|
||||||
|
codes[i] = Y;
|
||||||
|
found_it = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!found_it)
|
||||||
|
{
|
||||||
|
error_with_line (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'
|
||||||
|
&& !did_you_mean_codes[i])
|
||||||
|
{
|
||||||
|
did_you_mean_codes[i] = 1;
|
||||||
|
message_with_line (lineno, "(did you mean \"%s\"?)",
|
||||||
|
GET_RTX_NAME (i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MATCH_OPERAND:
|
||||||
|
/* MATCH_OPERAND disallows the set of codes that the named predicate
|
||||||
|
disallows, and is indeterminate for the codes that it does allow. */
|
||||||
|
{
|
||||||
|
struct pred_data *p = lookup_predicate (XSTR (exp, 1));
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
error_with_line (lineno, "reference to unknown predicate '%s'",
|
||||||
|
XSTR (exp, 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
||||||
|
codes[i] = p->codes[i] ? I : N;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case MATCH_TEST:
|
||||||
|
/* (match_test WHATEVER) is completely indeterminate. */
|
||||||
|
memset (codes, I, NUM_RTX_CODE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_with_line (lineno,
|
||||||
|
"'%s' cannot be used in a define_predicate expression",
|
||||||
|
GET_RTX_NAME (GET_CODE (exp)));
|
||||||
|
memset (codes, I, NUM_RTX_CODE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef TRISTATE_OR
|
||||||
|
#undef TRISTATE_AND
|
||||||
|
#undef TRISTATE_NOT
|
||||||
|
|
||||||
|
/* Return true if NAME is a valid predicate name. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
valid_predicate_name_p (const char *name)
|
||||||
|
{
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
if (!ISALPHA (name[0]) && name[0] != '_')
|
||||||
|
return false;
|
||||||
|
for (p = name + 1; *p; p++)
|
||||||
|
if (!ISALNUM (*p) && *p != '_')
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process define_predicate directive DESC, which appears on line number
|
||||||
|
LINENO. Compute the set of codes that can be matched, and record this
|
||||||
|
as a known predicate. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
process_define_predicate (rtx desc, int lineno)
|
||||||
|
{
|
||||||
|
struct pred_data *pred;
|
||||||
|
char codes[NUM_RTX_CODE];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!valid_predicate_name_p (XSTR (desc, 0)))
|
||||||
|
{
|
||||||
|
error_with_line (lineno,
|
||||||
|
"%s: predicate name must be a valid C function name",
|
||||||
|
XSTR (desc, 0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pred = XCNEW (struct pred_data);
|
||||||
|
pred->name = XSTR (desc, 0);
|
||||||
|
pred->exp = XEXP (desc, 1);
|
||||||
|
pred->c_block = XSTR (desc, 2);
|
||||||
|
if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
|
||||||
|
pred->special = true;
|
||||||
|
|
||||||
|
compute_predicate_codes (XEXP (desc, 1), lineno, codes);
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_RTX_CODE; i++)
|
||||||
|
if (codes[i] != N)
|
||||||
|
add_predicate_code (pred, (enum rtx_code) i);
|
||||||
|
|
||||||
|
add_predicate (pred);
|
||||||
|
}
|
||||||
|
#undef I
|
||||||
|
#undef N
|
||||||
|
#undef Y
|
||||||
|
|
||||||
/* Queue PATTERN on LIST_TAIL. Return the address of the new queue
|
/* Queue PATTERN on LIST_TAIL. Return the address of the new queue
|
||||||
element. */
|
element. */
|
||||||
|
|
||||||
|
@ -182,6 +423,9 @@ process_rtx (rtx desc, int lineno)
|
||||||
|
|
||||||
case DEFINE_PREDICATE:
|
case DEFINE_PREDICATE:
|
||||||
case DEFINE_SPECIAL_PREDICATE:
|
case DEFINE_SPECIAL_PREDICATE:
|
||||||
|
process_define_predicate (desc, lineno);
|
||||||
|
/* Fall through. */
|
||||||
|
|
||||||
case DEFINE_CONSTRAINT:
|
case DEFINE_CONSTRAINT:
|
||||||
case DEFINE_REGISTER_CONSTRAINT:
|
case DEFINE_REGISTER_CONSTRAINT:
|
||||||
case DEFINE_MEMORY_CONSTRAINT:
|
case DEFINE_MEMORY_CONSTRAINT:
|
||||||
|
|
Loading…
Reference in New Issue