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