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-2023 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 | unsigned int is_register : 1; |
681 | unsigned int is_const_int : 1; |
682 | unsigned int is_const_dbl : 1; |
683 | unsigned int : 1; |
684 | unsigned int is_memory : 1; |
685 | unsigned int is_special_memory: 1; |
686 | unsigned int is_relaxed_memory: 1; |
687 | unsigned int is_address : 1; |
688 | unsigned int maybe_allows_reg : 1; |
689 | unsigned int maybe_allows_mem : 1; |
690 | }; |
691 | |
692 | /* Overview of all constraints beginning with a given letter. */ |
693 | |
694 | static class constraint_data * |
695 | constraints_by_letter_table[1<<CHAR_BIT]; |
696 | |
697 | /* For looking up all the constraints in the order that they appeared |
698 | in the machine description. */ |
699 | static class constraint_data *first_constraint; |
700 | static class constraint_data **last_constraint_ptr = &first_constraint; |
701 | |
702 | #define FOR_ALL_CONSTRAINTS(iter_) \ |
703 | for (iter_ = first_constraint; iter_; iter_ = iter_->next_textual) |
704 | |
705 | /* Contraint letters that have a special meaning and that cannot be used |
706 | in define*_constraints. */ |
707 | static const char generic_constraint_letters[] = "g" ; |
708 | |
709 | /* Machine-independent code expects that constraints with these |
710 | (initial) letters will allow only (a subset of all) CONST_INTs. */ |
711 | |
712 | static const char const_int_constraints[] = "IJKLMNOP" ; |
713 | |
714 | /* Machine-independent code expects that constraints with these |
715 | (initial) letters will allow only (a subset of all) CONST_DOUBLEs. */ |
716 | |
717 | static const char const_dbl_constraints[] = "GH" ; |
718 | |
719 | /* Summary data used to decide whether to output various functions and |
720 | macro definitions. */ |
721 | static unsigned int constraint_max_namelen; |
722 | static bool have_register_constraints; |
723 | static bool have_memory_constraints; |
724 | static bool have_special_memory_constraints; |
725 | static bool have_relaxed_memory_constraints; |
726 | static bool have_address_constraints; |
727 | static bool ; |
728 | static bool have_const_int_constraints; |
729 | static unsigned int num_constraints; |
730 | |
731 | static const constraint_data **enum_order; |
732 | static unsigned int register_start, register_end; |
733 | static unsigned int satisfied_start; |
734 | static unsigned int const_int_start, const_int_end; |
735 | static unsigned int memory_start, memory_end; |
736 | static unsigned int special_memory_start, special_memory_end; |
737 | static unsigned int relaxed_memory_start, relaxed_memory_end; |
738 | static unsigned int address_start, address_end; |
739 | static unsigned int maybe_allows_none_start, maybe_allows_none_end; |
740 | static unsigned int maybe_allows_reg_start, maybe_allows_reg_end; |
741 | static unsigned int maybe_allows_mem_start, maybe_allows_mem_end; |
742 | |
743 | /* Convert NAME, which contains angle brackets and/or underscores, to |
744 | a string that can be used as part of a C identifier. The string |
745 | comes from the rtl_obstack. */ |
746 | static const char * |
747 | mangle (const char *name) |
748 | { |
749 | for (; *name; name++) |
750 | switch (*name) |
751 | { |
752 | case '_': obstack_grow (rtl_obstack, "__" , 2); break; |
753 | case '<': obstack_grow (rtl_obstack, "_l" , 2); break; |
754 | case '>': obstack_grow (rtl_obstack, "_g" , 2); break; |
755 | default: obstack_1grow (rtl_obstack, *name); break; |
756 | } |
757 | |
758 | obstack_1grow (rtl_obstack, '\0'); |
759 | return XOBFINISH (rtl_obstack, const char *); |
760 | } |
761 | |
762 | /* Add one constraint, of any sort, to the tables. NAME is its name; REGCLASS |
763 | is the register class, if any; EXP is the expression to test, if any; |
764 | IS_MEMORY, IS_SPECIAL_MEMORY, IS_RELAXED_MEMORY and IS_ADDRESS indicate |
765 | memory, special memory, and address constraints, respectively; LOC is the .md |
766 | file location. |
767 | |
768 | Not all combinations of arguments are valid; most importantly, REGCLASS is |
769 | mutually exclusive with EXP, and |
770 | IS_MEMORY/IS_SPECIAL_MEMORY/IS_RELAXED_MEMORY/IS_ADDRESS are only meaningful |
771 | for constraints with EXP. |
772 | |
773 | This function enforces all syntactic and semantic rules about what |
774 | constraints can be defined. */ |
775 | |
776 | static void |
777 | add_constraint (const char *name, const char *regclass, |
778 | rtx exp, bool is_memory, bool is_special_memory, |
779 | bool is_relaxed_memory, bool is_address, file_location loc) |
780 | { |
781 | class constraint_data *c, **iter, **slot; |
782 | const char *p; |
783 | bool need_mangled_name = false; |
784 | bool is_const_int; |
785 | bool is_const_dbl; |
786 | size_t namelen; |
787 | |
788 | if (strcmp (s1: name, s2: "TARGET_MEM_CONSTRAINT" ) == 0) |
789 | name = general_mem; |
790 | |
791 | if (exp && validate_exp (exp, name, loc)) |
792 | return; |
793 | |
794 | for (p = name; *p; p++) |
795 | if (!ISALNUM (*p)) |
796 | { |
797 | if (*p == '<' || *p == '>' || *p == '_') |
798 | need_mangled_name = true; |
799 | else |
800 | { |
801 | error_at (loc, "constraint name '%s' must be composed of letters," |
802 | " digits, underscores, and angle brackets" , name); |
803 | return; |
804 | } |
805 | } |
806 | |
807 | if (strchr (s: generic_constraint_letters, c: name[0])) |
808 | { |
809 | if (name[1] == '\0') |
810 | error_at (loc, "constraint letter '%s' cannot be " |
811 | "redefined by the machine description" , name); |
812 | else |
813 | error_at (loc, "constraint name '%s' cannot be defined by the machine" |
814 | " description, as it begins with '%c'" , name, name[0]); |
815 | return; |
816 | } |
817 | |
818 | |
819 | namelen = strlen (s: name); |
820 | slot = &constraints_by_letter_table[(unsigned int)name[0]]; |
821 | for (iter = slot; *iter; iter = &(*iter)->next_this_letter) |
822 | { |
823 | /* This causes slot to end up pointing to the |
824 | next_this_letter field of the last constraint with a name |
825 | of equal or greater length than the new constraint; hence |
826 | the new constraint will be inserted after all previous |
827 | constraints with names of the same length. */ |
828 | if ((*iter)->namelen >= namelen) |
829 | slot = iter; |
830 | |
831 | if (!strcmp (s1: (*iter)->name, s2: name)) |
832 | { |
833 | error_at (loc, "redefinition of constraint '%s'" , name); |
834 | message_at ((*iter)->loc, "previous definition is here" ); |
835 | return; |
836 | } |
837 | else if (!strncmp (s1: (*iter)->name, s2: name, n: (*iter)->namelen)) |
838 | { |
839 | error_at (loc, "defining constraint '%s' here" , name); |
840 | message_at ((*iter)->loc, "renders constraint '%s' " |
841 | "(defined here) a prefix" , (*iter)->name); |
842 | return; |
843 | } |
844 | else if (!strncmp (s1: (*iter)->name, s2: name, n: namelen)) |
845 | { |
846 | error_at (loc, "constraint '%s' is a prefix" , name); |
847 | message_at ((*iter)->loc, "of constraint '%s' (defined here)" , |
848 | (*iter)->name); |
849 | return; |
850 | } |
851 | } |
852 | |
853 | is_const_int = strchr (s: const_int_constraints, c: name[0]) != 0; |
854 | is_const_dbl = strchr (s: const_dbl_constraints, c: name[0]) != 0; |
855 | |
856 | if (is_const_int || is_const_dbl) |
857 | { |
858 | enum rtx_code appropriate_code |
859 | = is_const_int ? CONST_INT : CONST_DOUBLE; |
860 | |
861 | /* Consider relaxing this requirement in the future. */ |
862 | if (regclass |
863 | || GET_CODE (exp) != AND |
864 | || GET_CODE (XEXP (exp, 0)) != MATCH_CODE |
865 | || strcmp (XSTR (XEXP (exp, 0), 0), |
866 | GET_RTX_NAME (appropriate_code))) |
867 | { |
868 | if (name[1] == '\0') |
869 | error_at (loc, "constraint letter '%c' is reserved " |
870 | "for %s constraints" , name[0], |
871 | GET_RTX_NAME (appropriate_code)); |
872 | else |
873 | error_at (loc, "constraint names beginning with '%c' " |
874 | "(%s) are reserved for %s constraints" , |
875 | name[0], name, GET_RTX_NAME (appropriate_code)); |
876 | return; |
877 | } |
878 | |
879 | if (is_memory || is_special_memory || is_relaxed_memory) |
880 | { |
881 | if (name[1] == '\0') |
882 | error_at (loc, "constraint letter '%c' cannot be a " |
883 | "memory constraint" , name[0]); |
884 | else |
885 | error_at (loc, "constraint name '%s' begins with '%c', " |
886 | "and therefore cannot be a memory constraint" , |
887 | name, name[0]); |
888 | return; |
889 | } |
890 | else if (is_address) |
891 | { |
892 | if (name[1] == '\0') |
893 | error_at (loc, "constraint letter '%c' cannot be an " |
894 | "address constraint" , name[0]); |
895 | else |
896 | error_at (loc, "constraint name '%s' begins with '%c', " |
897 | "and therefore cannot be an address constraint" , |
898 | name, name[0]); |
899 | return; |
900 | } |
901 | } |
902 | |
903 | |
904 | c = XOBNEW (rtl_obstack, class constraint_data); |
905 | c->name = name; |
906 | c->c_name = need_mangled_name ? mangle (name) : name; |
907 | c->loc = loc; |
908 | c->namelen = namelen; |
909 | c->regclass = regclass; |
910 | c->exp = exp; |
911 | c->is_register = regclass != 0; |
912 | c->is_const_int = is_const_int; |
913 | c->is_const_dbl = is_const_dbl; |
914 | c->is_extra = !(regclass || is_const_int || is_const_dbl); |
915 | c->is_memory = is_memory; |
916 | c->is_special_memory = is_special_memory; |
917 | c->is_relaxed_memory = is_relaxed_memory; |
918 | c->is_address = is_address; |
919 | c->maybe_allows_reg = true; |
920 | c->maybe_allows_mem = true; |
921 | if (exp) |
922 | { |
923 | char codes[NUM_RTX_CODE]; |
924 | compute_test_codes (exp, loc, codes); |
925 | if (!codes[REG] && !codes[SUBREG]) |
926 | c->maybe_allows_reg = false; |
927 | if (!codes[MEM]) |
928 | c->maybe_allows_mem = false; |
929 | } |
930 | c->next_this_letter = *slot; |
931 | *slot = c; |
932 | |
933 | /* Insert this constraint in the list of all constraints in textual |
934 | order. */ |
935 | c->next_textual = 0; |
936 | *last_constraint_ptr = c; |
937 | last_constraint_ptr = &c->next_textual; |
938 | |
939 | constraint_max_namelen = MAX (constraint_max_namelen, strlen (name)); |
940 | have_register_constraints |= c->is_register; |
941 | have_const_int_constraints |= c->is_const_int; |
942 | have_extra_constraints |= c->is_extra; |
943 | have_memory_constraints |= c->is_memory; |
944 | have_special_memory_constraints |= c->is_special_memory; |
945 | have_relaxed_memory_constraints |= c->is_relaxed_memory; |
946 | have_address_constraints |= c->is_address; |
947 | num_constraints += 1; |
948 | } |
949 | |
950 | /* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, |
951 | DEFINE_SPECIAL_MEMORY_CONSTRAINT, DEFINE_RELAXED_MEMORY_CONSTRAINT, or |
952 | DEFINE_ADDRESS_CONSTRAINT expression, C. */ |
953 | static void |
954 | process_define_constraint (md_rtx_info *info) |
955 | { |
956 | add_constraint (XSTR (info->def, 0), regclass: 0, XEXP (info->def, 2), |
957 | GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT, |
958 | GET_CODE (info->def) == DEFINE_SPECIAL_MEMORY_CONSTRAINT, |
959 | GET_CODE (info->def) == DEFINE_RELAXED_MEMORY_CONSTRAINT, |
960 | GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT, |
961 | loc: info->loc); |
962 | } |
963 | |
964 | /* Process a DEFINE_REGISTER_CONSTRAINT expression, C. */ |
965 | static void |
966 | process_define_register_constraint (md_rtx_info *info) |
967 | { |
968 | add_constraint (XSTR (info->def, 0), XSTR (info->def, 1), |
969 | exp: 0, is_memory: false, is_special_memory: false, is_relaxed_memory: false, is_address: false, loc: info->loc); |
970 | } |
971 | |
972 | /* Put the constraints into enum order. We want to keep constraints |
973 | of the same type together so that query functions can be simple |
974 | range checks. */ |
975 | static void |
976 | choose_enum_order (void) |
977 | { |
978 | class constraint_data *c; |
979 | |
980 | enum_order = XNEWVEC (const constraint_data *, num_constraints); |
981 | unsigned int next = 0; |
982 | |
983 | register_start = next; |
984 | FOR_ALL_CONSTRAINTS (c) |
985 | if (c->is_register) |
986 | enum_order[next++] = c; |
987 | register_end = next; |
988 | |
989 | satisfied_start = next; |
990 | |
991 | const_int_start = next; |
992 | FOR_ALL_CONSTRAINTS (c) |
993 | if (c->is_const_int) |
994 | enum_order[next++] = c; |
995 | const_int_end = next; |
996 | |
997 | memory_start = next; |
998 | FOR_ALL_CONSTRAINTS (c) |
999 | if (c->is_memory) |
1000 | enum_order[next++] = c; |
1001 | memory_end = next; |
1002 | |
1003 | special_memory_start = next; |
1004 | FOR_ALL_CONSTRAINTS (c) |
1005 | if (c->is_special_memory) |
1006 | enum_order[next++] = c; |
1007 | special_memory_end = next; |
1008 | |
1009 | relaxed_memory_start = next; |
1010 | FOR_ALL_CONSTRAINTS (c) |
1011 | if (c->is_relaxed_memory) |
1012 | enum_order[next++] = c; |
1013 | relaxed_memory_end = next; |
1014 | |
1015 | address_start = next; |
1016 | FOR_ALL_CONSTRAINTS (c) |
1017 | if (c->is_address) |
1018 | enum_order[next++] = c; |
1019 | address_end = next; |
1020 | |
1021 | maybe_allows_none_start = next; |
1022 | FOR_ALL_CONSTRAINTS (c) |
1023 | if (!c->is_register && !c->is_const_int && !c->is_memory |
1024 | && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address |
1025 | && !c->maybe_allows_reg && !c->maybe_allows_mem) |
1026 | enum_order[next++] = c; |
1027 | maybe_allows_none_end = next; |
1028 | |
1029 | maybe_allows_reg_start = next; |
1030 | FOR_ALL_CONSTRAINTS (c) |
1031 | if (!c->is_register && !c->is_const_int && !c->is_memory |
1032 | && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address |
1033 | && c->maybe_allows_reg && !c->maybe_allows_mem) |
1034 | enum_order[next++] = c; |
1035 | maybe_allows_reg_end = next; |
1036 | |
1037 | maybe_allows_mem_start = next; |
1038 | FOR_ALL_CONSTRAINTS (c) |
1039 | if (!c->is_register && !c->is_const_int && !c->is_memory |
1040 | && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address |
1041 | && !c->maybe_allows_reg && c->maybe_allows_mem) |
1042 | enum_order[next++] = c; |
1043 | maybe_allows_mem_end = next; |
1044 | |
1045 | FOR_ALL_CONSTRAINTS (c) |
1046 | if (!c->is_register && !c->is_const_int && !c->is_memory |
1047 | && !c->is_special_memory && !c->is_relaxed_memory && !c->is_address |
1048 | && c->maybe_allows_reg && c->maybe_allows_mem) |
1049 | enum_order[next++] = c; |
1050 | gcc_assert (next == num_constraints); |
1051 | } |
1052 | |
1053 | /* Write out an enumeration with one entry per machine-specific |
1054 | constraint. */ |
1055 | static void |
1056 | write_enum_constraint_num (void) |
1057 | { |
1058 | fputs ("#define CONSTRAINT_NUM_DEFINED_P 1\n" , stdout); |
1059 | fputs ("enum constraint_num\n" |
1060 | "{\n" |
1061 | " CONSTRAINT__UNKNOWN = 0" , stdout); |
1062 | for (unsigned int i = 0; i < num_constraints; ++i) |
1063 | printf (format: ",\n CONSTRAINT_%s" , enum_order[i]->c_name); |
1064 | puts (s: ",\n CONSTRAINT__LIMIT\n};\n" ); |
1065 | } |
1066 | |
1067 | /* Write out a function which looks at a string and determines what |
1068 | constraint name, if any, it begins with. */ |
1069 | static void |
1070 | write_lookup_constraint_1 (void) |
1071 | { |
1072 | unsigned int i; |
1073 | puts (s: "enum constraint_num\n" |
1074 | "lookup_constraint_1 (const char *str)\n" |
1075 | "{\n" |
1076 | " switch (str[0])\n" |
1077 | " {" ); |
1078 | |
1079 | for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++) |
1080 | { |
1081 | class constraint_data *c = constraints_by_letter_table[i]; |
1082 | if (!c) |
1083 | continue; |
1084 | |
1085 | printf (format: " case '%c':\n" , i); |
1086 | if (c->namelen == 1) |
1087 | printf (format: " return CONSTRAINT_%s;\n" , c->c_name); |
1088 | else |
1089 | { |
1090 | do |
1091 | { |
1092 | if (c->namelen > 2) |
1093 | printf (format: " if (!strncmp (str + 1, \"%s\", %lu))\n" |
1094 | " return CONSTRAINT_%s;\n" , |
1095 | c->name + 1, (unsigned long int) c->namelen - 1, |
1096 | c->c_name); |
1097 | else |
1098 | printf (format: " if (str[1] == '%c')\n" |
1099 | " return CONSTRAINT_%s;\n" , |
1100 | c->name[1], c->c_name); |
1101 | c = c->next_this_letter; |
1102 | } |
1103 | while (c); |
1104 | puts (s: " break;" ); |
1105 | } |
1106 | } |
1107 | |
1108 | puts (s: " default: break;\n" |
1109 | " }\n" |
1110 | " return CONSTRAINT__UNKNOWN;\n" |
1111 | "}\n" ); |
1112 | } |
1113 | |
1114 | /* Write out an array that maps single-letter characters to their |
1115 | constraints (if that fits in a character) or 255 if lookup_constraint_1 |
1116 | must be called. */ |
1117 | static void |
1118 | write_lookup_constraint_array (void) |
1119 | { |
1120 | unsigned int i; |
1121 | printf (format: "const unsigned char lookup_constraint_array[] = {\n " ); |
1122 | for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++) |
1123 | { |
1124 | if (i != 0) |
1125 | printf (format: ",\n " ); |
1126 | class constraint_data *c = constraints_by_letter_table[i]; |
1127 | if (!c) |
1128 | printf (format: "CONSTRAINT__UNKNOWN" ); |
1129 | else if (c->namelen == 1) |
1130 | printf (format: "MIN ((int) CONSTRAINT_%s, (int) UCHAR_MAX)" , c->c_name); |
1131 | else |
1132 | printf (format: "UCHAR_MAX" ); |
1133 | } |
1134 | printf (format: "\n};\n\n" ); |
1135 | } |
1136 | |
1137 | /* Write out a function which looks at a string and determines what |
1138 | the constraint name length is. */ |
1139 | static void |
1140 | write_insn_constraint_len (void) |
1141 | { |
1142 | unsigned int i; |
1143 | |
1144 | puts (s: "static inline size_t\n" |
1145 | "insn_constraint_len (char fc, const char *str ATTRIBUTE_UNUSED)\n" |
1146 | "{\n" |
1147 | " switch (fc)\n" |
1148 | " {" ); |
1149 | |
1150 | for (i = 0; i < ARRAY_SIZE (constraints_by_letter_table); i++) |
1151 | { |
1152 | class constraint_data *c = constraints_by_letter_table[i]; |
1153 | |
1154 | if (!c |
1155 | || c->namelen == 1) |
1156 | continue; |
1157 | |
1158 | /* Constraints with multiple characters should have the same |
1159 | length. */ |
1160 | { |
1161 | class constraint_data *c2 = c->next_this_letter; |
1162 | size_t len = c->namelen; |
1163 | while (c2) |
1164 | { |
1165 | if (c2->namelen != len) |
1166 | error ("Multi-letter constraints with first letter '%c' " |
1167 | "should have same length" , i); |
1168 | c2 = c2->next_this_letter; |
1169 | } |
1170 | } |
1171 | |
1172 | printf (format: " case '%c': return %lu;\n" , |
1173 | i, (unsigned long int) c->namelen); |
1174 | } |
1175 | |
1176 | puts (s: " default: break;\n" |
1177 | " }\n" |
1178 | " return 1;\n" |
1179 | "}\n" ); |
1180 | } |
1181 | |
1182 | /* Write out the function which computes the register class corresponding |
1183 | to a register constraint. */ |
1184 | static void |
1185 | write_reg_class_for_constraint_1 (void) |
1186 | { |
1187 | class constraint_data *c; |
1188 | |
1189 | puts (s: "enum reg_class\n" |
1190 | "reg_class_for_constraint_1 (enum constraint_num c)\n" |
1191 | "{\n" |
1192 | " switch (c)\n" |
1193 | " {" ); |
1194 | |
1195 | FOR_ALL_CONSTRAINTS (c) |
1196 | if (c->is_register) |
1197 | printf (format: " case CONSTRAINT_%s: return %s;\n" , c->c_name, c->regclass); |
1198 | |
1199 | puts (s: " default: break;\n" |
1200 | " }\n" |
1201 | " return NO_REGS;\n" |
1202 | "}\n" ); |
1203 | } |
1204 | |
1205 | /* Write out the functions which compute whether a given value matches |
1206 | a given non-register constraint. */ |
1207 | static void |
1208 | write_tm_constrs_h (void) |
1209 | { |
1210 | class constraint_data *c; |
1211 | |
1212 | printf (format: "\ |
1213 | /* Generated automatically by the program '%s'\n\ |
1214 | from the machine description file '%s'. */\n\n" , progname, |
1215 | md_reader_ptr->get_top_level_filename ()); |
1216 | |
1217 | puts (s: "\ |
1218 | #ifndef GCC_TM_CONSTRS_H\n\ |
1219 | #define GCC_TM_CONSTRS_H\n" ); |
1220 | |
1221 | FOR_ALL_CONSTRAINTS (c) |
1222 | if (!c->is_register) |
1223 | { |
1224 | bool needs_ival = needs_variable (exp: c->exp, var: "ival" ); |
1225 | bool needs_hval = needs_variable (exp: c->exp, var: "hval" ); |
1226 | bool needs_lval = needs_variable (exp: c->exp, var: "lval" ); |
1227 | bool needs_rval = needs_variable (exp: c->exp, var: "rval" ); |
1228 | bool needs_mode = (needs_variable (exp: c->exp, var: "mode" ) |
1229 | || needs_hval || needs_lval || needs_rval); |
1230 | bool needs_op = (needs_variable (exp: c->exp, var: "op" ) |
1231 | || needs_ival || needs_mode); |
1232 | |
1233 | printf (format: "static inline bool\n" |
1234 | "satisfies_constraint_%s (rtx %s)\n" |
1235 | "{\n" , c->c_name, |
1236 | needs_op ? "op" : "ARG_UNUSED (op)" ); |
1237 | if (needs_mode) |
1238 | puts (s: " machine_mode mode = GET_MODE (op);" ); |
1239 | if (needs_ival) |
1240 | puts (s: " HOST_WIDE_INT ival = 0;" ); |
1241 | if (needs_hval) |
1242 | puts (s: " HOST_WIDE_INT hval = 0;" ); |
1243 | if (needs_lval) |
1244 | puts (s: " unsigned HOST_WIDE_INT lval = 0;" ); |
1245 | if (needs_rval) |
1246 | puts (s: " const REAL_VALUE_TYPE *rval = 0;" ); |
1247 | |
1248 | if (needs_ival) |
1249 | puts (s: " if (CONST_INT_P (op))\n" |
1250 | " ival = INTVAL (op);" ); |
1251 | #if TARGET_SUPPORTS_WIDE_INT |
1252 | if (needs_lval || needs_hval) |
1253 | error ("you can't use lval or hval" ); |
1254 | #else |
1255 | if (needs_hval) |
1256 | puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)" |
1257 | " hval = CONST_DOUBLE_HIGH (op);" ); |
1258 | if (needs_lval) |
1259 | puts (" if (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode)" |
1260 | " lval = CONST_DOUBLE_LOW (op);" ); |
1261 | #endif |
1262 | if (needs_rval) |
1263 | puts (s: " if (GET_CODE (op) == CONST_DOUBLE && mode != VOIDmode)" |
1264 | " rval = CONST_DOUBLE_REAL_VALUE (op);" ); |
1265 | |
1266 | write_predicate_stmts (exp: c->exp); |
1267 | fputs ("}\n" , stdout); |
1268 | } |
1269 | puts (s: "#endif /* tm-constrs.h */" ); |
1270 | } |
1271 | |
1272 | /* Write out the wrapper function, constraint_satisfied_p, that maps |
1273 | a CONSTRAINT_xxx constant to one of the predicate functions generated |
1274 | above. */ |
1275 | static void |
1276 | write_constraint_satisfied_p_array (void) |
1277 | { |
1278 | if (satisfied_start == num_constraints) |
1279 | return; |
1280 | |
1281 | printf (format: "bool (*constraint_satisfied_p_array[]) (rtx) = {\n " ); |
1282 | for (unsigned int i = satisfied_start; i < num_constraints; ++i) |
1283 | { |
1284 | if (i != satisfied_start) |
1285 | printf (format: ",\n " ); |
1286 | printf (format: "satisfies_constraint_%s" , enum_order[i]->c_name); |
1287 | } |
1288 | printf (format: "\n};\n\n" ); |
1289 | } |
1290 | |
1291 | /* Write out the function which computes whether a given value matches |
1292 | a given CONST_INT constraint. This doesn't just forward to |
1293 | constraint_satisfied_p because caller passes the INTVAL, not the RTX. */ |
1294 | static void |
1295 | write_insn_const_int_ok_for_constraint (void) |
1296 | { |
1297 | class constraint_data *c; |
1298 | |
1299 | puts (s: "bool\n" |
1300 | "insn_const_int_ok_for_constraint (HOST_WIDE_INT ival, " |
1301 | "enum constraint_num c)\n" |
1302 | "{\n" |
1303 | " switch (c)\n" |
1304 | " {" ); |
1305 | |
1306 | FOR_ALL_CONSTRAINTS (c) |
1307 | if (c->is_const_int) |
1308 | { |
1309 | printf (format: " case CONSTRAINT_%s:\n return " , c->c_name); |
1310 | /* c->exp is guaranteed to be (and (match_code "const_int") (...)); |
1311 | we know at this point that we have a const_int, so we need not |
1312 | bother with that part of the test. */ |
1313 | write_predicate_expr (XEXP (c->exp, 1)); |
1314 | fputs (";\n\n" , stdout); |
1315 | } |
1316 | |
1317 | puts (s: " default: break;\n" |
1318 | " }\n" |
1319 | " return false;\n" |
1320 | "}\n" ); |
1321 | } |
1322 | |
1323 | /* Write a definition for a function NAME that returns true if a given |
1324 | constraint_num is in the range [START, END). */ |
1325 | static void |
1326 | write_range_function (const char *name, unsigned int start, unsigned int end) |
1327 | { |
1328 | printf (format: "static inline bool\n" ); |
1329 | if (start != end) |
1330 | printf (format: "%s (enum constraint_num c)\n" |
1331 | "{\n" |
1332 | " return c >= CONSTRAINT_%s && c <= CONSTRAINT_%s;\n" |
1333 | "}\n\n" , |
1334 | name, enum_order[start]->c_name, enum_order[end - 1]->c_name); |
1335 | else |
1336 | printf (format: "%s (enum constraint_num)\n" |
1337 | "{\n" |
1338 | " return false;\n" |
1339 | "}\n\n" , name); |
1340 | } |
1341 | |
1342 | /* Write a definition for insn_extra_constraint_allows_reg_mem function. */ |
1343 | static void |
1344 | write_allows_reg_mem_function (void) |
1345 | { |
1346 | printf (format: "static inline void\n" |
1347 | "insn_extra_constraint_allows_reg_mem (enum constraint_num c,\n" |
1348 | "\t\t\t\t bool *allows_reg, bool *allows_mem)\n" |
1349 | "{\n" ); |
1350 | if (maybe_allows_none_start != maybe_allows_none_end) |
1351 | printf (format: " if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n" |
1352 | " return;\n" , |
1353 | enum_order[maybe_allows_none_start]->c_name, |
1354 | enum_order[maybe_allows_none_end - 1]->c_name); |
1355 | if (maybe_allows_reg_start != maybe_allows_reg_end) |
1356 | printf (format: " if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n" |
1357 | " {\n" |
1358 | " *allows_reg = true;\n" |
1359 | " return;\n" |
1360 | " }\n" , |
1361 | enum_order[maybe_allows_reg_start]->c_name, |
1362 | enum_order[maybe_allows_reg_end - 1]->c_name); |
1363 | if (maybe_allows_mem_start != maybe_allows_mem_end) |
1364 | printf (format: " if (c >= CONSTRAINT_%s && c <= CONSTRAINT_%s)\n" |
1365 | " {\n" |
1366 | " *allows_mem = true;\n" |
1367 | " return;\n" |
1368 | " }\n" , |
1369 | enum_order[maybe_allows_mem_start]->c_name, |
1370 | enum_order[maybe_allows_mem_end - 1]->c_name); |
1371 | printf (format: " (void) c;\n" |
1372 | " *allows_reg = true;\n" |
1373 | " *allows_mem = true;\n" |
1374 | "}\n\n" ); |
1375 | } |
1376 | |
1377 | /* VEC is a list of key/value pairs, with the keys being lower bounds |
1378 | of a range. Output a decision tree that handles the keys covered by |
1379 | [VEC[START], VEC[END]), returning FALLBACK for keys lower then VEC[START]'s. |
1380 | INDENT is the number of spaces to indent the code. */ |
1381 | static void |
1382 | print_type_tree (const vec <std::pair <unsigned int, const char *> > &vec, |
1383 | unsigned int start, unsigned int end, const char *fallback, |
1384 | unsigned int indent) |
1385 | { |
1386 | while (start < end) |
1387 | { |
1388 | unsigned int mid = (start + end) / 2; |
1389 | printf (format: "%*sif (c >= CONSTRAINT_%s)\n" , |
1390 | indent, "" , enum_order[vec[mid].first]->c_name); |
1391 | if (mid + 1 == end) |
1392 | print_type_tree (vec, start: mid + 1, end, fallback: vec[mid].second, indent: indent + 2); |
1393 | else |
1394 | { |
1395 | printf (format: "%*s{\n" , indent + 2, "" ); |
1396 | print_type_tree (vec, start: mid + 1, end, fallback: vec[mid].second, indent: indent + 4); |
1397 | printf (format: "%*s}\n" , indent + 2, "" ); |
1398 | } |
1399 | end = mid; |
1400 | } |
1401 | printf (format: "%*sreturn %s;\n" , indent, "" , fallback); |
1402 | } |
1403 | |
1404 | /* Write tm-preds.h. Unfortunately, it is impossible to forward-declare |
1405 | an enumeration in portable C, so we have to condition all these |
1406 | prototypes on HAVE_MACHINE_MODES. */ |
1407 | static void |
1408 | write_tm_preds_h (void) |
1409 | { |
1410 | struct pred_data *p; |
1411 | |
1412 | printf (format: "\ |
1413 | /* Generated automatically by the program '%s'\n\ |
1414 | from the machine description file '%s'. */\n\n" , progname, |
1415 | md_reader_ptr->get_top_level_filename ()); |
1416 | |
1417 | puts (s: "\ |
1418 | #ifndef GCC_TM_PREDS_H\n\ |
1419 | #define GCC_TM_PREDS_H\n\ |
1420 | \n\ |
1421 | #ifdef HAVE_MACHINE_MODES" ); |
1422 | |
1423 | FOR_ALL_PREDICATES (p) |
1424 | printf (format: "extern bool %s (rtx, machine_mode);\n" , p->name); |
1425 | |
1426 | puts (s: "#endif /* HAVE_MACHINE_MODES */\n" ); |
1427 | |
1428 | if (constraint_max_namelen > 0) |
1429 | { |
1430 | write_enum_constraint_num (); |
1431 | puts (s: "extern enum constraint_num lookup_constraint_1 (const char *);\n" |
1432 | "extern const unsigned char lookup_constraint_array[];\n" |
1433 | "\n" |
1434 | "/* Return the constraint at the beginning of P, or" |
1435 | " CONSTRAINT__UNKNOWN if it\n" |
1436 | " isn't recognized. */\n" |
1437 | "\n" |
1438 | "static inline enum constraint_num\n" |
1439 | "lookup_constraint (const char *p)\n" |
1440 | "{\n" |
1441 | " unsigned int index = lookup_constraint_array" |
1442 | "[(unsigned char) *p];\n" |
1443 | " return (index == UCHAR_MAX\n" |
1444 | " ? lookup_constraint_1 (p)\n" |
1445 | " : (enum constraint_num) index);\n" |
1446 | "}\n" ); |
1447 | if (satisfied_start == num_constraints) |
1448 | puts (s: "/* Return true if X satisfies constraint C. */\n" |
1449 | "\n" |
1450 | "static inline bool\n" |
1451 | "constraint_satisfied_p (rtx, enum constraint_num)\n" |
1452 | "{\n" |
1453 | " return false;\n" |
1454 | "}\n" ); |
1455 | else |
1456 | printf (format: "extern bool (*constraint_satisfied_p_array[]) (rtx);\n" |
1457 | "\n" |
1458 | "/* Return true if X satisfies constraint C. */\n" |
1459 | "\n" |
1460 | "static inline bool\n" |
1461 | "constraint_satisfied_p (rtx x, enum constraint_num c)\n" |
1462 | "{\n" |
1463 | " int i = (int) c - (int) CONSTRAINT_%s;\n" |
1464 | " return i >= 0 && constraint_satisfied_p_array[i] (x);\n" |
1465 | "}\n" |
1466 | "\n" , |
1467 | enum_order[satisfied_start]->name); |
1468 | |
1469 | write_range_function (name: "insn_extra_register_constraint" , |
1470 | start: register_start, end: register_end); |
1471 | write_range_function (name: "insn_extra_memory_constraint" , |
1472 | start: memory_start, end: memory_end); |
1473 | write_range_function (name: "insn_extra_special_memory_constraint" , |
1474 | start: special_memory_start, end: special_memory_end); |
1475 | write_range_function (name: "insn_extra_relaxed_memory_constraint" , |
1476 | start: relaxed_memory_start, end: relaxed_memory_end); |
1477 | write_range_function (name: "insn_extra_address_constraint" , |
1478 | start: address_start, end: address_end); |
1479 | write_allows_reg_mem_function (); |
1480 | |
1481 | if (constraint_max_namelen > 1) |
1482 | { |
1483 | write_insn_constraint_len (); |
1484 | puts (s: "#define CONSTRAINT_LEN(c_,s_) " |
1485 | "insn_constraint_len (c_,s_)\n" ); |
1486 | } |
1487 | else |
1488 | puts (s: "#define CONSTRAINT_LEN(c_,s_) 1\n" ); |
1489 | if (have_register_constraints) |
1490 | puts (s: "extern enum reg_class reg_class_for_constraint_1 " |
1491 | "(enum constraint_num);\n" |
1492 | "\n" |
1493 | "static inline enum reg_class\n" |
1494 | "reg_class_for_constraint (enum constraint_num c)\n" |
1495 | "{\n" |
1496 | " if (insn_extra_register_constraint (c))\n" |
1497 | " return reg_class_for_constraint_1 (c);\n" |
1498 | " return NO_REGS;\n" |
1499 | "}\n" ); |
1500 | else |
1501 | puts (s: "static inline enum reg_class\n" |
1502 | "reg_class_for_constraint (enum constraint_num)\n" |
1503 | "{\n" |
1504 | " return NO_REGS;\n" |
1505 | "}\n" ); |
1506 | if (have_const_int_constraints) |
1507 | puts (s: "extern bool insn_const_int_ok_for_constraint " |
1508 | "(HOST_WIDE_INT, enum constraint_num);\n" |
1509 | "#define CONST_OK_FOR_CONSTRAINT_P(v_,c_,s_) \\\n" |
1510 | " insn_const_int_ok_for_constraint (v_, " |
1511 | "lookup_constraint (s_))\n" ); |
1512 | else |
1513 | puts (s: "static inline bool\n" |
1514 | "insn_const_int_ok_for_constraint (HOST_WIDE_INT," |
1515 | " enum constraint_num)\n" |
1516 | "{\n" |
1517 | " return false;\n" |
1518 | "}\n" ); |
1519 | |
1520 | puts (s: "enum constraint_type\n" |
1521 | "{\n" |
1522 | " CT_REGISTER,\n" |
1523 | " CT_CONST_INT,\n" |
1524 | " CT_MEMORY,\n" |
1525 | " CT_SPECIAL_MEMORY,\n" |
1526 | " CT_RELAXED_MEMORY,\n" |
1527 | " CT_ADDRESS,\n" |
1528 | " CT_FIXED_FORM\n" |
1529 | "};\n" |
1530 | "\n" |
1531 | "static inline enum constraint_type\n" |
1532 | "get_constraint_type (enum constraint_num c)\n" |
1533 | "{" ); |
1534 | auto_vec <std::pair <unsigned int, const char *>, 4> values; |
1535 | if (const_int_start != const_int_end) |
1536 | values.safe_push (obj: std::make_pair (x&: const_int_start, y: "CT_CONST_INT" )); |
1537 | if (memory_start != memory_end) |
1538 | values.safe_push (obj: std::make_pair (x&: memory_start, y: "CT_MEMORY" )); |
1539 | if (special_memory_start != special_memory_end) |
1540 | values.safe_push (obj: std::make_pair (x&: special_memory_start, |
1541 | y: "CT_SPECIAL_MEMORY" )); |
1542 | if (relaxed_memory_start != relaxed_memory_end) |
1543 | values.safe_push (obj: std::make_pair (x&: relaxed_memory_start, |
1544 | y: "CT_RELAXED_MEMORY" )); |
1545 | if (address_start != address_end) |
1546 | values.safe_push (obj: std::make_pair (x&: address_start, y: "CT_ADDRESS" )); |
1547 | if (address_end != num_constraints) |
1548 | values.safe_push (obj: std::make_pair (x&: address_end, y: "CT_FIXED_FORM" )); |
1549 | print_type_tree (vec: values, start: 0, end: values.length (), fallback: "CT_REGISTER" , indent: 2); |
1550 | puts (s: "}" ); |
1551 | } |
1552 | |
1553 | puts (s: "#endif /* tm-preds.h */" ); |
1554 | } |
1555 | |
1556 | /* Write insn-preds.cc. |
1557 | N.B. the list of headers to include was copied from genrecog; it |
1558 | may not be ideal. |
1559 | |
1560 | FUTURE: Write #line markers referring back to the machine |
1561 | description. (Can't practically do this now since we don't know |
1562 | the line number of the C block - just the line number of the enclosing |
1563 | expression.) */ |
1564 | static void |
1565 | write_insn_preds_c (void) |
1566 | { |
1567 | struct pred_data *p; |
1568 | |
1569 | printf (format: "\ |
1570 | /* Generated automatically by the program '%s'\n\ |
1571 | from the machine description file '%s'. */\n\n" , progname, |
1572 | md_reader_ptr->get_top_level_filename ()); |
1573 | |
1574 | puts (s: "\ |
1575 | #define IN_TARGET_CODE 1\n\ |
1576 | #include \"config.h\"\n\ |
1577 | #include \"system.h\"\n\ |
1578 | #include \"coretypes.h\"\n\ |
1579 | #include \"backend.h\"\n\ |
1580 | #include \"predict.h\"\n\ |
1581 | #include \"tree.h\"\n\ |
1582 | #include \"rtl.h\"\n\ |
1583 | #include \"alias.h\"\n\ |
1584 | #include \"varasm.h\"\n\ |
1585 | #include \"stor-layout.h\"\n\ |
1586 | #include \"calls.h\"\n\ |
1587 | #include \"memmodel.h\"\n\ |
1588 | #include \"tm_p.h\"\n\ |
1589 | #include \"insn-config.h\"\n\ |
1590 | #include \"recog.h\"\n\ |
1591 | #include \"output.h\"\n\ |
1592 | #include \"flags.h\"\n\ |
1593 | #include \"df.h\"\n\ |
1594 | #include \"resource.h\"\n\ |
1595 | #include \"diagnostic-core.h\"\n\ |
1596 | #include \"reload.h\"\n\ |
1597 | #include \"regs.h\"\n\ |
1598 | #include \"emit-rtl.h\"\n\ |
1599 | #include \"tm-constrs.h\"\n\ |
1600 | #include \"target.h\"\n" ); |
1601 | |
1602 | FOR_ALL_PREDICATES (p) |
1603 | write_one_predicate_function (p); |
1604 | |
1605 | if (constraint_max_namelen > 0) |
1606 | { |
1607 | write_lookup_constraint_1 (); |
1608 | write_lookup_constraint_array (); |
1609 | if (have_register_constraints) |
1610 | write_reg_class_for_constraint_1 (); |
1611 | write_constraint_satisfied_p_array (); |
1612 | |
1613 | if (have_const_int_constraints) |
1614 | write_insn_const_int_ok_for_constraint (); |
1615 | } |
1616 | } |
1617 | |
1618 | /* Argument parsing. */ |
1619 | static bool ; |
1620 | static bool gen_constrs; |
1621 | |
1622 | static bool |
1623 | parse_option (const char *opt) |
1624 | { |
1625 | if (!strcmp (s1: opt, s2: "-h" )) |
1626 | { |
1627 | gen_header = true; |
1628 | return 1; |
1629 | } |
1630 | else if (!strcmp (s1: opt, s2: "-c" )) |
1631 | { |
1632 | gen_constrs = true; |
1633 | return 1; |
1634 | } |
1635 | else |
1636 | return 0; |
1637 | } |
1638 | |
1639 | /* Master control. */ |
1640 | int |
1641 | main (int argc, const char **argv) |
1642 | { |
1643 | progname = argv[0]; |
1644 | if (argc <= 1) |
1645 | fatal ("no input file name" ); |
1646 | if (!init_rtx_reader_args_cb (argc, argv, parse_option)) |
1647 | return FATAL_EXIT_CODE; |
1648 | |
1649 | md_rtx_info info; |
1650 | while (read_md_rtx (&info)) |
1651 | switch (GET_CODE (info.def)) |
1652 | { |
1653 | case DEFINE_PREDICATE: |
1654 | case DEFINE_SPECIAL_PREDICATE: |
1655 | process_define_predicate (info: &info); |
1656 | break; |
1657 | |
1658 | case DEFINE_CONSTRAINT: |
1659 | case DEFINE_MEMORY_CONSTRAINT: |
1660 | case DEFINE_SPECIAL_MEMORY_CONSTRAINT: |
1661 | case DEFINE_RELAXED_MEMORY_CONSTRAINT: |
1662 | case DEFINE_ADDRESS_CONSTRAINT: |
1663 | process_define_constraint (info: &info); |
1664 | break; |
1665 | |
1666 | case DEFINE_REGISTER_CONSTRAINT: |
1667 | process_define_register_constraint (info: &info); |
1668 | break; |
1669 | |
1670 | default: |
1671 | break; |
1672 | } |
1673 | |
1674 | choose_enum_order (); |
1675 | |
1676 | if (gen_header) |
1677 | write_tm_preds_h (); |
1678 | else if (gen_constrs) |
1679 | write_tm_constrs_h (); |
1680 | else |
1681 | write_insn_preds_c (); |
1682 | |
1683 | if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout)) |
1684 | return FATAL_EXIT_CODE; |
1685 | |
1686 | return SUCCESS_EXIT_CODE; |
1687 | } |
1688 | |