1*38fd1498Szrj /* Generate from machine description:
2*38fd1498Szrj - prototype declarations for operand predicates (tm-preds.h)
3*38fd1498Szrj - function definitions of operand predicates, if defined new-style
4*38fd1498Szrj (insn-preds.c)
5*38fd1498Szrj Copyright (C) 2001-2018 Free Software Foundation, Inc.
6*38fd1498Szrj
7*38fd1498Szrj This file is part of GCC.
8*38fd1498Szrj
9*38fd1498Szrj GCC is free software; you can redistribute it and/or modify
10*38fd1498Szrj it under the terms of the GNU General Public License as published by
11*38fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
12*38fd1498Szrj any later version.
13*38fd1498Szrj
14*38fd1498Szrj GCC is distributed in the hope that it will be useful,
15*38fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
16*38fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*38fd1498Szrj GNU General Public License for more details.
18*38fd1498Szrj
19*38fd1498Szrj You should have received a copy of the GNU General Public License
20*38fd1498Szrj along with GCC; see the file COPYING3. If not see
21*38fd1498Szrj <http://www.gnu.org/licenses/>. */
22*38fd1498Szrj
23*38fd1498Szrj #include "bconfig.h"
24*38fd1498Szrj #include "system.h"
25*38fd1498Szrj #include "coretypes.h"
26*38fd1498Szrj #include "tm.h"
27*38fd1498Szrj #include "rtl.h"
28*38fd1498Szrj #include "errors.h"
29*38fd1498Szrj #include "obstack.h"
30*38fd1498Szrj #include "read-md.h"
31*38fd1498Szrj #include "gensupport.h"
32*38fd1498Szrj
33*38fd1498Szrj static char general_mem[] = { TARGET_MEM_CONSTRAINT, 0 };
34*38fd1498Szrj
35*38fd1498Szrj /* Given a predicate expression EXP, from form NAME at location LOC,
36*38fd1498Szrj verify that it does not contain any RTL constructs which are not
37*38fd1498Szrj valid in predicate definitions. Returns true if EXP is
38*38fd1498Szrj INvalid; issues error messages, caller need not. */
39*38fd1498Szrj static bool
validate_exp(rtx exp,const char * name,file_location loc)40*38fd1498Szrj validate_exp (rtx exp, const char *name, file_location loc)
41*38fd1498Szrj {
42*38fd1498Szrj if (exp == 0)
43*38fd1498Szrj {
44*38fd1498Szrj message_at (loc, "%s: must give a predicate expression", name);
45*38fd1498Szrj return true;
46*38fd1498Szrj }
47*38fd1498Szrj
48*38fd1498Szrj switch (GET_CODE (exp))
49*38fd1498Szrj {
50*38fd1498Szrj /* Ternary, binary, unary expressions: recurse into subexpressions. */
51*38fd1498Szrj case IF_THEN_ELSE:
52*38fd1498Szrj if (validate_exp (XEXP (exp, 2), name, loc))
53*38fd1498Szrj return true;
54*38fd1498Szrj /* fall through */
55*38fd1498Szrj case AND:
56*38fd1498Szrj case IOR:
57*38fd1498Szrj if (validate_exp (XEXP (exp, 1), name, loc))
58*38fd1498Szrj return true;
59*38fd1498Szrj /* fall through */
60*38fd1498Szrj case NOT:
61*38fd1498Szrj return validate_exp (XEXP (exp, 0), name, loc);
62*38fd1498Szrj
63*38fd1498Szrj /* MATCH_CODE might have a syntax error in its path expression. */
64*38fd1498Szrj case MATCH_CODE:
65*38fd1498Szrj {
66*38fd1498Szrj const char *p;
67*38fd1498Szrj for (p = XSTR (exp, 1); *p; p++)
68*38fd1498Szrj {
69*38fd1498Szrj if (!ISDIGIT (*p) && !ISLOWER (*p))
70*38fd1498Szrj {
71*38fd1498Szrj error_at (loc, "%s: invalid character in path "
72*38fd1498Szrj "string '%s'", name, XSTR (exp, 1));
73*38fd1498Szrj return true;
74*38fd1498Szrj }
75*38fd1498Szrj }
76*38fd1498Szrj }
77*38fd1498Szrj gcc_fallthrough ();
78*38fd1498Szrj
79*38fd1498Szrj /* These need no special checking. */
80*38fd1498Szrj case MATCH_OPERAND:
81*38fd1498Szrj case MATCH_TEST:
82*38fd1498Szrj return false;
83*38fd1498Szrj
84*38fd1498Szrj default:
85*38fd1498Szrj error_at (loc, "%s: cannot use '%s' in a predicate expression",
86*38fd1498Szrj name, GET_RTX_NAME (GET_CODE (exp)));
87*38fd1498Szrj return true;
88*38fd1498Szrj }
89*38fd1498Szrj }
90*38fd1498Szrj
91*38fd1498Szrj /* Predicates are defined with (define_predicate) or
92*38fd1498Szrj (define_special_predicate) expressions in the machine description. */
93*38fd1498Szrj static void
process_define_predicate(md_rtx_info * info)94*38fd1498Szrj process_define_predicate (md_rtx_info *info)
95*38fd1498Szrj {
96*38fd1498Szrj validate_exp (XEXP (info->def, 1), XSTR (info->def, 0), info->loc);
97*38fd1498Szrj }
98*38fd1498Szrj
99*38fd1498Szrj /* Given a predicate, if it has an embedded C block, write the block
100*38fd1498Szrj out as a static inline subroutine, and augment the RTL test with a
101*38fd1498Szrj match_test that calls that subroutine. For instance,
102*38fd1498Szrj
103*38fd1498Szrj (define_predicate "basereg_operand"
104*38fd1498Szrj (match_operand 0 "register_operand")
105*38fd1498Szrj {
106*38fd1498Szrj if (GET_CODE (op) == SUBREG)
107*38fd1498Szrj op = SUBREG_REG (op);
108*38fd1498Szrj return REG_POINTER (op);
109*38fd1498Szrj })
110*38fd1498Szrj
111*38fd1498Szrj becomes
112*38fd1498Szrj
113*38fd1498Szrj static inline int basereg_operand_1(rtx op, machine_mode mode)
114*38fd1498Szrj {
115*38fd1498Szrj if (GET_CODE (op) == SUBREG)
116*38fd1498Szrj op = SUBREG_REG (op);
117*38fd1498Szrj return REG_POINTER (op);
118*38fd1498Szrj }
119*38fd1498Szrj
120*38fd1498Szrj (define_predicate "basereg_operand"
121*38fd1498Szrj (and (match_operand 0 "register_operand")
122*38fd1498Szrj (match_test "basereg_operand_1 (op, mode)")))
123*38fd1498Szrj
124*38fd1498Szrj The only wart is that there's no way to insist on a { } string in
125*38fd1498Szrj an RTL template, so we have to handle "" strings. */
126*38fd1498Szrj
127*38fd1498Szrj
128*38fd1498Szrj static void
write_predicate_subfunction(struct pred_data * p)129*38fd1498Szrj write_predicate_subfunction (struct pred_data *p)
130*38fd1498Szrj {
131*38fd1498Szrj const char *match_test_str;
132*38fd1498Szrj rtx match_test_exp, and_exp;
133*38fd1498Szrj
134*38fd1498Szrj if (p->c_block[0] == '\0')
135*38fd1498Szrj return;
136*38fd1498Szrj
137*38fd1498Szrj /* Construct the function-call expression. */
138*38fd1498Szrj obstack_grow (rtl_obstack, p->name, strlen (p->name));
139*38fd1498Szrj obstack_grow (rtl_obstack, "_1 (op, mode)",
140*38fd1498Szrj sizeof "_1 (op, mode)");
141*38fd1498Szrj match_test_str = XOBFINISH (rtl_obstack, const char *);
142*38fd1498Szrj
143*38fd1498Szrj /* Add the function-call expression to the complete expression to be
144*38fd1498Szrj evaluated. */
145*38fd1498Szrj match_test_exp = rtx_alloc (MATCH_TEST);
146*38fd1498Szrj XSTR (match_test_exp, 0) = match_test_str;
147*38fd1498Szrj
148*38fd1498Szrj and_exp = rtx_alloc (AND);
149*38fd1498Szrj XEXP (and_exp, 0) = p->exp;
150*38fd1498Szrj XEXP (and_exp, 1) = match_test_exp;
151*38fd1498Szrj
152*38fd1498Szrj p->exp = and_exp;
153*38fd1498Szrj
154*38fd1498Szrj printf ("static inline int\n"
155*38fd1498Szrj "%s_1 (rtx op, machine_mode mode ATTRIBUTE_UNUSED)\n",
156*38fd1498Szrj p->name);
157*38fd1498Szrj rtx_reader_ptr->print_md_ptr_loc (p->c_block);
158*38fd1498Szrj if (p->c_block[0] == '{')
159*38fd1498Szrj fputs (p->c_block, stdout);
160*38fd1498Szrj else
161*38fd1498Szrj printf ("{\n %s\n}", p->c_block);
162*38fd1498Szrj fputs ("\n\n", stdout);
163*38fd1498Szrj }
164*38fd1498Szrj
165*38fd1498Szrj /* Given a predicate expression EXP, from form NAME, determine whether
166*38fd1498Szrj it refers to the variable given as VAR. */
167*38fd1498Szrj static bool
needs_variable(rtx exp,const char * var)168*38fd1498Szrj needs_variable (rtx exp, const char *var)
169*38fd1498Szrj {
170*38fd1498Szrj switch (GET_CODE (exp))
171*38fd1498Szrj {
172*38fd1498Szrj /* Ternary, binary, unary expressions need a variable if
173*38fd1498Szrj any of their subexpressions do. */
174*38fd1498Szrj case IF_THEN_ELSE:
175*38fd1498Szrj if (needs_variable (XEXP (exp, 2), var))
176*38fd1498Szrj return true;
177*38fd1498Szrj /* fall through */
178*38fd1498Szrj case AND:
179*38fd1498Szrj case IOR:
180*38fd1498Szrj if (needs_variable (XEXP (exp, 1), var))
181*38fd1498Szrj return true;
182*38fd1498Szrj /* fall through */
183*38fd1498Szrj case NOT:
184*38fd1498Szrj return needs_variable (XEXP (exp, 0), var);
185*38fd1498Szrj
186*38fd1498Szrj /* MATCH_CODE uses "op", but nothing else. */
187*38fd1498Szrj case MATCH_CODE:
188*38fd1498Szrj return !strcmp (var, "op");
189*38fd1498Szrj
190*38fd1498Szrj /* MATCH_OPERAND uses "op" and may use "mode". */
191*38fd1498Szrj case MATCH_OPERAND:
192*38fd1498Szrj if (!strcmp (var, "op"))
193*38fd1498Szrj return true;
194*38fd1498Szrj if (!strcmp (var, "mode") && GET_MODE (exp) == VOIDmode)
195*38fd1498Szrj return true;
196*38fd1498Szrj return false;
197*38fd1498Szrj
198*38fd1498Szrj /* MATCH_TEST uses var if XSTR (exp, 0) =~ /\b${var}\b/o; */
199*38fd1498Szrj case MATCH_TEST:
200*38fd1498Szrj {
201*38fd1498Szrj const char *p = XSTR (exp, 0);
202*38fd1498Szrj const char *q = strstr (p, var);
203*38fd1498Szrj if (!q)
204*38fd1498Szrj return false;
205*38fd1498Szrj if (q != p && (ISALNUM (q[-1]) || q[-1] == '_'))
206*38fd1498Szrj return false;
207*38fd1498Szrj q += strlen (var);
208*38fd1498Szrj if (ISALNUM (q[0]) || q[0] == '_')
209*38fd1498Szrj return false;
210*38fd1498Szrj }
211*38fd1498Szrj return true;
212*38fd1498Szrj
213*38fd1498Szrj default:
214*38fd1498Szrj gcc_unreachable ();
215*38fd1498Szrj }
216*38fd1498Szrj }
217*38fd1498Szrj
218*38fd1498Szrj /* Given an RTL expression EXP, find all subexpressions which we may
219*38fd1498Szrj assume to perform mode tests. Normal MATCH_OPERAND does;
220*38fd1498Szrj MATCH_CODE doesn't as such (although certain codes always have
221*38fd1498Szrj VOIDmode); and we have to assume that MATCH_TEST does not.
222*38fd1498Szrj These combine in almost-boolean fashion - the only exception is
223*38fd1498Szrj that (not X) must be assumed not to perform a mode test, whether
224*38fd1498Szrj or not X does.
225*38fd1498Szrj
226*38fd1498Szrj The mark is the RTL /v flag, which is true for subexpressions which
227*38fd1498Szrj do *not* perform mode tests.
228*38fd1498Szrj */
229*38fd1498Szrj #define NO_MODE_TEST(EXP) RTX_FLAG (EXP, volatil)
230*38fd1498Szrj static void
mark_mode_tests(rtx exp)231*38fd1498Szrj mark_mode_tests (rtx exp)
232*38fd1498Szrj {
233*38fd1498Szrj switch (GET_CODE (exp))
234*38fd1498Szrj {
235*38fd1498Szrj case MATCH_OPERAND:
236*38fd1498Szrj {
237*38fd1498Szrj struct pred_data *p = lookup_predicate (XSTR (exp, 1));
238*38fd1498Szrj if (!p)
239*38fd1498Szrj error ("reference to undefined predicate '%s'", XSTR (exp, 1));
240*38fd1498Szrj else if (p->special || GET_MODE (exp) != VOIDmode)
241*38fd1498Szrj NO_MODE_TEST (exp) = 1;
242*38fd1498Szrj }
243*38fd1498Szrj break;
244*38fd1498Szrj
245*38fd1498Szrj case MATCH_CODE:
246*38fd1498Szrj NO_MODE_TEST (exp) = 1;
247*38fd1498Szrj break;
248*38fd1498Szrj
249*38fd1498Szrj case MATCH_TEST:
250*38fd1498Szrj case NOT:
251*38fd1498Szrj NO_MODE_TEST (exp) = 1;
252*38fd1498Szrj break;
253*38fd1498Szrj
254*38fd1498Szrj case AND:
255*38fd1498Szrj mark_mode_tests (XEXP (exp, 0));
256*38fd1498Szrj mark_mode_tests (XEXP (exp, 1));
257*38fd1498Szrj
258*38fd1498Szrj NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
259*38fd1498Szrj && NO_MODE_TEST (XEXP (exp, 1)));
260*38fd1498Szrj break;
261*38fd1498Szrj
262*38fd1498Szrj case IOR:
263*38fd1498Szrj mark_mode_tests (XEXP (exp, 0));
264*38fd1498Szrj mark_mode_tests (XEXP (exp, 1));
265*38fd1498Szrj
266*38fd1498Szrj NO_MODE_TEST (exp) = (NO_MODE_TEST (XEXP (exp, 0))
267*38fd1498Szrj || NO_MODE_TEST (XEXP (exp, 1)));
268*38fd1498Szrj break;
269*38fd1498Szrj
270*38fd1498Szrj case IF_THEN_ELSE:
271*38fd1498Szrj /* A ? B : C does a mode test if (one of A and B) does a mode
272*38fd1498Szrj test, and C does too. */
273*38fd1498Szrj mark_mode_tests (XEXP (exp, 0));
274*38fd1498Szrj mark_mode_tests (XEXP (exp, 1));
275*38fd1498Szrj mark_mode_tests (XEXP (exp, 2));
276*38fd1498Szrj
277*38fd1498Szrj NO_MODE_TEST (exp) = ((NO_MODE_TEST (XEXP (exp, 0))
278*38fd1498Szrj && NO_MODE_TEST (XEXP (exp, 1)))
279*38fd1498Szrj || NO_MODE_TEST (XEXP (exp, 2)));
280*38fd1498Szrj break;
281*38fd1498Szrj
282*38fd1498Szrj default:
283*38fd1498Szrj gcc_unreachable ();
284*38fd1498Szrj }
285*38fd1498Szrj }
286*38fd1498Szrj
287*38fd1498Szrj /* Determine whether the expression EXP is a MATCH_CODE that should
288*38fd1498Szrj be written as a switch statement. */
289*38fd1498Szrj static bool
generate_switch_p(rtx exp)290*38fd1498Szrj generate_switch_p (rtx exp)
291*38fd1498Szrj {
292*38fd1498Szrj return GET_CODE (exp) == MATCH_CODE
293*38fd1498Szrj && strchr (XSTR (exp, 0), ',');
294*38fd1498Szrj }
295*38fd1498Szrj
296*38fd1498Szrj /* Given a predicate, work out where in its RTL expression to add
297*38fd1498Szrj tests for proper modes. Special predicates do not get any such
298*38fd1498Szrj tests. We try to avoid adding tests when we don't have to; in
299*38fd1498Szrj particular, other normal predicates can be counted on to do it for
300*38fd1498Szrj us. */
301*38fd1498Szrj
302*38fd1498Szrj static void
add_mode_tests(struct pred_data * p)303*38fd1498Szrj add_mode_tests (struct pred_data *p)
304*38fd1498Szrj {
305*38fd1498Szrj rtx match_test_exp, and_exp;
306*38fd1498Szrj rtx *pos;
307*38fd1498Szrj
308*38fd1498Szrj /* Don't touch special predicates. */
309*38fd1498Szrj if (p->special)
310*38fd1498Szrj return;
311*38fd1498Szrj
312*38fd1498Szrj /* Check whether the predicate accepts const scalar ints (which always
313*38fd1498Szrj have a stored mode of VOIDmode, but logically have a real mode)
314*38fd1498Szrj and whether it matches anything besides const scalar ints. */
315*38fd1498Szrj bool matches_const_scalar_int_p = false;
316*38fd1498Szrj bool matches_other_p = false;
317*38fd1498Szrj for (int i = 0; i < NUM_RTX_CODE; ++i)
318*38fd1498Szrj if (p->codes[i])
319*38fd1498Szrj switch (i)
320*38fd1498Szrj {
321*38fd1498Szrj case CONST_INT:
322*38fd1498Szrj case CONST_WIDE_INT:
323*38fd1498Szrj /* Special handling for (VOIDmode) LABEL_REFs. */
324*38fd1498Szrj case LABEL_REF:
325*38fd1498Szrj matches_const_scalar_int_p = true;
326*38fd1498Szrj break;
327*38fd1498Szrj
328*38fd1498Szrj case CONST_DOUBLE:
329*38fd1498Szrj if (!TARGET_SUPPORTS_WIDE_INT)
330*38fd1498Szrj matches_const_scalar_int_p = true;
331*38fd1498Szrj matches_other_p = true;
332*38fd1498Szrj break;
333*38fd1498Szrj
334*38fd1498Szrj default:
335*38fd1498Szrj matches_other_p = true;
336*38fd1498Szrj break;
337*38fd1498Szrj }
338*38fd1498Szrj
339*38fd1498Szrj /* There's no need for a mode check if the predicate only accepts
340*38fd1498Szrj constant integers. The code checks in the predicate are enough
341*38fd1498Szrj to establish that the mode is VOIDmode.
342*38fd1498Szrj
343*38fd1498Szrj Note that the predicate itself should check whether a scalar
344*38fd1498Szrj integer is in range of the given mode. */
345*38fd1498Szrj if (!matches_other_p)
346*38fd1498Szrj return;
347*38fd1498Szrj
348*38fd1498Szrj mark_mode_tests (p->exp);
349*38fd1498Szrj
350*38fd1498Szrj /* If the whole expression already tests the mode, we're done. */
351*38fd1498Szrj if (!NO_MODE_TEST (p->exp))
352*38fd1498Szrj return;
353*38fd1498Szrj
354*38fd1498Szrj match_test_exp = rtx_alloc (MATCH_TEST);
355*38fd1498Szrj if (matches_const_scalar_int_p)
356*38fd1498Szrj XSTR (match_test_exp, 0) = ("mode == VOIDmode || GET_MODE (op) == mode"
357*38fd1498Szrj " || GET_MODE (op) == VOIDmode");
358*38fd1498Szrj else
359*38fd1498Szrj XSTR (match_test_exp, 0) = "mode == VOIDmode || GET_MODE (op) == mode";
360*38fd1498Szrj and_exp = rtx_alloc (AND);
361*38fd1498Szrj XEXP (and_exp, 1) = match_test_exp;
362*38fd1498Szrj
363*38fd1498Szrj /* It is always correct to rewrite p->exp as
364*38fd1498Szrj
365*38fd1498Szrj (and (...) (match_test "mode == VOIDmode || GET_MODE (op) == mode"))
366*38fd1498Szrj
367*38fd1498Szrj but there are a couple forms where we can do better. If the
368*38fd1498Szrj top-level pattern is an IOR, and one of the two branches does test
369*38fd1498Szrj the mode, we can wrap just the branch that doesn't. Likewise, if
370*38fd1498Szrj we have an IF_THEN_ELSE, and one side of it tests the mode, we can
371*38fd1498Szrj wrap just the side that doesn't. And, of course, we can repeat this
372*38fd1498Szrj descent as many times as it works. */
373*38fd1498Szrj
374*38fd1498Szrj pos = &p->exp;
375*38fd1498Szrj for (;;)
376*38fd1498Szrj {
377*38fd1498Szrj rtx subexp = *pos;
378*38fd1498Szrj
379*38fd1498Szrj switch (GET_CODE (subexp))
380*38fd1498Szrj {
381*38fd1498Szrj case AND:
382*38fd1498Szrj /* The switch code generation in write_predicate_stmts prefers
383*38fd1498Szrj rtx code tests to be at the top of the expression tree. So
384*38fd1498Szrj push this AND down into the second operand of an existing
385*38fd1498Szrj AND expression. */
386*38fd1498Szrj if (generate_switch_p (XEXP (subexp, 0)))
387*38fd1498Szrj pos = &XEXP (subexp, 1);
388*38fd1498Szrj goto break_loop;
389*38fd1498Szrj
390*38fd1498Szrj case IOR:
391*38fd1498Szrj {
392*38fd1498Szrj int test0 = NO_MODE_TEST (XEXP (subexp, 0));
393*38fd1498Szrj int test1 = NO_MODE_TEST (XEXP (subexp, 1));
394*38fd1498Szrj
395*38fd1498Szrj gcc_assert (test0 || test1);
396*38fd1498Szrj
397*38fd1498Szrj if (test0 && test1)
398*38fd1498Szrj goto break_loop;
399*38fd1498Szrj pos = test0 ? &XEXP (subexp, 0) : &XEXP (subexp, 1);
400*38fd1498Szrj }
401*38fd1498Szrj break;
402*38fd1498Szrj
403*38fd1498Szrj case IF_THEN_ELSE:
404*38fd1498Szrj {
405*38fd1498Szrj int test0 = NO_MODE_TEST (XEXP (subexp, 0));
406*38fd1498Szrj int test1 = NO_MODE_TEST (XEXP (subexp, 1));
407*38fd1498Szrj int test2 = NO_MODE_TEST (XEXP (subexp, 2));
408*38fd1498Szrj
409*38fd1498Szrj gcc_assert ((test0 && test1) || test2);
410*38fd1498Szrj
411*38fd1498Szrj if (test0 && test1 && test2)
412*38fd1498Szrj goto break_loop;
413*38fd1498Szrj if (test0 && test1)
414*38fd1498Szrj /* Must put it on the dependent clause, not the
415*38fd1498Szrj controlling expression, or we change the meaning of
416*38fd1498Szrj the test. */
417*38fd1498Szrj pos = &XEXP (subexp, 1);
418*38fd1498Szrj else
419*38fd1498Szrj pos = &XEXP (subexp, 2);
420*38fd1498Szrj }
421*38fd1498Szrj break;
422*38fd1498Szrj
423*38fd1498Szrj default:
424*38fd1498Szrj goto break_loop;
425*38fd1498Szrj }
426*38fd1498Szrj }
427*38fd1498Szrj break_loop:
428*38fd1498Szrj XEXP (and_exp, 0) = *pos;
429*38fd1498Szrj *pos = and_exp;
430*38fd1498Szrj }
431*38fd1498Szrj
432*38fd1498Szrj /* PATH is a string describing a path from the root of an RTL
433*38fd1498Szrj expression to an inner subexpression to be tested. Output
434*38fd1498Szrj code which computes the subexpression from the variable
435*38fd1498Szrj holding the root of the expression. */
436*38fd1498Szrj static void
write_extract_subexp(const char * path)437*38fd1498Szrj write_extract_subexp (const char *path)
438*38fd1498Szrj {
439*38fd1498Szrj int len = strlen (path);
440*38fd1498Szrj int i;
441*38fd1498Szrj
442*38fd1498Szrj /* We first write out the operations (XEXP or XVECEXP) in reverse
443*38fd1498Szrj order, then write "op", then the indices in forward order. */
444*38fd1498Szrj for (i = len - 1; i >= 0; i--)
445*38fd1498Szrj {
446*38fd1498Szrj if (ISLOWER (path[i]))
447*38fd1498Szrj fputs ("XVECEXP (", stdout);
448*38fd1498Szrj else if (ISDIGIT (path[i]))
449*38fd1498Szrj fputs ("XEXP (", stdout);
450*38fd1498Szrj else
451*38fd1498Szrj gcc_unreachable ();
452*38fd1498Szrj }
453*38fd1498Szrj
454*38fd1498Szrj fputs ("op", stdout);
455*38fd1498Szrj
456*38fd1498Szrj for (i = 0; i < len; i++)
457*38fd1498Szrj {
458*38fd1498Szrj if (ISLOWER (path[i]))
459*38fd1498Szrj printf (", 0, %d)", path[i] - 'a');
460*38fd1498Szrj else if (ISDIGIT (path[i]))
461*38fd1498Szrj printf (", %d)", path[i] - '0');
462*38fd1498Szrj else
463*38fd1498Szrj gcc_unreachable ();
464*38fd1498Szrj }
465*38fd1498Szrj }
466*38fd1498Szrj
467*38fd1498Szrj /* CODES is a list of RTX codes. Write out an expression which
468*38fd1498Szrj determines whether the operand has one of those codes. */
469*38fd1498Szrj static void
write_match_code(const char * path,const char * codes)470*38fd1498Szrj write_match_code (const char *path, const char *codes)
471*38fd1498Szrj {
472*38fd1498Szrj const char *code;
473*38fd1498Szrj
474*38fd1498Szrj while ((code = scan_comma_elt (&codes)) != 0)
475*38fd1498Szrj {
476*38fd1498Szrj fputs ("GET_CODE (", stdout);
477*38fd1498Szrj write_extract_subexp (path);
478*38fd1498Szrj fputs (") == ", stdout);
479*38fd1498Szrj while (code < codes)
480*38fd1498Szrj {
481*38fd1498Szrj putchar (TOUPPER (*code));
482*38fd1498Szrj code++;
483*38fd1498Szrj }
484*38fd1498Szrj
485*38fd1498Szrj if (*codes == ',')
486*38fd1498Szrj fputs (" || ", stdout);
487*38fd1498Szrj }
488*38fd1498Szrj }
489*38fd1498Szrj
490*38fd1498Szrj /* EXP is an RTL (sub)expression for a predicate. Recursively
491*38fd1498Szrj descend the expression and write out an equivalent C expression. */
492*38fd1498Szrj static void
write_predicate_expr(rtx exp)493*38fd1498Szrj write_predicate_expr (rtx exp)
494*38fd1498Szrj {
495*38fd1498Szrj switch (GET_CODE (exp))
496*38fd1498Szrj {
497*38fd1498Szrj case AND:
498*38fd1498Szrj putchar ('(');
499*38fd1498Szrj write_predicate_expr (XEXP (exp, 0));
500*38fd1498Szrj fputs (") && (", stdout);
501*38fd1498Szrj write_predicate_expr (XEXP (exp, 1));
502*38fd1498Szrj putchar (')');
503*38fd1498Szrj break;
504*38fd1498Szrj
505*38fd1498Szrj case IOR:
506*38fd1498Szrj putchar ('(');
507*38fd1498Szrj write_predicate_expr (XEXP (exp, 0));
508*38fd1498Szrj fputs (") || (", stdout);
509*38fd1498Szrj write_predicate_expr (XEXP (exp, 1));
510*38fd1498Szrj putchar (')');
511*38fd1498Szrj break;
512*38fd1498Szrj
513*38fd1498Szrj case NOT:
514*38fd1498Szrj fputs ("!(", stdout);
515*38fd1498Szrj write_predicate_expr (XEXP (exp, 0));
516*38fd1498Szrj putchar (')');
517*38fd1498Szrj break;
518*38fd1498Szrj
519*38fd1498Szrj case IF_THEN_ELSE:
520*38fd1498Szrj putchar ('(');
521*38fd1498Szrj write_predicate_expr (XEXP (exp, 0));
522*38fd1498Szrj fputs (") ? (", stdout);
523*38fd1498Szrj write_predicate_expr (XEXP (exp, 1));
524*38fd1498Szrj fputs (") : (", stdout);
525*38fd1498Szrj write_predicate_expr (XEXP (exp, 2));
526*38fd1498Szrj putchar (')');
527*38fd1498Szrj break;
528*38fd1498Szrj
529*38fd1498Szrj case MATCH_OPERAND:
530*38fd1498Szrj if (GET_MODE (exp) == VOIDmode)
531*38fd1498Szrj printf ("%s (op, mode)", XSTR (exp, 1));
532*38fd1498Szrj else
533*38fd1498Szrj printf ("%s (op, %smode)", XSTR (exp, 1), mode_name[GET_MODE (exp)]);
534*38fd1498Szrj break;
535*38fd1498Szrj
536*38fd1498Szrj case MATCH_CODE:
537*38fd1498Szrj write_match_code (XSTR (exp, 1), XSTR (exp, 0));
538*38fd1498Szrj break;
539*38fd1498Szrj
540*38fd1498Szrj case MATCH_TEST:
541*38fd1498Szrj rtx_reader_ptr->print_c_condition (XSTR (exp, 0));
542*38fd1498Szrj break;
543*38fd1498Szrj
544*38fd1498Szrj default:
545*38fd1498Szrj gcc_unreachable ();
546*38fd1498Szrj }
547*38fd1498Szrj }
548*38fd1498Szrj
549*38fd1498Szrj /* Write the MATCH_CODE expression EXP as a switch statement. */
550*38fd1498Szrj
551*38fd1498Szrj static void
write_match_code_switch(rtx exp)552*38fd1498Szrj write_match_code_switch (rtx exp)
553*38fd1498Szrj {
554*38fd1498Szrj const char *codes = XSTR (exp, 0);
555*38fd1498Szrj const char *path = XSTR (exp, 1);
556*38fd1498Szrj const char *code;
557*38fd1498Szrj
558*38fd1498Szrj fputs (" switch (GET_CODE (", stdout);
559*38fd1498Szrj write_extract_subexp (path);
560*38fd1498Szrj fputs ("))\n {\n", stdout);
561*38fd1498Szrj
562*38fd1498Szrj while ((code = scan_comma_elt (&codes)) != 0)
563*38fd1498Szrj {
564*38fd1498Szrj fputs (" case ", stdout);
565*38fd1498Szrj while (code < codes)
566*38fd1498Szrj {
567*38fd1498Szrj putchar (TOUPPER (*code));
568*38fd1498Szrj code++;
569*38fd1498Szrj }
570*38fd1498Szrj fputs (":\n", stdout);
571*38fd1498Szrj }
572*38fd1498Szrj }
573*38fd1498Szrj
574*38fd1498Szrj /* Given a predicate expression EXP, write out a sequence of stmts
575*38fd1498Szrj to evaluate it. This is similar to write_predicate_expr but can
576*38fd1498Szrj generate efficient switch statements. */
577*38fd1498Szrj
578*38fd1498Szrj static void
write_predicate_stmts(rtx exp)579*38fd1498Szrj write_predicate_stmts (rtx exp)
580*38fd1498Szrj {
581*38fd1498Szrj switch (GET_CODE (exp))
582*38fd1498Szrj {
583*38fd1498Szrj case MATCH_CODE:
584*38fd1498Szrj if (generate_switch_p (exp))
585*38fd1498Szrj {
586*38fd1498Szrj write_match_code_switch (exp);
587*38fd1498Szrj puts (" return true;\n"
588*38fd1498Szrj " default:\n"
589*38fd1498Szrj " break;\n"
590*38fd1498Szrj " }\n"
591*38fd1498Szrj " return false;");
592*38fd1498Szrj return;
593*38fd1498Szrj }
594*38fd1498Szrj break;
595*38fd1498Szrj
596*38fd1498Szrj case AND:
597*38fd1498Szrj if (generate_switch_p (XEXP (exp, 0)))
598*38fd1498Szrj {
599*38fd1498Szrj write_match_code_switch (XEXP (exp, 0));
600*38fd1498Szrj puts (" break;\n"
601*38fd1498Szrj " default:\n"
602*38fd1498Szrj " return false;\n"
603*38fd1498Szrj " }");
604*38fd1498Szrj exp = XEXP (exp, 1);
605*38fd1498Szrj }
606*38fd1498Szrj break;
607*38fd1498Szrj
608*38fd1498Szrj case IOR:
609*38fd1498Szrj if (generate_switch_p (XEXP (exp, 0)))
610*38fd1498Szrj {
611*38fd1498Szrj write_match_code_switch (XEXP (exp, 0));
612*38fd1498Szrj puts (" return true;\n"
613*38fd1498Szrj " default:\n"
614*38fd1498Szrj " break;\n"
615*38fd1498Szrj " }");
616*38fd1498Szrj exp = XEXP (exp, 1);
617*38fd1498Szrj }
618*38fd1498Szrj break;
619*38fd1498Szrj
620*38fd1498Szrj case NOT:
621*38fd1498Szrj if (generate_switch_p (XEXP (exp, 0)))
622*38fd1498Szrj {
623*38fd1498Szrj write_match_code_switch (XEXP (exp, 0));
624*38fd1498Szrj puts (" return false;\n"
625*38fd1498Szrj " default:\n"
626*38fd1498Szrj " break;\n"
627*38fd1498Szrj " }\n"
628*38fd1498Szrj " return true;");
629*38fd1498Szrj return;
630*38fd1498Szrj }
631*38fd1498Szrj break;
632*38fd1498Szrj
633*38fd1498Szrj default:
634*38fd1498Szrj break;
635*38fd1498Szrj }
636*38fd1498Szrj
637*38fd1498Szrj fputs (" return ",stdout);
638*38fd1498Szrj write_predicate_expr (exp);
639*38fd1498Szrj fputs (";\n", stdout);
640*38fd1498Szrj }
641*38fd1498Szrj
642*38fd1498Szrj /* Given a predicate, write out a complete C function to compute it. */
643*38fd1498Szrj static void
write_one_predicate_function(struct pred_data * p)644*38fd1498Szrj write_one_predicate_function (struct pred_data *p)
645*38fd1498Szrj {
646*38fd1498Szrj if (!p->exp)
647*38fd1498Szrj return;
648*38fd1498Szrj
649*38fd1498Szrj write_predicate_subfunction (p);
650*38fd1498Szrj add_mode_tests (p);
651*38fd1498Szrj
652*38fd1498Szrj /* A normal predicate can legitimately not look at machine_mode
653*38fd1498Szrj if it accepts only CONST_INTs and/or CONST_WIDE_INT and/or CONST_DOUBLEs. */
654*38fd1498Szrj printf ("int\n%s (rtx op, machine_mode mode ATTRIBUTE_UNUSED)\n{\n",
655*38fd1498Szrj p->name);
656*38fd1498Szrj write_predicate_stmts (p->exp);
657*38fd1498Szrj fputs ("}\n\n", stdout);
658*38fd1498Szrj }
659*38fd1498Szrj
660*38fd1498Szrj /* Constraints fall into two categories: register constraints
661*38fd1498Szrj (define_register_constraint), and others (define_constraint,
662*38fd1498Szrj define_memory_constraint, define_special_memory_constraint,
663*38fd1498Szrj define_address_constraint). We work out automatically which of the
664*38fd1498Szrj various old-style macros they correspond to, and produce
665*38fd1498Szrj appropriate code. They all go in the same hash table so we can
666*38fd1498Szrj verify that there are no duplicate names. */
667*38fd1498Szrj
668*38fd1498Szrj /* All data from one constraint definition. */
669*38fd1498Szrj struct constraint_data
670*38fd1498Szrj {
671*38fd1498Szrj struct constraint_data *next_this_letter;
672*38fd1498Szrj struct constraint_data *next_textual;
673*38fd1498Szrj const char *name;
674*38fd1498Szrj const char *c_name; /* same as .name unless mangling is necessary */
675*38fd1498Szrj file_location loc; /* location of definition */
676*38fd1498Szrj size_t namelen;
677*38fd1498Szrj const char *regclass; /* for register constraints */
678*38fd1498Szrj rtx exp; /* for other constraints */
679*38fd1498Szrj unsigned int is_register : 1;
680*38fd1498Szrj unsigned int is_const_int : 1;
681*38fd1498Szrj unsigned int is_const_dbl : 1;
682*38fd1498Szrj unsigned int is_extra : 1;
683*38fd1498Szrj unsigned int is_memory : 1;
684*38fd1498Szrj unsigned int is_special_memory: 1;
685*38fd1498Szrj unsigned int is_address : 1;
686*38fd1498Szrj unsigned int maybe_allows_reg : 1;
687*38fd1498Szrj unsigned int maybe_allows_mem : 1;
688*38fd1498Szrj };
689*38fd1498Szrj
690*38fd1498Szrj /* Overview of all constraints beginning with a given letter. */
691*38fd1498Szrj
692*38fd1498Szrj static struct constraint_data *
693*38fd1498Szrj constraints_by_letter_table[1<<CHAR_BIT];
694*38fd1498Szrj
695*38fd1498Szrj /* For looking up all the constraints in the order that they appeared
696*38fd1498Szrj in the machine description. */
697*38fd1498Szrj static struct constraint_data *first_constraint;
698*38fd1498Szrj static struct constraint_data **last_constraint_ptr = &first_constraint;
699*38fd1498Szrj
700*38fd1498Szrj #define FOR_ALL_CONSTRAINTS(iter_) \
701*38fd1498Szrj for (iter_ = first_constraint; iter_; iter_ = iter_->next_textual)
702*38fd1498Szrj
703*38fd1498Szrj /* Contraint letters that have a special meaning and that cannot be used
704*38fd1498Szrj in define*_constraints. */
705*38fd1498Szrj static const char generic_constraint_letters[] = "g";
706*38fd1498Szrj
707*38fd1498Szrj /* Machine-independent code expects that constraints with these
708*38fd1498Szrj (initial) letters will allow only (a subset of all) CONST_INTs. */
709*38fd1498Szrj
710*38fd1498Szrj static const char const_int_constraints[] = "IJKLMNOP";
711*38fd1498Szrj
712*38fd1498Szrj /* Machine-independent code expects that constraints with these
713*38fd1498Szrj (initial) letters will allow only (a subset of all) CONST_DOUBLEs. */
714*38fd1498Szrj
715*38fd1498Szrj static const char const_dbl_constraints[] = "GH";
716*38fd1498Szrj
717*38fd1498Szrj /* Summary data used to decide whether to output various functions and
718*38fd1498Szrj macro definitions. */
719*38fd1498Szrj static unsigned int constraint_max_namelen;
720*38fd1498Szrj static bool have_register_constraints;
721*38fd1498Szrj static bool have_memory_constraints;
722*38fd1498Szrj static bool have_special_memory_constraints;
723*38fd1498Szrj static bool have_address_constraints;
724*38fd1498Szrj static bool have_extra_constraints;
725*38fd1498Szrj static bool have_const_int_constraints;
726*38fd1498Szrj static unsigned int num_constraints;
727*38fd1498Szrj
728*38fd1498Szrj static const constraint_data **enum_order;
729*38fd1498Szrj static unsigned int register_start, register_end;
730*38fd1498Szrj static unsigned int satisfied_start;
731*38fd1498Szrj static unsigned int const_int_start, const_int_end;
732*38fd1498Szrj static unsigned int memory_start, memory_end;
733*38fd1498Szrj static unsigned int special_memory_start, special_memory_end;
734*38fd1498Szrj static unsigned int address_start, address_end;
735*38fd1498Szrj static unsigned int maybe_allows_none_start, maybe_allows_none_end;
736*38fd1498Szrj static unsigned int maybe_allows_reg_start, maybe_allows_reg_end;
737*38fd1498Szrj static unsigned int maybe_allows_mem_start, maybe_allows_mem_end;
738*38fd1498Szrj
739*38fd1498Szrj /* Convert NAME, which contains angle brackets and/or underscores, to
740*38fd1498Szrj a string that can be used as part of a C identifier. The string
741*38fd1498Szrj comes from the rtl_obstack. */
742*38fd1498Szrj static const char *
mangle(const char * name)743*38fd1498Szrj mangle (const char *name)
744*38fd1498Szrj {
745*38fd1498Szrj for (; *name; name++)
746*38fd1498Szrj switch (*name)
747*38fd1498Szrj {
748*38fd1498Szrj case '_': obstack_grow (rtl_obstack, "__", 2); break;
749*38fd1498Szrj case '<': obstack_grow (rtl_obstack, "_l", 2); break;
750*38fd1498Szrj case '>': obstack_grow (rtl_obstack, "_g", 2); break;
751*38fd1498Szrj default: obstack_1grow (rtl_obstack, *name); break;
752*38fd1498Szrj }
753*38fd1498Szrj
754*38fd1498Szrj obstack_1grow (rtl_obstack, '\0');
755*38fd1498Szrj return XOBFINISH (rtl_obstack, const char *);
756*38fd1498Szrj }
757*38fd1498Szrj
758*38fd1498Szrj /* Add one constraint, of any sort, to the tables. NAME is its name;
759*38fd1498Szrj REGCLASS is the register class, if any; EXP is the expression to
760*38fd1498Szrj test, if any; IS_MEMORY, IS_SPECIAL_MEMORY and IS_ADDRESS indicate
761*38fd1498Szrj memory, special memory, and address constraints, respectively; LOC
762*38fd1498Szrj is the .md file location.
763*38fd1498Szrj
764*38fd1498Szrj Not all combinations of arguments are valid; most importantly,
765*38fd1498Szrj REGCLASS is mutually exclusive with EXP, and
766*38fd1498Szrj IS_MEMORY/IS_SPECIAL_MEMORY/IS_ADDRESS are only meaningful for
767*38fd1498Szrj constraints with EXP.
768*38fd1498Szrj
769*38fd1498Szrj This function enforces all syntactic and semantic rules about what
770*38fd1498Szrj constraints can be defined. */
771*38fd1498Szrj
772*38fd1498Szrj static void
add_constraint(const char * name,const char * regclass,rtx exp,bool is_memory,bool is_special_memory,bool is_address,file_location loc)773*38fd1498Szrj add_constraint (const char *name, const char *regclass,
774*38fd1498Szrj rtx exp, bool is_memory, bool is_special_memory,
775*38fd1498Szrj bool is_address, file_location loc)
776*38fd1498Szrj {
777*38fd1498Szrj struct constraint_data *c, **iter, **slot;
778*38fd1498Szrj const char *p;
779*38fd1498Szrj bool need_mangled_name = false;
780*38fd1498Szrj bool is_const_int;
781*38fd1498Szrj bool is_const_dbl;
782*38fd1498Szrj size_t namelen;
783*38fd1498Szrj
784*38fd1498Szrj if (strcmp (name, "TARGET_MEM_CONSTRAINT") == 0)
785*38fd1498Szrj name = general_mem;
786*38fd1498Szrj
787*38fd1498Szrj if (exp && validate_exp (exp, name, loc))
788*38fd1498Szrj return;
789*38fd1498Szrj
790*38fd1498Szrj for (p = name; *p; p++)
791*38fd1498Szrj if (!ISALNUM (*p))
792*38fd1498Szrj {
793*38fd1498Szrj if (*p == '<' || *p == '>' || *p == '_')
794*38fd1498Szrj need_mangled_name = true;
795*38fd1498Szrj else
796*38fd1498Szrj {
797*38fd1498Szrj error_at (loc, "constraint name '%s' must be composed of letters,"
798*38fd1498Szrj " digits, underscores, and angle brackets", name);
799*38fd1498Szrj return;
800*38fd1498Szrj }
801*38fd1498Szrj }
802*38fd1498Szrj
803*38fd1498Szrj if (strchr (generic_constraint_letters, name[0]))
804*38fd1498Szrj {
805*38fd1498Szrj if (name[1] == '\0')
806*38fd1498Szrj error_at (loc, "constraint letter '%s' cannot be "
807*38fd1498Szrj "redefined by the machine description", name);
808*38fd1498Szrj else
809*38fd1498Szrj error_at (loc, "constraint name '%s' cannot be defined by the machine"
810*38fd1498Szrj " description, as it begins with '%c'", name, name[0]);
811*38fd1498Szrj return;
812*38fd1498Szrj }
813*38fd1498Szrj
814*38fd1498Szrj
815*38fd1498Szrj namelen = strlen (name);
816*38fd1498Szrj slot = &constraints_by_letter_table[(unsigned int)name[0]];
817*38fd1498Szrj for (iter = slot; *iter; iter = &(*iter)->next_this_letter)
818*38fd1498Szrj {
819*38fd1498Szrj /* This causes slot to end up pointing to the
820*38fd1498Szrj next_this_letter field of the last constraint with a name
821*38fd1498Szrj of equal or greater length than the new constraint; hence
822*38fd1498Szrj the new constraint will be inserted after all previous
823*38fd1498Szrj constraints with names of the same length. */
824*38fd1498Szrj if ((*iter)->namelen >= namelen)
825*38fd1498Szrj slot = iter;
826*38fd1498Szrj
827*38fd1498Szrj if (!strcmp ((*iter)->name, name))
828*38fd1498Szrj {
829*38fd1498Szrj error_at (loc, "redefinition of constraint '%s'", name);
830*38fd1498Szrj message_at ((*iter)->loc, "previous definition is here");
831*38fd1498Szrj return;
832*38fd1498Szrj }
833*38fd1498Szrj else if (!strncmp ((*iter)->name, name, (*iter)->namelen))
834*38fd1498Szrj {
835*38fd1498Szrj error_at (loc, "defining constraint '%s' here", name);
836*38fd1498Szrj message_at ((*iter)->loc, "renders constraint '%s' "
837*38fd1498Szrj "(defined here) a prefix", (*iter)->name);
838*38fd1498Szrj return;
839*38fd1498Szrj }
840*38fd1498Szrj else if (!strncmp ((*iter)->name, name, namelen))
841*38fd1498Szrj {
842*38fd1498Szrj error_at (loc, "constraint '%s' is a prefix", name);
843*38fd1498Szrj message_at ((*iter)->loc, "of constraint '%s' (defined here)",
844*38fd1498Szrj (*iter)->name);
845*38fd1498Szrj return;
846*38fd1498Szrj }
847*38fd1498Szrj }
848*38fd1498Szrj
849*38fd1498Szrj is_const_int = strchr (const_int_constraints, name[0]) != 0;
850*38fd1498Szrj is_const_dbl = strchr (const_dbl_constraints, name[0]) != 0;
851*38fd1498Szrj
852*38fd1498Szrj if (is_const_int || is_const_dbl)
853*38fd1498Szrj {
854*38fd1498Szrj enum rtx_code appropriate_code
855*38fd1498Szrj = is_const_int ? CONST_INT : CONST_DOUBLE;
856*38fd1498Szrj
857*38fd1498Szrj /* Consider relaxing this requirement in the future. */
858*38fd1498Szrj if (regclass
859*38fd1498Szrj || GET_CODE (exp) != AND
860*38fd1498Szrj || GET_CODE (XEXP (exp, 0)) != MATCH_CODE
861*38fd1498Szrj || strcmp (XSTR (XEXP (exp, 0), 0),
862*38fd1498Szrj GET_RTX_NAME (appropriate_code)))
863*38fd1498Szrj {
864*38fd1498Szrj if (name[1] == '\0')
865*38fd1498Szrj error_at (loc, "constraint letter '%c' is reserved "
866*38fd1498Szrj "for %s constraints", name[0],
867*38fd1498Szrj GET_RTX_NAME (appropriate_code));
868*38fd1498Szrj else
869*38fd1498Szrj error_at (loc, "constraint names beginning with '%c' "
870*38fd1498Szrj "(%s) are reserved for %s constraints",
871*38fd1498Szrj name[0], name, GET_RTX_NAME (appropriate_code));
872*38fd1498Szrj return;
873*38fd1498Szrj }
874*38fd1498Szrj
875*38fd1498Szrj if (is_memory)
876*38fd1498Szrj {
877*38fd1498Szrj if (name[1] == '\0')
878*38fd1498Szrj error_at (loc, "constraint letter '%c' cannot be a "
879*38fd1498Szrj "memory constraint", name[0]);
880*38fd1498Szrj else
881*38fd1498Szrj error_at (loc, "constraint name '%s' begins with '%c', "
882*38fd1498Szrj "and therefore cannot be a memory constraint",
883*38fd1498Szrj name, name[0]);
884*38fd1498Szrj return;
885*38fd1498Szrj }
886*38fd1498Szrj else if (is_special_memory)
887*38fd1498Szrj {
888*38fd1498Szrj if (name[1] == '\0')
889*38fd1498Szrj error_at (loc, "constraint letter '%c' cannot be a "
890*38fd1498Szrj "special memory constraint", name[0]);
891*38fd1498Szrj else
892*38fd1498Szrj error_at (loc, "constraint name '%s' begins with '%c', "
893*38fd1498Szrj "and therefore cannot be a special memory constraint",
894*38fd1498Szrj name, name[0]);
895*38fd1498Szrj return;
896*38fd1498Szrj }
897*38fd1498Szrj else if (is_address)
898*38fd1498Szrj {
899*38fd1498Szrj if (name[1] == '\0')
900*38fd1498Szrj error_at (loc, "constraint letter '%c' cannot be an "
901*38fd1498Szrj "address constraint", name[0]);
902*38fd1498Szrj else
903*38fd1498Szrj error_at (loc, "constraint name '%s' begins with '%c', "
904*38fd1498Szrj "and therefore cannot be an address constraint",
905*38fd1498Szrj name, name[0]);
906*38fd1498Szrj return;
907*38fd1498Szrj }
908*38fd1498Szrj }
909*38fd1498Szrj
910*38fd1498Szrj
911*38fd1498Szrj c = XOBNEW (rtl_obstack, struct constraint_data);
912*38fd1498Szrj c->name = name;
913*38fd1498Szrj c->c_name = need_mangled_name ? mangle (name) : name;
914*38fd1498Szrj c->loc = loc;
915*38fd1498Szrj c->namelen = namelen;
916*38fd1498Szrj c->regclass = regclass;
917*38fd1498Szrj c->exp = exp;
918*38fd1498Szrj c->is_register = regclass != 0;
919*38fd1498Szrj c->is_const_int = is_const_int;
920*38fd1498Szrj c->is_const_dbl = is_const_dbl;
921*38fd1498Szrj c->is_extra = !(regclass || is_const_int || is_const_dbl);
922*38fd1498Szrj c->is_memory = is_memory;
923*38fd1498Szrj c->is_special_memory = is_special_memory;
924*38fd1498Szrj c->is_address = is_address;
925*38fd1498Szrj c->maybe_allows_reg = true;
926*38fd1498Szrj c->maybe_allows_mem = true;
927*38fd1498Szrj if (exp)
928*38fd1498Szrj {
929*38fd1498Szrj char codes[NUM_RTX_CODE];
930*38fd1498Szrj compute_test_codes (exp, loc, codes);
931*38fd1498Szrj if (!codes[REG] && !codes[SUBREG])
932*38fd1498Szrj c->maybe_allows_reg = false;
933*38fd1498Szrj if (!codes[MEM])
934*38fd1498Szrj c->maybe_allows_mem = false;
935*38fd1498Szrj }
936*38fd1498Szrj c->next_this_letter = *slot;
937*38fd1498Szrj *slot = c;
938*38fd1498Szrj
939*38fd1498Szrj /* Insert this constraint in the list of all constraints in textual
940*38fd1498Szrj order. */
941*38fd1498Szrj c->next_textual = 0;
942*38fd1498Szrj *last_constraint_ptr = c;
943*38fd1498Szrj last_constraint_ptr = &c->next_textual;
944*38fd1498Szrj
945*38fd1498Szrj constraint_max_namelen = MAX (constraint_max_namelen, strlen (name));
946*38fd1498Szrj have_register_constraints |= c->is_register;
947*38fd1498Szrj have_const_int_constraints |= c->is_const_int;
948*38fd1498Szrj have_extra_constraints |= c->is_extra;
949*38fd1498Szrj have_memory_constraints |= c->is_memory;
950*38fd1498Szrj have_special_memory_constraints |= c->is_special_memory;
951*38fd1498Szrj have_address_constraints |= c->is_address;
952*38fd1498Szrj num_constraints += 1;
953*38fd1498Szrj }
954*38fd1498Szrj
955*38fd1498Szrj /* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT,
956*38fd1498Szrj DEFINE_SPECIAL_MEMORY_CONSTRAINT, or DEFINE_ADDRESS_CONSTRAINT
957*38fd1498Szrj expression, C. */
958*38fd1498Szrj static void
process_define_constraint(md_rtx_info * info)959*38fd1498Szrj process_define_constraint (md_rtx_info *info)
960*38fd1498Szrj {
961*38fd1498Szrj add_constraint (XSTR (info->def, 0), 0, XEXP (info->def, 2),
962*38fd1498Szrj GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT,
963*38fd1498Szrj GET_CODE (info->def) == DEFINE_SPECIAL_MEMORY_CONSTRAINT,
964*38fd1498Szrj GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT,
965*38fd1498Szrj info->loc);
966*38fd1498Szrj }
967*38fd1498Szrj
968*38fd1498Szrj /* Process a DEFINE_REGISTER_CONSTRAINT expression, C. */
969*38fd1498Szrj static void
process_define_register_constraint(md_rtx_info * info)970*38fd1498Szrj process_define_register_constraint (md_rtx_info *info)
971*38fd1498Szrj {
972*38fd1498Szrj add_constraint (XSTR (info->def, 0), XSTR (info->def, 1),
973*38fd1498Szrj 0, false, false, false, info->loc);
974*38fd1498Szrj }
975*38fd1498Szrj
976*38fd1498Szrj /* Put the constraints into enum order. We want to keep constraints
977*38fd1498Szrj of the same type together so that query functions can be simple
978*38fd1498Szrj range checks. */
979*38fd1498Szrj static void
choose_enum_order(void)980*38fd1498Szrj choose_enum_order (void)
981*38fd1498Szrj {
982*38fd1498Szrj struct constraint_data *c;
983*38fd1498Szrj
984*38fd1498Szrj enum_order = XNEWVEC (const constraint_data *, num_constraints);
985*38fd1498Szrj unsigned int next = 0;
986*38fd1498Szrj
987*38fd1498Szrj register_start = next;
988*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
989*38fd1498Szrj if (c->is_register)
990*38fd1498Szrj enum_order[next++] = c;
991*38fd1498Szrj register_end = next;
992*38fd1498Szrj
993*38fd1498Szrj satisfied_start = next;
994*38fd1498Szrj
995*38fd1498Szrj const_int_start = next;
996*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
997*38fd1498Szrj if (c->is_const_int)
998*38fd1498Szrj enum_order[next++] = c;
999*38fd1498Szrj const_int_end = next;
1000*38fd1498Szrj
1001*38fd1498Szrj memory_start = next;
1002*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1003*38fd1498Szrj if (c->is_memory)
1004*38fd1498Szrj enum_order[next++] = c;
1005*38fd1498Szrj memory_end = next;
1006*38fd1498Szrj
1007*38fd1498Szrj special_memory_start = next;
1008*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1009*38fd1498Szrj if (c->is_special_memory)
1010*38fd1498Szrj enum_order[next++] = c;
1011*38fd1498Szrj special_memory_end = next;
1012*38fd1498Szrj
1013*38fd1498Szrj address_start = next;
1014*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1015*38fd1498Szrj if (c->is_address)
1016*38fd1498Szrj enum_order[next++] = c;
1017*38fd1498Szrj address_end = next;
1018*38fd1498Szrj
1019*38fd1498Szrj maybe_allows_none_start = next;
1020*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1021*38fd1498Szrj if (!c->is_register && !c->is_const_int && !c->is_memory
1022*38fd1498Szrj && !c->is_special_memory && !c->is_address
1023*38fd1498Szrj && !c->maybe_allows_reg && !c->maybe_allows_mem)
1024*38fd1498Szrj enum_order[next++] = c;
1025*38fd1498Szrj maybe_allows_none_end = next;
1026*38fd1498Szrj
1027*38fd1498Szrj maybe_allows_reg_start = next;
1028*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1029*38fd1498Szrj if (!c->is_register && !c->is_const_int && !c->is_memory
1030*38fd1498Szrj && !c->is_special_memory && !c->is_address
1031*38fd1498Szrj && c->maybe_allows_reg && !c->maybe_allows_mem)
1032*38fd1498Szrj enum_order[next++] = c;
1033*38fd1498Szrj maybe_allows_reg_end = next;
1034*38fd1498Szrj
1035*38fd1498Szrj maybe_allows_mem_start = next;
1036*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1037*38fd1498Szrj if (!c->is_register && !c->is_const_int && !c->is_memory
1038*38fd1498Szrj && !c->is_special_memory && !c->is_address
1039*38fd1498Szrj && !c->maybe_allows_reg && c->maybe_allows_mem)
1040*38fd1498Szrj enum_order[next++] = c;
1041*38fd1498Szrj maybe_allows_mem_end = next;
1042*38fd1498Szrj
1043*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1044*38fd1498Szrj if (!c->is_register && !c->is_const_int && !c->is_memory
1045*38fd1498Szrj && !c->is_special_memory && !c->is_address
1046*38fd1498Szrj && c->maybe_allows_reg && c->maybe_allows_mem)
1047*38fd1498Szrj enum_order[next++] = c;
1048*38fd1498Szrj gcc_assert (next == num_constraints);
1049*38fd1498Szrj }
1050*38fd1498Szrj
1051*38fd1498Szrj /* Write out an enumeration with one entry per machine-specific
1052*38fd1498Szrj constraint. */
1053*38fd1498Szrj static void
write_enum_constraint_num(void)1054*38fd1498Szrj write_enum_constraint_num (void)
1055*38fd1498Szrj {
1056*38fd1498Szrj fputs ("#define CONSTRAINT_NUM_DEFINED_P 1\n", stdout);
1057*38fd1498Szrj fputs ("enum constraint_num\n"
1058*38fd1498Szrj "{\n"
1059*38fd1498Szrj " CONSTRAINT__UNKNOWN = 0", stdout);
1060*38fd1498Szrj for (unsigned int i = 0; i < num_constraints; ++i)
1061*38fd1498Szrj printf (",\n CONSTRAINT_%s", enum_order[i]->c_name);
1062*38fd1498Szrj puts (",\n CONSTRAINT__LIMIT\n};\n");
1063*38fd1498Szrj }
1064*38fd1498Szrj
1065*38fd1498Szrj /* Write out a function which looks at a string and determines what
1066*38fd1498Szrj constraint name, if any, it begins with. */
1067*38fd1498Szrj static void
write_lookup_constraint_1(void)1068*38fd1498Szrj write_lookup_constraint_1 (void)
1069*38fd1498Szrj {
1070*38fd1498Szrj unsigned int i;
1071*38fd1498Szrj puts ("enum constraint_num\n"
1072*38fd1498Szrj "lookup_constraint_1 (const char *str)\n"
1073*38fd1498Szrj "{\n"
1074*38fd1498Szrj " switch (str[0])\n"
1075*38fd1498Szrj " {");
1076*38fd1498Szrj
1077*38fd1498Szrj for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++)
1078*38fd1498Szrj {
1079*38fd1498Szrj struct constraint_data *c = constraints_by_letter_table[i];
1080*38fd1498Szrj if (!c)
1081*38fd1498Szrj continue;
1082*38fd1498Szrj
1083*38fd1498Szrj printf (" case '%c':\n", i);
1084*38fd1498Szrj if (c->namelen == 1)
1085*38fd1498Szrj printf (" return CONSTRAINT_%s;\n", c->c_name);
1086*38fd1498Szrj else
1087*38fd1498Szrj {
1088*38fd1498Szrj do
1089*38fd1498Szrj {
1090*38fd1498Szrj printf (" if (!strncmp (str + 1, \"%s\", %lu))\n"
1091*38fd1498Szrj " return CONSTRAINT_%s;\n",
1092*38fd1498Szrj c->name + 1, (unsigned long int) c->namelen - 1,
1093*38fd1498Szrj c->c_name);
1094*38fd1498Szrj c = c->next_this_letter;
1095*38fd1498Szrj }
1096*38fd1498Szrj while (c);
1097*38fd1498Szrj puts (" break;");
1098*38fd1498Szrj }
1099*38fd1498Szrj }
1100*38fd1498Szrj
1101*38fd1498Szrj puts (" default: break;\n"
1102*38fd1498Szrj " }\n"
1103*38fd1498Szrj " return CONSTRAINT__UNKNOWN;\n"
1104*38fd1498Szrj "}\n");
1105*38fd1498Szrj }
1106*38fd1498Szrj
1107*38fd1498Szrj /* Write out an array that maps single-letter characters to their
1108*38fd1498Szrj constraints (if that fits in a character) or 255 if lookup_constraint_1
1109*38fd1498Szrj must be called. */
1110*38fd1498Szrj static void
write_lookup_constraint_array(void)1111*38fd1498Szrj write_lookup_constraint_array (void)
1112*38fd1498Szrj {
1113*38fd1498Szrj unsigned int i;
1114*38fd1498Szrj printf ("const unsigned char lookup_constraint_array[] = {\n ");
1115*38fd1498Szrj for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++)
1116*38fd1498Szrj {
1117*38fd1498Szrj if (i != 0)
1118*38fd1498Szrj printf (",\n ");
1119*38fd1498Szrj struct constraint_data *c = constraints_by_letter_table[i];
1120*38fd1498Szrj if (!c)
1121*38fd1498Szrj printf ("CONSTRAINT__UNKNOWN");
1122*38fd1498Szrj else if (c->namelen == 1)
1123*38fd1498Szrj printf ("MIN ((int) CONSTRAINT_%s, (int) UCHAR_MAX)", c->c_name);
1124*38fd1498Szrj else
1125*38fd1498Szrj printf ("UCHAR_MAX");
1126*38fd1498Szrj }
1127*38fd1498Szrj printf ("\n};\n\n");
1128*38fd1498Szrj }
1129*38fd1498Szrj
1130*38fd1498Szrj /* Write out a function which looks at a string and determines what
1131*38fd1498Szrj the constraint name length is. */
1132*38fd1498Szrj static void
write_insn_constraint_len(void)1133*38fd1498Szrj write_insn_constraint_len (void)
1134*38fd1498Szrj {
1135*38fd1498Szrj unsigned int i;
1136*38fd1498Szrj
1137*38fd1498Szrj puts ("static inline size_t\n"
1138*38fd1498Szrj "insn_constraint_len (char fc, const char *str ATTRIBUTE_UNUSED)\n"
1139*38fd1498Szrj "{\n"
1140*38fd1498Szrj " switch (fc)\n"
1141*38fd1498Szrj " {");
1142*38fd1498Szrj
1143*38fd1498Szrj for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++)
1144*38fd1498Szrj {
1145*38fd1498Szrj struct constraint_data *c = constraints_by_letter_table[i];
1146*38fd1498Szrj
1147*38fd1498Szrj if (!c
1148*38fd1498Szrj || c->namelen == 1)
1149*38fd1498Szrj continue;
1150*38fd1498Szrj
1151*38fd1498Szrj /* Constraints with multiple characters should have the same
1152*38fd1498Szrj length. */
1153*38fd1498Szrj {
1154*38fd1498Szrj struct constraint_data *c2 = c->next_this_letter;
1155*38fd1498Szrj size_t len = c->namelen;
1156*38fd1498Szrj while (c2)
1157*38fd1498Szrj {
1158*38fd1498Szrj if (c2->namelen != len)
1159*38fd1498Szrj error ("Multi-letter constraints with first letter '%c' "
1160*38fd1498Szrj "should have same length", i);
1161*38fd1498Szrj c2 = c2->next_this_letter;
1162*38fd1498Szrj }
1163*38fd1498Szrj }
1164*38fd1498Szrj
1165*38fd1498Szrj printf (" case '%c': return %lu;\n",
1166*38fd1498Szrj i, (unsigned long int) c->namelen);
1167*38fd1498Szrj }
1168*38fd1498Szrj
1169*38fd1498Szrj puts (" default: break;\n"
1170*38fd1498Szrj " }\n"
1171*38fd1498Szrj " return 1;\n"
1172*38fd1498Szrj "}\n");
1173*38fd1498Szrj }
1174*38fd1498Szrj
1175*38fd1498Szrj /* Write out the function which computes the register class corresponding
1176*38fd1498Szrj to a register constraint. */
1177*38fd1498Szrj static void
write_reg_class_for_constraint_1(void)1178*38fd1498Szrj write_reg_class_for_constraint_1 (void)
1179*38fd1498Szrj {
1180*38fd1498Szrj struct constraint_data *c;
1181*38fd1498Szrj
1182*38fd1498Szrj puts ("enum reg_class\n"
1183*38fd1498Szrj "reg_class_for_constraint_1 (enum constraint_num c)\n"
1184*38fd1498Szrj "{\n"
1185*38fd1498Szrj " switch (c)\n"
1186*38fd1498Szrj " {");
1187*38fd1498Szrj
1188*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1189*38fd1498Szrj if (c->is_register)
1190*38fd1498Szrj printf (" case CONSTRAINT_%s: return %s;\n", c->c_name, c->regclass);
1191*38fd1498Szrj
1192*38fd1498Szrj puts (" default: break;\n"
1193*38fd1498Szrj " }\n"
1194*38fd1498Szrj " return NO_REGS;\n"
1195*38fd1498Szrj "}\n");
1196*38fd1498Szrj }
1197*38fd1498Szrj
1198*38fd1498Szrj /* Write out the functions which compute whether a given value matches
1199*38fd1498Szrj a given non-register constraint. */
1200*38fd1498Szrj static void
write_tm_constrs_h(void)1201*38fd1498Szrj write_tm_constrs_h (void)
1202*38fd1498Szrj {
1203*38fd1498Szrj struct constraint_data *c;
1204*38fd1498Szrj
1205*38fd1498Szrj printf ("\
1206*38fd1498Szrj /* Generated automatically by the program '%s'\n\
1207*38fd1498Szrj from the machine description file '%s'. */\n\n", progname,
1208*38fd1498Szrj md_reader_ptr->get_top_level_filename ());
1209*38fd1498Szrj
1210*38fd1498Szrj puts ("\
1211*38fd1498Szrj #ifndef GCC_TM_CONSTRS_H\n\
1212*38fd1498Szrj #define GCC_TM_CONSTRS_H\n");
1213*38fd1498Szrj
1214*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1215*38fd1498Szrj if (!c->is_register)
1216*38fd1498Szrj {
1217*38fd1498Szrj bool needs_ival = needs_variable (c->exp, "ival");
1218*38fd1498Szrj bool needs_hval = needs_variable (c->exp, "hval");
1219*38fd1498Szrj bool needs_lval = needs_variable (c->exp, "lval");
1220*38fd1498Szrj bool needs_rval = needs_variable (c->exp, "rval");
1221*38fd1498Szrj bool needs_mode = (needs_variable (c->exp, "mode")
1222*38fd1498Szrj || needs_hval || needs_lval || needs_rval);
1223*38fd1498Szrj bool needs_op = (needs_variable (c->exp, "op")
1224*38fd1498Szrj || needs_ival || needs_mode);
1225*38fd1498Szrj
1226*38fd1498Szrj printf ("static inline bool\n"
1227*38fd1498Szrj "satisfies_constraint_%s (rtx %s)\n"
1228*38fd1498Szrj "{\n", c->c_name,
1229*38fd1498Szrj needs_op ? "op" : "ARG_UNUSED (op)");
1230*38fd1498Szrj if (needs_mode)
1231*38fd1498Szrj puts (" machine_mode mode = GET_MODE (op);");
1232*38fd1498Szrj if (needs_ival)
1233*38fd1498Szrj puts (" HOST_WIDE_INT ival = 0;");
1234*38fd1498Szrj if (needs_hval)
1235*38fd1498Szrj puts (" HOST_WIDE_INT hval = 0;");
1236*38fd1498Szrj if (needs_lval)
1237*38fd1498Szrj puts (" unsigned HOST_WIDE_INT lval = 0;");
1238*38fd1498Szrj if (needs_rval)
1239*38fd1498Szrj puts (" const REAL_VALUE_TYPE *rval = 0;");
1240*38fd1498Szrj
1241*38fd1498Szrj if (needs_ival)
1242*38fd1498Szrj puts (" if (CONST_INT_P (op))\n"
1243*38fd1498Szrj " ival = INTVAL (op);");
1244*38fd1498Szrj #if TARGET_SUPPORTS_WIDE_INT
1245*38fd1498Szrj if (needs_lval || needs_hval)
1246*38fd1498Szrj error ("you can't use lval or hval");
1247*38fd1498Szrj #else
1248*38fd1498Szrj if (needs_hval)
1249*38fd1498Szrj puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)"
1250*38fd1498Szrj " hval = CONST_DOUBLE_HIGH (op);");
1251*38fd1498Szrj if (needs_lval)
1252*38fd1498Szrj puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)"
1253*38fd1498Szrj " lval = CONST_DOUBLE_LOW (op);");
1254*38fd1498Szrj #endif
1255*38fd1498Szrj if (needs_rval)
1256*38fd1498Szrj puts (" if (GET_CODE (op) == CONST_DOUBLE && mode != VOIDmode)"
1257*38fd1498Szrj " rval = CONST_DOUBLE_REAL_VALUE (op);");
1258*38fd1498Szrj
1259*38fd1498Szrj write_predicate_stmts (c->exp);
1260*38fd1498Szrj fputs ("}\n", stdout);
1261*38fd1498Szrj }
1262*38fd1498Szrj puts ("#endif /* tm-constrs.h */");
1263*38fd1498Szrj }
1264*38fd1498Szrj
1265*38fd1498Szrj /* Write out the wrapper function, constraint_satisfied_p, that maps
1266*38fd1498Szrj a CONSTRAINT_xxx constant to one of the predicate functions generated
1267*38fd1498Szrj above. */
1268*38fd1498Szrj static void
write_constraint_satisfied_p_array(void)1269*38fd1498Szrj write_constraint_satisfied_p_array (void)
1270*38fd1498Szrj {
1271*38fd1498Szrj if (satisfied_start == num_constraints)
1272*38fd1498Szrj return;
1273*38fd1498Szrj
1274*38fd1498Szrj printf ("bool (*constraint_satisfied_p_array[]) (rtx) = {\n ");
1275*38fd1498Szrj for (unsigned int i = satisfied_start; i < num_constraints; ++i)
1276*38fd1498Szrj {
1277*38fd1498Szrj if (i != satisfied_start)
1278*38fd1498Szrj printf (",\n ");
1279*38fd1498Szrj printf ("satisfies_constraint_%s", enum_order[i]->c_name);
1280*38fd1498Szrj }
1281*38fd1498Szrj printf ("\n};\n\n");
1282*38fd1498Szrj }
1283*38fd1498Szrj
1284*38fd1498Szrj /* Write out the function which computes whether a given value matches
1285*38fd1498Szrj a given CONST_INT constraint. This doesn't just forward to
1286*38fd1498Szrj constraint_satisfied_p because caller passes the INTVAL, not the RTX. */
1287*38fd1498Szrj static void
write_insn_const_int_ok_for_constraint(void)1288*38fd1498Szrj write_insn_const_int_ok_for_constraint (void)
1289*38fd1498Szrj {
1290*38fd1498Szrj struct constraint_data *c;
1291*38fd1498Szrj
1292*38fd1498Szrj puts ("bool\n"
1293*38fd1498Szrj "insn_const_int_ok_for_constraint (HOST_WIDE_INT ival, "
1294*38fd1498Szrj "enum constraint_num c)\n"
1295*38fd1498Szrj "{\n"
1296*38fd1498Szrj " switch (c)\n"
1297*38fd1498Szrj " {");
1298*38fd1498Szrj
1299*38fd1498Szrj FOR_ALL_CONSTRAINTS (c)
1300*38fd1498Szrj if (c->is_const_int)
1301*38fd1498Szrj {
1302*38fd1498Szrj printf (" case CONSTRAINT_%s:\n return ", c->c_name);
1303*38fd1498Szrj /* c->exp is guaranteed to be (and (match_code "const_int") (...));
1304*38fd1498Szrj we know at this point that we have a const_int, so we need not
1305*38fd1498Szrj bother with that part of the test. */
1306*38fd1498Szrj write_predicate_expr (XEXP (c->exp, 1));
1307*38fd1498Szrj fputs (";\n\n", stdout);
1308*38fd1498Szrj }
1309*38fd1498Szrj
1310*38fd1498Szrj puts (" default: break;\n"
1311*38fd1498Szrj " }\n"
1312*38fd1498Szrj " return false;\n"
1313*38fd1498Szrj "}\n");
1314*38fd1498Szrj }
1315*38fd1498Szrj
1316*38fd1498Szrj /* Write a definition for a function NAME that returns true if a given
1317*38fd1498Szrj constraint_num is in the range [START, END). */
1318*38fd1498Szrj static void
write_range_function(const char * name,unsigned int start,unsigned int end)1319*38fd1498Szrj write_range_function (const char *name, unsigned int start, unsigned int end)
1320*38fd1498Szrj {
1321*38fd1498Szrj printf ("static inline bool\n");
1322*38fd1498Szrj if (start != end)
1323*38fd1498Szrj printf ("%s (enum constraint_num c)\n"
1324*38fd1498Szrj "{\n"
1325*38fd1498Szrj " return c >= CONSTRAINT_%s && c <= CONSTRAINT_%s;\n"
1326*38fd1498Szrj "}\n\n",
1327*38fd1498Szrj name, enum_order[start]->c_name, enum_order[end - 1]->c_name);
1328*38fd1498Szrj else
1329*38fd1498Szrj printf ("%s (enum constraint_num)\n"
1330*38fd1498Szrj "{\n"
1331*38fd1498Szrj " return false;\n"
1332*38fd1498Szrj "}\n\n", name);
1333*38fd1498Szrj }
1334*38fd1498Szrj
1335*38fd1498Szrj /* Write a definition for insn_extra_constraint_allows_reg_mem function. */
1336*38fd1498Szrj static void
write_allows_reg_mem_function(void)1337*38fd1498Szrj write_allows_reg_mem_function (void)
1338*38fd1498Szrj {
1339*38fd1498Szrj printf ("static inline void\n"
1340*38fd1498Szrj "insn_extra_constraint_allows_reg_mem (enum constraint_num c,\n"
1341*38fd1498Szrj "\t\t\t\t bool *allows_reg, bool *allows_mem)\n"
1342*38fd1498Szrj "{\n");
1343*38fd1498Szrj if (maybe_allows_none_start != maybe_allows_none_end)
1344*38fd1498Szrj printf (" if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n"
1345*38fd1498Szrj " return;\n",
1346*38fd1498Szrj enum_order[maybe_allows_none_start]->c_name,
1347*38fd1498Szrj enum_order[maybe_allows_none_end - 1]->c_name);
1348*38fd1498Szrj if (maybe_allows_reg_start != maybe_allows_reg_end)
1349*38fd1498Szrj printf (" if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n"
1350*38fd1498Szrj " {\n"
1351*38fd1498Szrj " *allows_reg = true;\n"
1352*38fd1498Szrj " return;\n"
1353*38fd1498Szrj " }\n",
1354*38fd1498Szrj enum_order[maybe_allows_reg_start]->c_name,
1355*38fd1498Szrj enum_order[maybe_allows_reg_end - 1]->c_name);
1356*38fd1498Szrj if (maybe_allows_mem_start != maybe_allows_mem_end)
1357*38fd1498Szrj printf (" if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n"
1358*38fd1498Szrj " {\n"
1359*38fd1498Szrj " *allows_mem = true;\n"
1360*38fd1498Szrj " return;\n"
1361*38fd1498Szrj " }\n",
1362*38fd1498Szrj enum_order[maybe_allows_mem_start]->c_name,
1363*38fd1498Szrj enum_order[maybe_allows_mem_end - 1]->c_name);
1364*38fd1498Szrj printf (" (void) c;\n"
1365*38fd1498Szrj " *allows_reg = true;\n"
1366*38fd1498Szrj " *allows_mem = true;\n"
1367*38fd1498Szrj "}\n\n");
1368*38fd1498Szrj }
1369*38fd1498Szrj
1370*38fd1498Szrj /* VEC is a list of key/value pairs, with the keys being lower bounds
1371*38fd1498Szrj of a range. Output a decision tree that handles the keys covered by
1372*38fd1498Szrj [VEC[START], VEC[END]), returning FALLBACK for keys lower then VEC[START]'s.
1373*38fd1498Szrj INDENT is the number of spaces to indent the code. */
1374*38fd1498Szrj static void
print_type_tree(const vec<std::pair<unsigned int,const char * >> & vec,unsigned int start,unsigned int end,const char * fallback,unsigned int indent)1375*38fd1498Szrj print_type_tree (const vec <std::pair <unsigned int, const char *> > &vec,
1376*38fd1498Szrj unsigned int start, unsigned int end, const char *fallback,
1377*38fd1498Szrj unsigned int indent)
1378*38fd1498Szrj {
1379*38fd1498Szrj while (start < end)
1380*38fd1498Szrj {
1381*38fd1498Szrj unsigned int mid = (start + end) / 2;
1382*38fd1498Szrj printf ("%*sif (c >= CONSTRAINT_%s)\n",
1383*38fd1498Szrj indent, "", enum_order[vec[mid].first]->c_name);
1384*38fd1498Szrj if (mid + 1 == end)
1385*38fd1498Szrj print_type_tree (vec, mid + 1, end, vec[mid].second, indent + 2);
1386*38fd1498Szrj else
1387*38fd1498Szrj {
1388*38fd1498Szrj printf ("%*s{\n", indent + 2, "");
1389*38fd1498Szrj print_type_tree (vec, mid + 1, end, vec[mid].second, indent + 4);
1390*38fd1498Szrj printf ("%*s}\n", indent + 2, "");
1391*38fd1498Szrj }
1392*38fd1498Szrj end = mid;
1393*38fd1498Szrj }
1394*38fd1498Szrj printf ("%*sreturn %s;\n", indent, "", fallback);
1395*38fd1498Szrj }
1396*38fd1498Szrj
1397*38fd1498Szrj /* Write tm-preds.h. Unfortunately, it is impossible to forward-declare
1398*38fd1498Szrj an enumeration in portable C, so we have to condition all these
1399*38fd1498Szrj prototypes on HAVE_MACHINE_MODES. */
1400*38fd1498Szrj static void
write_tm_preds_h(void)1401*38fd1498Szrj write_tm_preds_h (void)
1402*38fd1498Szrj {
1403*38fd1498Szrj struct pred_data *p;
1404*38fd1498Szrj
1405*38fd1498Szrj printf ("\
1406*38fd1498Szrj /* Generated automatically by the program '%s'\n\
1407*38fd1498Szrj from the machine description file '%s'. */\n\n", progname,
1408*38fd1498Szrj md_reader_ptr->get_top_level_filename ());
1409*38fd1498Szrj
1410*38fd1498Szrj puts ("\
1411*38fd1498Szrj #ifndef GCC_TM_PREDS_H\n\
1412*38fd1498Szrj #define GCC_TM_PREDS_H\n\
1413*38fd1498Szrj \n\
1414*38fd1498Szrj #ifdef HAVE_MACHINE_MODES");
1415*38fd1498Szrj
1416*38fd1498Szrj FOR_ALL_PREDICATES (p)
1417*38fd1498Szrj printf ("extern int %s (rtx, machine_mode);\n", p->name);
1418*38fd1498Szrj
1419*38fd1498Szrj puts ("#endif /* HAVE_MACHINE_MODES */\n");
1420*38fd1498Szrj
1421*38fd1498Szrj if (constraint_max_namelen > 0)
1422*38fd1498Szrj {
1423*38fd1498Szrj write_enum_constraint_num ();
1424*38fd1498Szrj puts ("extern enum constraint_num lookup_constraint_1 (const char *);\n"
1425*38fd1498Szrj "extern const unsigned char lookup_constraint_array[];\n"
1426*38fd1498Szrj "\n"
1427*38fd1498Szrj "/* Return the constraint at the beginning of P, or"
1428*38fd1498Szrj " CONSTRAINT__UNKNOWN if it\n"
1429*38fd1498Szrj " isn't recognized. */\n"
1430*38fd1498Szrj "\n"
1431*38fd1498Szrj "static inline enum constraint_num\n"
1432*38fd1498Szrj "lookup_constraint (const char *p)\n"
1433*38fd1498Szrj "{\n"
1434*38fd1498Szrj " unsigned int index = lookup_constraint_array"
1435*38fd1498Szrj "[(unsigned char) *p];\n"
1436*38fd1498Szrj " return (index == UCHAR_MAX\n"
1437*38fd1498Szrj " ? lookup_constraint_1 (p)\n"
1438*38fd1498Szrj " : (enum constraint_num) index);\n"
1439*38fd1498Szrj "}\n");
1440*38fd1498Szrj if (satisfied_start == num_constraints)
1441*38fd1498Szrj puts ("/* Return true if X satisfies constraint C. */\n"
1442*38fd1498Szrj "\n"
1443*38fd1498Szrj "static inline bool\n"
1444*38fd1498Szrj "constraint_satisfied_p (rtx, enum constraint_num)\n"
1445*38fd1498Szrj "{\n"
1446*38fd1498Szrj " return false;\n"
1447*38fd1498Szrj "}\n");
1448*38fd1498Szrj else
1449*38fd1498Szrj printf ("extern bool (*constraint_satisfied_p_array[]) (rtx);\n"
1450*38fd1498Szrj "\n"
1451*38fd1498Szrj "/* Return true if X satisfies constraint C. */\n"
1452*38fd1498Szrj "\n"
1453*38fd1498Szrj "static inline bool\n"
1454*38fd1498Szrj "constraint_satisfied_p (rtx x, enum constraint_num c)\n"
1455*38fd1498Szrj "{\n"
1456*38fd1498Szrj " int i = (int) c - (int) CONSTRAINT_%s;\n"
1457*38fd1498Szrj " return i >= 0 && constraint_satisfied_p_array[i] (x);\n"
1458*38fd1498Szrj "}\n"
1459*38fd1498Szrj "\n",
1460*38fd1498Szrj enum_order[satisfied_start]->name);
1461*38fd1498Szrj
1462*38fd1498Szrj write_range_function ("insn_extra_register_constraint",
1463*38fd1498Szrj register_start, register_end);
1464*38fd1498Szrj write_range_function ("insn_extra_memory_constraint",
1465*38fd1498Szrj memory_start, memory_end);
1466*38fd1498Szrj write_range_function ("insn_extra_special_memory_constraint",
1467*38fd1498Szrj special_memory_start, special_memory_end);
1468*38fd1498Szrj write_range_function ("insn_extra_address_constraint",
1469*38fd1498Szrj address_start, address_end);
1470*38fd1498Szrj write_allows_reg_mem_function ();
1471*38fd1498Szrj
1472*38fd1498Szrj if (constraint_max_namelen > 1)
1473*38fd1498Szrj {
1474*38fd1498Szrj write_insn_constraint_len ();
1475*38fd1498Szrj puts ("#define CONSTRAINT_LEN(c_,s_) "
1476*38fd1498Szrj "insn_constraint_len (c_,s_)\n");
1477*38fd1498Szrj }
1478*38fd1498Szrj else
1479*38fd1498Szrj puts ("#define CONSTRAINT_LEN(c_,s_) 1\n");
1480*38fd1498Szrj if (have_register_constraints)
1481*38fd1498Szrj puts ("extern enum reg_class reg_class_for_constraint_1 "
1482*38fd1498Szrj "(enum constraint_num);\n"
1483*38fd1498Szrj "\n"
1484*38fd1498Szrj "static inline enum reg_class\n"
1485*38fd1498Szrj "reg_class_for_constraint (enum constraint_num c)\n"
1486*38fd1498Szrj "{\n"
1487*38fd1498Szrj " if (insn_extra_register_constraint (c))\n"
1488*38fd1498Szrj " return reg_class_for_constraint_1 (c);\n"
1489*38fd1498Szrj " return NO_REGS;\n"
1490*38fd1498Szrj "}\n");
1491*38fd1498Szrj else
1492*38fd1498Szrj puts ("static inline enum reg_class\n"
1493*38fd1498Szrj "reg_class_for_constraint (enum constraint_num)\n"
1494*38fd1498Szrj "{\n"
1495*38fd1498Szrj " return NO_REGS;\n"
1496*38fd1498Szrj "}\n");
1497*38fd1498Szrj if (have_const_int_constraints)
1498*38fd1498Szrj puts ("extern bool insn_const_int_ok_for_constraint "
1499*38fd1498Szrj "(HOST_WIDE_INT, enum constraint_num);\n"
1500*38fd1498Szrj "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n"
1501*38fd1498Szrj " insn_const_int_ok_for_constraint (v_, "
1502*38fd1498Szrj "lookup_constraint (s_))\n");
1503*38fd1498Szrj else
1504*38fd1498Szrj puts ("static inline bool\n"
1505*38fd1498Szrj "insn_const_int_ok_for_constraint (HOST_WIDE_INT,"
1506*38fd1498Szrj " enum constraint_num)\n"
1507*38fd1498Szrj "{\n"
1508*38fd1498Szrj " return false;\n"
1509*38fd1498Szrj "}\n");
1510*38fd1498Szrj
1511*38fd1498Szrj puts ("enum constraint_type\n"
1512*38fd1498Szrj "{\n"
1513*38fd1498Szrj " CT_REGISTER,\n"
1514*38fd1498Szrj " CT_CONST_INT,\n"
1515*38fd1498Szrj " CT_MEMORY,\n"
1516*38fd1498Szrj " CT_SPECIAL_MEMORY,\n"
1517*38fd1498Szrj " CT_ADDRESS,\n"
1518*38fd1498Szrj " CT_FIXED_FORM\n"
1519*38fd1498Szrj "};\n"
1520*38fd1498Szrj "\n"
1521*38fd1498Szrj "static inline enum constraint_type\n"
1522*38fd1498Szrj "get_constraint_type (enum constraint_num c)\n"
1523*38fd1498Szrj "{");
1524*38fd1498Szrj auto_vec <std::pair <unsigned int, const char *>, 4> values;
1525*38fd1498Szrj if (const_int_start != const_int_end)
1526*38fd1498Szrj values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT"));
1527*38fd1498Szrj if (memory_start != memory_end)
1528*38fd1498Szrj values.safe_push (std::make_pair (memory_start, "CT_MEMORY"));
1529*38fd1498Szrj if (special_memory_start != special_memory_end)
1530*38fd1498Szrj values.safe_push (std::make_pair (special_memory_start, "CT_SPECIAL_MEMORY"));
1531*38fd1498Szrj if (address_start != address_end)
1532*38fd1498Szrj values.safe_push (std::make_pair (address_start, "CT_ADDRESS"));
1533*38fd1498Szrj if (address_end != num_constraints)
1534*38fd1498Szrj values.safe_push (std::make_pair (address_end, "CT_FIXED_FORM"));
1535*38fd1498Szrj print_type_tree (values, 0, values.length (), "CT_REGISTER", 2);
1536*38fd1498Szrj puts ("}");
1537*38fd1498Szrj }
1538*38fd1498Szrj
1539*38fd1498Szrj puts ("#endif /* tm-preds.h */");
1540*38fd1498Szrj }
1541*38fd1498Szrj
1542*38fd1498Szrj /* Write insn-preds.c.
1543*38fd1498Szrj N.B. the list of headers to include was copied from genrecog; it
1544*38fd1498Szrj may not be ideal.
1545*38fd1498Szrj
1546*38fd1498Szrj FUTURE: Write #line markers referring back to the machine
1547*38fd1498Szrj description. (Can't practically do this now since we don't know
1548*38fd1498Szrj the line number of the C block - just the line number of the enclosing
1549*38fd1498Szrj expression.) */
1550*38fd1498Szrj static void
write_insn_preds_c(void)1551*38fd1498Szrj write_insn_preds_c (void)
1552*38fd1498Szrj {
1553*38fd1498Szrj struct pred_data *p;
1554*38fd1498Szrj
1555*38fd1498Szrj printf ("\
1556*38fd1498Szrj /* Generated automatically by the program '%s'\n\
1557*38fd1498Szrj from the machine description file '%s'. */\n\n", progname,
1558*38fd1498Szrj md_reader_ptr->get_top_level_filename ());
1559*38fd1498Szrj
1560*38fd1498Szrj puts ("\
1561*38fd1498Szrj #define IN_TARGET_CODE 1\n\
1562*38fd1498Szrj #include \"config.h\"\n\
1563*38fd1498Szrj #include \"system.h\"\n\
1564*38fd1498Szrj #include \"coretypes.h\"\n\
1565*38fd1498Szrj #include \"backend.h\"\n\
1566*38fd1498Szrj #include \"predict.h\"\n\
1567*38fd1498Szrj #include \"tree.h\"\n\
1568*38fd1498Szrj #include \"rtl.h\"\n\
1569*38fd1498Szrj #include \"alias.h\"\n\
1570*38fd1498Szrj #include \"varasm.h\"\n\
1571*38fd1498Szrj #include \"stor-layout.h\"\n\
1572*38fd1498Szrj #include \"calls.h\"\n\
1573*38fd1498Szrj #include \"memmodel.h\"\n\
1574*38fd1498Szrj #include \"tm_p.h\"\n\
1575*38fd1498Szrj #include \"insn-config.h\"\n\
1576*38fd1498Szrj #include \"recog.h\"\n\
1577*38fd1498Szrj #include \"output.h\"\n\
1578*38fd1498Szrj #include \"flags.h\"\n\
1579*38fd1498Szrj #include \"df.h\"\n\
1580*38fd1498Szrj #include \"resource.h\"\n\
1581*38fd1498Szrj #include \"diagnostic-core.h\"\n\
1582*38fd1498Szrj #include \"reload.h\"\n\
1583*38fd1498Szrj #include \"regs.h\"\n\
1584*38fd1498Szrj #include \"emit-rtl.h\"\n\
1585*38fd1498Szrj #include \"tm-constrs.h\"\n\
1586*38fd1498Szrj #include \"target.h\"\n");
1587*38fd1498Szrj
1588*38fd1498Szrj FOR_ALL_PREDICATES (p)
1589*38fd1498Szrj write_one_predicate_function (p);
1590*38fd1498Szrj
1591*38fd1498Szrj if (constraint_max_namelen > 0)
1592*38fd1498Szrj {
1593*38fd1498Szrj write_lookup_constraint_1 ();
1594*38fd1498Szrj write_lookup_constraint_array ();
1595*38fd1498Szrj if (have_register_constraints)
1596*38fd1498Szrj write_reg_class_for_constraint_1 ();
1597*38fd1498Szrj write_constraint_satisfied_p_array ();
1598*38fd1498Szrj
1599*38fd1498Szrj if (have_const_int_constraints)
1600*38fd1498Szrj write_insn_const_int_ok_for_constraint ();
1601*38fd1498Szrj }
1602*38fd1498Szrj }
1603*38fd1498Szrj
1604*38fd1498Szrj /* Argument parsing. */
1605*38fd1498Szrj static bool gen_header;
1606*38fd1498Szrj static bool gen_constrs;
1607*38fd1498Szrj
1608*38fd1498Szrj static bool
parse_option(const char * opt)1609*38fd1498Szrj parse_option (const char *opt)
1610*38fd1498Szrj {
1611*38fd1498Szrj if (!strcmp (opt, "-h"))
1612*38fd1498Szrj {
1613*38fd1498Szrj gen_header = true;
1614*38fd1498Szrj return 1;
1615*38fd1498Szrj }
1616*38fd1498Szrj else if (!strcmp (opt, "-c"))
1617*38fd1498Szrj {
1618*38fd1498Szrj gen_constrs = true;
1619*38fd1498Szrj return 1;
1620*38fd1498Szrj }
1621*38fd1498Szrj else
1622*38fd1498Szrj return 0;
1623*38fd1498Szrj }
1624*38fd1498Szrj
1625*38fd1498Szrj /* Master control. */
1626*38fd1498Szrj int
main(int argc,const char ** argv)1627*38fd1498Szrj main (int argc, const char **argv)
1628*38fd1498Szrj {
1629*38fd1498Szrj progname = argv[0];
1630*38fd1498Szrj if (argc <= 1)
1631*38fd1498Szrj fatal ("no input file name");
1632*38fd1498Szrj if (!init_rtx_reader_args_cb (argc, argv, parse_option))
1633*38fd1498Szrj return FATAL_EXIT_CODE;
1634*38fd1498Szrj
1635*38fd1498Szrj md_rtx_info info;
1636*38fd1498Szrj while (read_md_rtx (&info))
1637*38fd1498Szrj switch (GET_CODE (info.def))
1638*38fd1498Szrj {
1639*38fd1498Szrj case DEFINE_PREDICATE:
1640*38fd1498Szrj case DEFINE_SPECIAL_PREDICATE:
1641*38fd1498Szrj process_define_predicate (&info);
1642*38fd1498Szrj break;
1643*38fd1498Szrj
1644*38fd1498Szrj case DEFINE_CONSTRAINT:
1645*38fd1498Szrj case DEFINE_MEMORY_CONSTRAINT:
1646*38fd1498Szrj case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
1647*38fd1498Szrj case DEFINE_ADDRESS_CONSTRAINT:
1648*38fd1498Szrj process_define_constraint (&info);
1649*38fd1498Szrj break;
1650*38fd1498Szrj
1651*38fd1498Szrj case DEFINE_REGISTER_CONSTRAINT:
1652*38fd1498Szrj process_define_register_constraint (&info);
1653*38fd1498Szrj break;
1654*38fd1498Szrj
1655*38fd1498Szrj default:
1656*38fd1498Szrj break;
1657*38fd1498Szrj }
1658*38fd1498Szrj
1659*38fd1498Szrj choose_enum_order ();
1660*38fd1498Szrj
1661*38fd1498Szrj if (gen_header)
1662*38fd1498Szrj write_tm_preds_h ();
1663*38fd1498Szrj else if (gen_constrs)
1664*38fd1498Szrj write_tm_constrs_h ();
1665*38fd1498Szrj else
1666*38fd1498Szrj write_insn_preds_c ();
1667*38fd1498Szrj
1668*38fd1498Szrj if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
1669*38fd1498Szrj return FATAL_EXIT_CODE;
1670*38fd1498Szrj
1671*38fd1498Szrj return SUCCESS_EXIT_CODE;
1672*38fd1498Szrj }
1673