1/* Support routines for the various generation passes.
2 Copyright (C) 2000-2023 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20#include "bconfig.h"
21#define INCLUDE_STRING
22#define INCLUDE_VECTOR
23#include "system.h"
24#include "coretypes.h"
25#include "tm.h"
26#include "rtl.h"
27#include "obstack.h"
28#include "errors.h"
29#include "read-md.h"
30#include "gensupport.h"
31#include "vec.h"
32
33#define MAX_OPERANDS 40
34
35static rtx operand_data[MAX_OPERANDS];
36static rtx match_operand_entries_in_pattern[MAX_OPERANDS];
37static char used_operands_numbers[MAX_OPERANDS];
38/* List of entries which are part of the new syntax. */
39hash_set<rtx> compact_syntax;
40
41
42/* In case some macros used by files we include need it, define this here. */
43int target_flags;
44
45int insn_elision = 1;
46
47static struct obstack obstack;
48struct obstack *rtl_obstack = &obstack;
49
50/* Counter for named patterns and INSN_CODEs. */
51static int insn_sequence_num;
52
53/* Counter for define_splits. */
54static int split_sequence_num;
55
56/* Counter for define_peephole2s. */
57static int peephole2_sequence_num;
58
59static int predicable_default;
60static const char *predicable_true;
61static const char *predicable_false;
62
63static const char *subst_true = "yes";
64static const char *subst_false = "no";
65
66static htab_t condition_table;
67
68/* We initially queue all patterns, process the define_insn,
69 define_cond_exec and define_subst patterns, then return
70 them one at a time. */
71
72class queue_elem
73{
74public:
75 rtx data;
76 file_location loc;
77 class queue_elem *next;
78 /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or
79 DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT. */
80 class queue_elem *split;
81};
82
83#define MNEMONIC_ATTR_NAME "mnemonic"
84#define MNEMONIC_HTAB_SIZE 1024
85
86static class queue_elem *define_attr_queue;
87static class queue_elem **define_attr_tail = &define_attr_queue;
88static class queue_elem *define_pred_queue;
89static class queue_elem **define_pred_tail = &define_pred_queue;
90static class queue_elem *define_insn_queue;
91static class queue_elem **define_insn_tail = &define_insn_queue;
92static class queue_elem *define_cond_exec_queue;
93static class queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
94static class queue_elem *define_subst_queue;
95static class queue_elem **define_subst_tail = &define_subst_queue;
96static class queue_elem *other_queue;
97static class queue_elem **other_tail = &other_queue;
98static class queue_elem *define_subst_attr_queue;
99static class queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
100
101/* Mapping from DEFINE_* rtxes to their location in the source file. */
102static hash_map <rtx, file_location> *rtx_locs;
103
104static void remove_constraints (rtx);
105
106static int is_predicable (class queue_elem *);
107static void identify_predicable_attribute (void);
108static int n_alternatives (const char *);
109static void collect_insn_data (rtx, int *, int *);
110static const char *alter_test_for_insn (class queue_elem *,
111 class queue_elem *);
112static char *shift_output_template (char *, const char *, int);
113static const char *alter_output_for_insn (class queue_elem *,
114 class queue_elem *,
115 int, int);
116static void process_one_cond_exec (class queue_elem *);
117static void process_define_cond_exec (void);
118static void init_predicate_table (void);
119static void record_insn_name (int, const char *);
120
121static bool has_subst_attribute (class queue_elem *, class queue_elem *);
122static const char * alter_output_for_subst_insn (rtx, int);
123static void alter_attrs_for_subst_insn (class queue_elem *, int);
124static void process_substs_on_one_elem (class queue_elem *,
125 class queue_elem *);
126static rtx subst_dup (rtx, int, int);
127static void process_define_subst (void);
128
129static const char * duplicate_alternatives (const char *, int);
130static const char * duplicate_each_alternative (const char * str, int n_dup);
131
132typedef const char * (*constraints_handler_t) (const char *, int);
133static rtx alter_constraints (rtx, int, constraints_handler_t);
134static rtx adjust_operands_numbers (rtx);
135static rtx replace_duplicating_operands_in_pattern (rtx);
136
137/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
138 the gensupport programs. */
139
140rtx
141gen_rtx_CONST_INT (machine_mode ARG_UNUSED (mode),
142 HOST_WIDE_INT arg)
143{
144 rtx rt = rtx_alloc (CONST_INT);
145
146 XWINT (rt, 0) = arg;
147 return rt;
148}
149
150/* Return the rtx pattern specified by the list of rtxes in a
151 define_insn or define_split. */
152
153rtx
154add_implicit_parallel (rtvec vec)
155{
156 if (GET_NUM_ELEM (vec) == 1)
157 return RTVEC_ELT (vec, 0);
158 else
159 {
160 rtx pattern = rtx_alloc (PARALLEL);
161 XVEC (pattern, 0) = vec;
162 return pattern;
163 }
164}
165
166/* Predicate handling.
167
168 We construct from the machine description a table mapping each
169 predicate to a list of the rtl codes it can possibly match. The
170 function 'maybe_both_true' uses it to deduce that there are no
171 expressions that can be matches by certain pairs of tree nodes.
172 Also, if a predicate can match only one code, we can hardwire that
173 code into the node testing the predicate.
174
175 Some predicates are flagged as special. validate_pattern will not
176 warn about modeless match_operand expressions if they have a
177 special predicate. Predicates that allow only constants are also
178 treated as special, for this purpose.
179
180 validate_pattern will warn about predicates that allow non-lvalues
181 when they appear in destination operands.
182
183 Calculating the set of rtx codes that can possibly be accepted by a
184 predicate expression EXP requires a three-state logic: any given
185 subexpression may definitively accept a code C (Y), definitively
186 reject a code C (N), or may have an indeterminate effect (I). N
187 and I is N; Y or I is Y; Y and I, N or I are both I. Here are full
188 truth tables.
189
190 a b a&b a|b
191 Y Y Y Y
192 N Y N Y
193 N N N N
194 I Y I Y
195 I N N I
196 I I I I
197
198 We represent Y with 1, N with 0, I with 2. If any code is left in
199 an I state by the complete expression, we must assume that that
200 code can be accepted. */
201
202#define N 0
203#define Y 1
204#define I 2
205
206#define TRISTATE_AND(a,b) \
207 ((a) == I ? ((b) == N ? N : I) : \
208 (b) == I ? ((a) == N ? N : I) : \
209 (a) && (b))
210
211#define TRISTATE_OR(a,b) \
212 ((a) == I ? ((b) == Y ? Y : I) : \
213 (b) == I ? ((a) == Y ? Y : I) : \
214 (a) || (b))
215
216#define TRISTATE_NOT(a) \
217 ((a) == I ? I : !(a))
218
219/* 0 means no warning about that code yet, 1 means warned. */
220static char did_you_mean_codes[NUM_RTX_CODE];
221
222/* Recursively calculate the set of rtx codes accepted by the
223 predicate expression EXP, writing the result to CODES. LOC is
224 the .md file location of the directive containing EXP. */
225
226void
227compute_test_codes (rtx exp, file_location loc, char *codes)
228{
229 char op0_codes[NUM_RTX_CODE];
230 char op1_codes[NUM_RTX_CODE];
231 char op2_codes[NUM_RTX_CODE];
232 int i;
233
234 switch (GET_CODE (exp))
235 {
236 case AND:
237 compute_test_codes (XEXP (exp, 0), loc, codes: op0_codes);
238 compute_test_codes (XEXP (exp, 1), loc, codes: op1_codes);
239 for (i = 0; i < NUM_RTX_CODE; i++)
240 codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
241 break;
242
243 case IOR:
244 compute_test_codes (XEXP (exp, 0), loc, codes: op0_codes);
245 compute_test_codes (XEXP (exp, 1), loc, codes: op1_codes);
246 for (i = 0; i < NUM_RTX_CODE; i++)
247 codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
248 break;
249 case NOT:
250 compute_test_codes (XEXP (exp, 0), loc, codes: op0_codes);
251 for (i = 0; i < NUM_RTX_CODE; i++)
252 codes[i] = TRISTATE_NOT (op0_codes[i]);
253 break;
254
255 case IF_THEN_ELSE:
256 /* a ? b : c accepts the same codes as (a & b) | (!a & c). */
257 compute_test_codes (XEXP (exp, 0), loc, codes: op0_codes);
258 compute_test_codes (XEXP (exp, 1), loc, codes: op1_codes);
259 compute_test_codes (XEXP (exp, 2), loc, codes: op2_codes);
260 for (i = 0; i < NUM_RTX_CODE; i++)
261 codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
262 TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
263 op2_codes[i]));
264 break;
265
266 case MATCH_CODE:
267 /* MATCH_CODE allows a specified list of codes. However, if it
268 does not apply to the top level of the expression, it does not
269 constrain the set of codes for the top level. */
270 if (XSTR (exp, 1)[0] != '\0')
271 {
272 memset (s: codes, Y, NUM_RTX_CODE);
273 break;
274 }
275
276 memset (s: codes, N, NUM_RTX_CODE);
277 {
278 const char *next_code = XSTR (exp, 0);
279 const char *code;
280
281 if (*next_code == '\0')
282 {
283 error_at (loc, "empty match_code expression");
284 break;
285 }
286
287 while ((code = scan_comma_elt (&next_code)) != 0)
288 {
289 size_t n = next_code - code;
290 int found_it = 0;
291
292 for (i = 0; i < NUM_RTX_CODE; i++)
293 if (!strncmp (s1: code, GET_RTX_NAME (i), n: n)
294 && GET_RTX_NAME (i)[n] == '\0')
295 {
296 codes[i] = Y;
297 found_it = 1;
298 break;
299 }
300 if (!found_it)
301 {
302 error_at (loc, "match_code \"%.*s\" matches nothing",
303 (int) n, code);
304 for (i = 0; i < NUM_RTX_CODE; i++)
305 if (!strncasecmp (s1: code, GET_RTX_NAME (i), n: n)
306 && GET_RTX_NAME (i)[n] == '\0'
307 && !did_you_mean_codes[i])
308 {
309 did_you_mean_codes[i] = 1;
310 message_at (loc, "(did you mean \"%s\"?)",
311 GET_RTX_NAME (i));
312 }
313 }
314 }
315 }
316 break;
317
318 case MATCH_OPERAND:
319 /* MATCH_OPERAND disallows the set of codes that the named predicate
320 disallows, and is indeterminate for the codes that it does allow. */
321 {
322 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
323 if (!p)
324 {
325 error_at (loc, "reference to unknown predicate '%s'",
326 XSTR (exp, 1));
327 break;
328 }
329 for (i = 0; i < NUM_RTX_CODE; i++)
330 codes[i] = p->codes[i] ? I : N;
331 }
332 break;
333
334
335 case MATCH_TEST:
336 /* (match_test WHATEVER) is completely indeterminate. */
337 memset (s: codes, I, NUM_RTX_CODE);
338 break;
339
340 default:
341 error_at (loc, "'%s' cannot be used in predicates or constraints",
342 GET_RTX_NAME (GET_CODE (exp)));
343 memset (s: codes, I, NUM_RTX_CODE);
344 break;
345 }
346}
347
348#undef TRISTATE_OR
349#undef TRISTATE_AND
350#undef TRISTATE_NOT
351
352/* Return true if NAME is a valid predicate name. */
353
354static bool
355valid_predicate_name_p (const char *name)
356{
357 const char *p;
358
359 if (!ISALPHA (name[0]) && name[0] != '_')
360 return false;
361 for (p = name + 1; *p; p++)
362 if (!ISALNUM (*p) && *p != '_')
363 return false;
364 return true;
365}
366
367/* Process define_predicate directive DESC, which appears at location LOC.
368 Compute the set of codes that can be matched, and record this as a known
369 predicate. */
370
371static void
372process_define_predicate (rtx desc, file_location loc)
373{
374 struct pred_data *pred;
375 char codes[NUM_RTX_CODE];
376 int i;
377
378 if (!valid_predicate_name_p (XSTR (desc, 0)))
379 {
380 error_at (loc, "%s: predicate name must be a valid C function name",
381 XSTR (desc, 0));
382 return;
383 }
384
385 pred = XCNEW (struct pred_data);
386 pred->name = XSTR (desc, 0);
387 pred->exp = XEXP (desc, 1);
388 pred->c_block = XSTR (desc, 2);
389 if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
390 pred->special = true;
391
392 compute_test_codes (XEXP (desc, 1), loc, codes);
393
394 for (i = 0; i < NUM_RTX_CODE; i++)
395 if (codes[i] != N)
396 add_predicate_code (pred, (enum rtx_code) i);
397
398 add_predicate (pred);
399}
400#undef I
401#undef N
402#undef Y
403
404/* Queue PATTERN on LIST_TAIL. Return the address of the new queue
405 element. */
406
407static class queue_elem *
408queue_pattern (rtx pattern, class queue_elem ***list_tail,
409 file_location loc)
410{
411 class queue_elem *e = XNEW (class queue_elem);
412 e->data = pattern;
413 e->loc = loc;
414 e->next = NULL;
415 e->split = NULL;
416 **list_tail = e;
417 *list_tail = &e->next;
418 return e;
419}
420
421/* Remove element ELEM from QUEUE. */
422static void
423remove_from_queue (class queue_elem *elem, class queue_elem **queue)
424{
425 class queue_elem *prev, *e;
426 prev = NULL;
427 for (e = *queue; e ; e = e->next)
428 {
429 if (e == elem)
430 break;
431 prev = e;
432 }
433 if (e == NULL)
434 return;
435
436 if (prev)
437 prev->next = elem->next;
438 else
439 *queue = elem->next;
440}
441
442/* Build a define_attr for an binary attribute with name NAME and
443 possible values "yes" and "no", and queue it. */
444static void
445add_define_attr (const char *name)
446{
447 class queue_elem *e = XNEW (class queue_elem);
448 rtx t1 = rtx_alloc (DEFINE_ATTR);
449 XSTR (t1, 0) = name;
450 XSTR (t1, 1) = "no,yes";
451 XEXP (t1, 2) = rtx_alloc (CONST_STRING);
452 XSTR (XEXP (t1, 2), 0) = "yes";
453 e->data = t1;
454 e->loc = file_location ("built-in", -1, -1);
455 e->next = define_attr_queue;
456 define_attr_queue = e;
457
458}
459
460/* Recursively remove constraints from an rtx. */
461
462static void
463remove_constraints (rtx part)
464{
465 int i, j;
466 const char *format_ptr;
467
468 if (part == 0)
469 return;
470
471 if (GET_CODE (part) == MATCH_OPERAND)
472 XSTR (part, 2) = "";
473 else if (GET_CODE (part) == MATCH_SCRATCH)
474 XSTR (part, 1) = "";
475
476 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
477
478 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
479 switch (*format_ptr++)
480 {
481 case 'e':
482 case 'u':
483 remove_constraints (XEXP (part, i));
484 break;
485 case 'E':
486 if (XVEC (part, i) != NULL)
487 for (j = 0; j < XVECLEN (part, i); j++)
488 remove_constraints (XVECEXP (part, i, j));
489 break;
490 }
491}
492
493/* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs
494 with MATCH_OP_DUPs in X. */
495
496static rtx
497replace_operands_with_dups (rtx x)
498{
499 if (x == 0)
500 return x;
501
502 rtx newx;
503 if (GET_CODE (x) == MATCH_OPERAND)
504 {
505 newx = rtx_alloc (MATCH_DUP);
506 XINT (newx, 0) = XINT (x, 0);
507 x = newx;
508 }
509 else if (GET_CODE (x) == MATCH_OPERATOR)
510 {
511 newx = rtx_alloc (MATCH_OP_DUP);
512 XINT (newx, 0) = XINT (x, 0);
513 XVEC (newx, 1) = XVEC (x, 2);
514 x = newx;
515 }
516 else
517 newx = shallow_copy_rtx (x);
518
519 const char *format_ptr = GET_RTX_FORMAT (GET_CODE (x));
520 for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
521 switch (*format_ptr++)
522 {
523 case 'e':
524 case 'u':
525 XEXP (newx, i) = replace_operands_with_dups (XEXP (x, i));
526 break;
527 case 'E':
528 if (XVEC (x, i) != NULL)
529 {
530 XVEC (newx, i) = rtvec_alloc (XVECLEN (x, i));
531 for (int j = 0; j < XVECLEN (x, i); j++)
532 XVECEXP (newx, i, j)
533 = replace_operands_with_dups (XVECEXP (x, i, j));
534 }
535 break;
536 }
537 return newx;
538}
539
540/* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into
541 a sequence that should be generated by the splitter. */
542
543static rtvec
544gen_rewrite_sequence (rtvec vec)
545{
546 rtvec new_vec = rtvec_alloc (1);
547 rtx x = add_implicit_parallel (vec);
548 RTVEC_ELT (new_vec, 0) = replace_operands_with_dups (x);
549 return new_vec;
550}
551
552/* The following is for handling the compact syntax for constraints and
553 attributes.
554
555 The normal syntax looks like this:
556
557 ...
558 (match_operand: 0 "s_register_operand" "r,I,k")
559 (match_operand: 2 "s_register_operand" "r,k,I")
560 ...
561 "@
562 <asm>
563 <asm>
564 <asm>"
565 ...
566 (set_attr "length" "4,8,8")
567
568 The compact syntax looks like this:
569
570 ...
571 (match_operand: 0 "s_register_operand")
572 (match_operand: 2 "s_register_operand")
573 ...
574 {@ [cons: 0, 2; attrs: length]
575 [r,r; 4] <asm>
576 [I,k; 8] <asm>
577 [k,I; 8] <asm>
578 }
579 ...
580 [<other attributes>]
581
582 This is the only place where this syntax needs to be handled. Relevant
583 patterns are transformed from compact to the normal syntax before they are
584 queued, so none of the gen* programs need to know about this syntax at all.
585
586 Conversion process (convert_syntax):
587
588 0) Check that pattern actually uses new syntax (check for {@ ... }).
589
590 1) Get the "layout", i.e. the "[cons: 0 2; attrs: length]" from the above
591 example. cons must come first; both are optional. Set up two vecs,
592 convec and attrvec, for holding the results of the transformation.
593
594 2) For each alternative: parse the list of constraints and/or attributes,
595 and enqueue them in the relevant lists in convec and attrvec. By the end
596 of this process, convec[N].con and attrvec[N].con should contain regular
597 syntax constraint/attribute lists like "r,I,k". Copy the asm to a string
598 as we go.
599
600 3) Search the rtx and write the constraint and attribute lists into the
601 correct places. Write the asm back into the template. */
602
603/* Helper class for shuffling constraints/attributes in convert_syntax and
604 add_constraints/add_attributes. This includes commas but not whitespace. */
605
606class conlist {
607private:
608 std::string con;
609
610public:
611 std::string name;
612 int idx = -1;
613
614 conlist () = default;
615
616 /* [ns..ns + len) should be a string with the id of the rtx to match
617 i.e. if rtx is the relevant match_operand or match_scratch then
618 [ns..ns + len) should equal itoa (XINT (rtx, 0)), and if set_attr then
619 [ns..ns + len) should equal XSTR (rtx, 0). */
620 conlist (const char *ns, unsigned int len, bool numeric)
621 {
622 /* Trim leading whitespaces. */
623 while (len > 0 && ISBLANK (*ns))
624 {
625 ns++;
626 len--;
627 }
628
629 /* Trim trailing whitespace. */
630 for (int i = len - 1; i >= 0; i--, len--)
631 if (!ISBLANK (ns[i]))
632 break;
633
634 /* Parse off any modifiers. */
635 while (len > 0 && !ISALNUM (*ns))
636 {
637 con += *(ns++);
638 len--;
639 }
640
641 name.assign (s: ns, n: len);
642 if (numeric)
643 idx = strtol (nptr: name.c_str (), endptr: (char **)NULL, base: 10);
644 }
645
646 /* Adds a character to the end of the string. */
647 void add (char c)
648 {
649 con += c;
650 }
651
652 /* Output the string in the form of a brand-new char *, then effectively
653 clear the internal string by resetting len to 0. */
654 char *out ()
655 {
656 /* Final character is always a trailing comma, so strip it out. */
657 char *q = xstrndup (con.c_str (), con.size () - 1);
658 con.clear ();
659 return q;
660 }
661};
662
663typedef std::vector<conlist> vec_conlist;
664
665/* Add constraints to an rtx. This function is similar to remove_constraints.
666 Errors if adding the constraints would overwrite existing constraints. */
667
668static void
669add_constraints (rtx part, file_location loc, vec_conlist &cons)
670{
671 const char *format_ptr;
672
673 if (part == NULL_RTX)
674 return;
675
676 /* If match_op or match_scr, check if we have the right one, and if so, copy
677 over the constraint list. */
678 if (GET_CODE (part) == MATCH_OPERAND || GET_CODE (part) == MATCH_SCRATCH)
679 {
680 int field = GET_CODE (part) == MATCH_OPERAND ? 2 : 1;
681 unsigned id = XINT (part, 0);
682
683 if (id >= cons.size () || cons[id].idx == -1)
684 return;
685
686 if (XSTR (part, field)[0] != '\0')
687 {
688 error_at (loc, "can't mix normal and compact constraint syntax");
689 return;
690 }
691 XSTR (part, field) = cons[id].out ();
692 cons[id].idx = -1;
693 }
694
695 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
696
697 /* Recursively search the rtx. */
698 for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
699 switch (*format_ptr++)
700 {
701 case 'e':
702 case 'u':
703 add_constraints (XEXP (part, i), loc, cons);
704 break;
705 case 'E':
706 if (XVEC (part, i) != NULL)
707 for (int j = 0; j < XVECLEN (part, i); j++)
708 add_constraints (XVECEXP (part, i, j), loc, cons);
709 break;
710 default:
711 continue;
712 }
713}
714
715/* Add ATTRS to definition X's attribute list. */
716
717static void
718add_attributes (rtx x, vec_conlist &attrs)
719{
720 unsigned int attr_index = GET_CODE (x) == DEFINE_INSN ? 4 : 3;
721 rtvec orig = XVEC (x, attr_index);
722 if (orig)
723 {
724 size_t n_curr = XVECLEN (x, attr_index);
725 rtvec copy = rtvec_alloc (n_curr + attrs.size ());
726
727 /* Create a shallow copy of existing entries. */
728 memcpy (dest: &copy->elem[attrs.size ()], src: &orig->elem[0],
729 n: sizeof (rtx) * n_curr);
730 XVEC (x, attr_index) = copy;
731 }
732 else
733 XVEC (x, attr_index) = rtvec_alloc (attrs.size ());
734
735 /* Create the new elements. */
736 for (unsigned i = 0; i < attrs.size (); i++)
737 {
738 rtx attr = rtx_alloc (SET_ATTR);
739 XSTR (attr, 0) = xstrdup (attrs[i].name.c_str ());
740 XSTR (attr, 1) = attrs[i].out ();
741 XVECEXP (x, attr_index, i) = attr;
742 }
743}
744
745/* Consumes spaces and tabs. */
746
747static inline void
748skip_spaces (const char **str)
749{
750 while (ISBLANK (**str))
751 (*str)++;
752}
753
754/* Consumes the given character, if it's there. */
755
756static inline bool
757expect_char (const char **str, char c)
758{
759 if (**str != c)
760 return false;
761 (*str)++;
762 return true;
763}
764
765/* Parses the section layout that follows a "{@" if using new syntax. Builds
766 a vector for a single section. E.g. if we have "attrs: length, arch]..."
767 then list will have two elements, the first for "length" and the second
768 for "arch". */
769
770static void
771parse_section_layout (file_location loc, const char **templ, const char *label,
772 vec_conlist &list, bool numeric)
773{
774 const char *name_start;
775 size_t label_len = strlen (s: label);
776 if (strncmp (s1: label, s2: *templ, n: label_len) == 0)
777 {
778 *templ += label_len;
779
780 /* Gather the names. */
781 while (**templ != ';' && **templ != ']')
782 {
783 skip_spaces (str: templ);
784 name_start = *templ;
785 int len = 0;
786 char val = (*templ)[len];
787 while (val != ',' && val != ';' && val != ']')
788 {
789 if (val == 0 || val == '\n')
790 fatal_at (loc, "missing ']'");
791 val = (*templ)[++len];
792 }
793 *templ += len;
794 if (val == ',')
795 (*templ)++;
796 list.push_back (x: conlist (name_start, len, numeric));
797 }
798 }
799}
800
801/* Parse a section, a section is defined as a named space separated list, e.g.
802
803 foo: a, b, c
804
805 is a section named "foo" with entries a, b and c. */
806
807static void
808parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no,
809 vec_conlist &list, file_location loc, const char *name)
810{
811 unsigned int i;
812
813 /* Go through the list, one character at a time, adding said character
814 to the correct string. */
815 for (i = 0; **templ != ']' && **templ != ';'; (*templ)++)
816 if (!ISBLANK (**templ))
817 {
818 if (**templ == 0 || **templ == '\n')
819 fatal_at (loc, "missing ']'");
820 list[i].add (c: **templ);
821 if (**templ == ',')
822 {
823 ++i;
824 if (i == n_elems)
825 fatal_at (loc, "too many %ss in alternative %d: expected %d",
826 name, alt_no, n_elems);
827 }
828 }
829
830 if (i + 1 < n_elems)
831 fatal_at (loc, "too few %ss in alternative %d: expected %d, got %d",
832 name, alt_no, n_elems, i);
833
834 list[i].add (c: ',');
835}
836
837/* The compact syntax has more convience syntaxes. As such we post process
838 the lines to get them back to something the normal syntax understands. */
839
840static void
841preprocess_compact_syntax (file_location loc, int alt_no, std::string &line,
842 std::string &last_line)
843{
844 /* Check if we're copying the last statement. */
845 if (line.find (s: "^") == 0 && line.size () == 1)
846 {
847 if (last_line.empty ())
848 fatal_at (loc, "found instruction to copy previous line (^) in"
849 "alternative %d but no previous line to copy", alt_no);
850 line = last_line;
851 return;
852 }
853
854 std::string result;
855 std::string buffer;
856 /* Check if we have << which means return c statement. */
857 if (line.find (s: "<<") == 0)
858 {
859 result.append (s: "* return ");
860 const char *chunk = line.c_str () + 2;
861 skip_spaces (str: &chunk);
862 result.append (s: chunk);
863 }
864 else
865 result.append (str: line);
866
867 line = result;
868 return;
869}
870
871/* Converts an rtx from compact syntax to normal syntax if possible. */
872
873static void
874convert_syntax (rtx x, file_location loc)
875{
876 int alt_no;
877 unsigned int templ_index;
878 const char *templ;
879 vec_conlist tconvec, convec, attrvec;
880
881 templ_index = 3;
882 gcc_assert (GET_CODE (x) == DEFINE_INSN);
883
884 templ = XTMPL (x, templ_index);
885
886 /* Templates with constraints start with "{@". */
887 if (strncmp (s1: "*{@", s2: templ, n: 3))
888 return;
889
890 /* Get the layout for the template. */
891 templ += 3;
892 skip_spaces (str: &templ);
893
894 if (!expect_char (str: &templ, c: '['))
895 fatal_at (loc, "expecing `[' to begin section list");
896
897 skip_spaces (str: &templ);
898
899 parse_section_layout (loc, templ: &templ, label: "cons:", list&: tconvec, numeric: true);
900
901 if (*templ != ']')
902 {
903 if (*templ == ';')
904 skip_spaces (str: &(++templ));
905 parse_section_layout (loc, templ: &templ, label: "attrs:", list&: attrvec, numeric: false);
906 }
907
908 if (!expect_char (str: &templ, c: ']'))
909 fatal_at (loc, "expecting `]` to end section list - section list must have "
910 "cons first, attrs second");
911
912 /* We will write the un-constrainified template into new_templ. */
913 std::string new_templ;
914 new_templ.append (s: "@");
915
916 /* Skip to the first proper line. */
917 skip_spaces (str: &templ);
918 if (*templ == 0)
919 fatal_at (loc, "'{@...}' blocks must have at least one alternative");
920 if (*templ != '\n')
921 fatal_at (loc, "unexpected character '%c' after ']'", *templ);
922 templ++;
923
924 alt_no = 0;
925 std::string last_line;
926
927 /* Process the alternatives. */
928 while (*(templ - 1) != '\0')
929 {
930 /* Skip leading whitespace. */
931 std::string buffer;
932 skip_spaces (str: &templ);
933
934 /* Check if we're at the end. */
935 if (templ[0] == '}' && templ[1] == '\0')
936 break;
937
938 if (expect_char (str: &templ, c: '['))
939 {
940 new_templ += '\n';
941 new_templ.append (str: buffer);
942 /* Parse the constraint list, then the attribute list. */
943 if (tconvec.size () > 0)
944 parse_section (templ: &templ, n_elems: tconvec.size (), alt_no, list&: tconvec, loc,
945 name: "constraint");
946
947 if (attrvec.size () > 0)
948 {
949 if (tconvec.size () > 0 && !expect_char (str: &templ, c: ';'))
950 fatal_at (loc, "expected `;' to separate constraints "
951 "and attributes in alternative %d", alt_no);
952
953 parse_section (templ: &templ, n_elems: attrvec.size (), alt_no,
954 list&: attrvec, loc, name: "attribute");
955 }
956
957 if (!expect_char (str: &templ, c: ']'))
958 fatal_at (loc, "expected end of constraint/attribute list but "
959 "missing an ending `]' in alternative %d", alt_no);
960 }
961 else if (templ[0] == '/' && templ[1] == '/')
962 {
963 templ += 2;
964 /* Glob till newline or end of string. */
965 while (*templ != '\n' || *templ != '\0')
966 templ++;
967
968 /* Skip any newlines or whitespaces needed. */
969 while (ISSPACE(*templ))
970 templ++;
971 continue;
972 }
973 else if (templ[0] == '/' && templ[1] == '*')
974 {
975 templ += 2;
976 /* Glob till newline or end of multiline comment. */
977 while (templ[0] != 0 && templ[0] != '*' && templ[1] != '/')
978 templ++;
979
980 while (templ[0] != '*' || templ[1] != '/')
981 {
982 if (templ[0] == 0)
983 fatal_at (loc, "unterminated '/*'");
984 templ++;
985 }
986 templ += 2;
987
988 /* Skip any newlines or whitespaces needed. */
989 while (ISSPACE(*templ))
990 templ++;
991 continue;
992 }
993 else
994 fatal_at (loc, "expected constraint/attribute list at beginning of "
995 "alternative %d but missing a starting `['", alt_no);
996
997 /* Skip whitespace between list and asm. */
998 skip_spaces (str: &templ);
999
1000 /* Copy asm to new template. */
1001 std::string line;
1002 while (*templ != '\n' && *templ != '\0')
1003 line += *templ++;
1004
1005 /* Apply any pre-processing needed to the line. */
1006 preprocess_compact_syntax (loc, alt_no, line, last_line);
1007 new_templ.append (str: line);
1008 last_line = line;
1009
1010 /* Normal "*..." syntax expects the closing quote to be on the final
1011 line of asm, whereas we allow the closing "}" to be on its own line.
1012 Postpone copying the '\n' until we know that there is another
1013 alternative in the list. */
1014 while (ISSPACE (*templ))
1015 templ++;
1016 ++alt_no;
1017 }
1018
1019 /* Check for any duplicate cons entries and sort based on i. */
1020 for (auto e : tconvec)
1021 {
1022 unsigned idx = e.idx;
1023 if (idx >= convec.size ())
1024 convec.resize (new_size: idx + 1);
1025
1026 if (convec[idx].idx >= 0)
1027 fatal_at (loc, "duplicate cons number found: %d", idx);
1028 convec[idx] = e;
1029 }
1030 tconvec.clear ();
1031
1032 /* Write the constraints and attributes into their proper places. */
1033 if (convec.size () > 0)
1034 add_constraints (part: x, loc, cons&: convec);
1035
1036 if (attrvec.size () > 0)
1037 add_attributes (x, attrs&: attrvec);
1038
1039 /* Copy over the new un-constrainified template. */
1040 XTMPL (x, templ_index) = xstrdup (new_templ.c_str ());
1041
1042 /* Register for later checks during iterator expansions. */
1043 compact_syntax.add (k: x);
1044}
1045
1046/* Process a top level rtx in some way, queuing as appropriate. */
1047
1048static void
1049process_rtx (rtx desc, file_location loc)
1050{
1051 switch (GET_CODE (desc))
1052 {
1053 case DEFINE_INSN:
1054 convert_syntax (x: desc, loc);
1055 queue_pattern (pattern: desc, list_tail: &define_insn_tail, loc);
1056 break;
1057
1058 case DEFINE_COND_EXEC:
1059 queue_pattern (pattern: desc, list_tail: &define_cond_exec_tail, loc);
1060 break;
1061
1062 case DEFINE_SUBST:
1063 queue_pattern (pattern: desc, list_tail: &define_subst_tail, loc);
1064 break;
1065
1066 case DEFINE_SUBST_ATTR:
1067 queue_pattern (pattern: desc, list_tail: &define_subst_attr_tail, loc);
1068 break;
1069
1070 case DEFINE_ATTR:
1071 case DEFINE_ENUM_ATTR:
1072 queue_pattern (pattern: desc, list_tail: &define_attr_tail, loc);
1073 break;
1074
1075 case DEFINE_PREDICATE:
1076 case DEFINE_SPECIAL_PREDICATE:
1077 process_define_predicate (desc, loc);
1078 /* Fall through. */
1079
1080 case DEFINE_CONSTRAINT:
1081 case DEFINE_REGISTER_CONSTRAINT:
1082 case DEFINE_MEMORY_CONSTRAINT:
1083 case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
1084 case DEFINE_RELAXED_MEMORY_CONSTRAINT:
1085 case DEFINE_ADDRESS_CONSTRAINT:
1086 queue_pattern (pattern: desc, list_tail: &define_pred_tail, loc);
1087 break;
1088
1089 case DEFINE_INSN_AND_SPLIT:
1090 case DEFINE_INSN_AND_REWRITE:
1091 {
1092 const char *split_cond;
1093 rtx split;
1094 rtvec attr;
1095 int i;
1096 class queue_elem *insn_elem;
1097 class queue_elem *split_elem;
1098 int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6);
1099
1100 /* Create a split with values from the insn_and_split. */
1101 split = rtx_alloc (DEFINE_SPLIT);
1102
1103 i = XVECLEN (desc, 1);
1104 XVEC (split, 0) = rtvec_alloc (i);
1105 while (--i >= 0)
1106 {
1107 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
1108 remove_constraints (XVECEXP (split, 0, i));
1109 }
1110
1111 /* If the split condition starts with "&&", append it to the
1112 insn condition to create the new split condition. */
1113 split_cond = XSTR (desc, 4);
1114 if (split_cond[0] == '&' && split_cond[1] == '&')
1115 {
1116 rtx_reader_ptr->copy_md_ptr_loc (new_ptr: split_cond + 2, old_ptr: split_cond);
1117 split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
1118 cond2: split_cond + 2);
1119 }
1120 else if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
1121 error_at (loc, "the rewrite condition must start with `&&'");
1122 XSTR (split, 1) = split_cond;
1123 if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
1124 XVEC (split, 2) = gen_rewrite_sequence (XVEC (desc, 1));
1125 else
1126 XVEC (split, 2) = XVEC (desc, 5);
1127 XSTR (split, 3) = XSTR (desc, split_code);
1128
1129 /* Fix up the DEFINE_INSN. */
1130 attr = XVEC (desc, split_code + 1);
1131 PUT_CODE (desc, DEFINE_INSN);
1132 XVEC (desc, 4) = attr;
1133 convert_syntax (x: desc, loc);
1134
1135 /* Queue them. */
1136 insn_elem = queue_pattern (pattern: desc, list_tail: &define_insn_tail, loc);
1137 split_elem = queue_pattern (pattern: split, list_tail: &other_tail, loc);
1138 insn_elem->split = split_elem;
1139 break;
1140 }
1141
1142 default:
1143 queue_pattern (pattern: desc, list_tail: &other_tail, loc);
1144 break;
1145 }
1146}
1147
1148/* Return true if attribute PREDICABLE is true for ELEM, which holds
1149 a DEFINE_INSN. */
1150
1151static int
1152is_predicable (class queue_elem *elem)
1153{
1154 rtvec vec = XVEC (elem->data, 4);
1155 const char *value;
1156 int i;
1157
1158 if (! vec)
1159 return predicable_default;
1160
1161 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
1162 {
1163 rtx sub = RTVEC_ELT (vec, i);
1164 switch (GET_CODE (sub))
1165 {
1166 case SET_ATTR:
1167 if (strcmp (XSTR (sub, 0), s2: "predicable") == 0)
1168 {
1169 value = XSTR (sub, 1);
1170 goto found;
1171 }
1172 break;
1173
1174 case SET_ATTR_ALTERNATIVE:
1175 if (strcmp (XSTR (sub, 0), s2: "predicable") == 0)
1176 {
1177 error_at (elem->loc, "multiple alternatives for `predicable'");
1178 return 0;
1179 }
1180 break;
1181
1182 case SET:
1183 if (GET_CODE (SET_DEST (sub)) != ATTR
1184 || strcmp (XSTR (SET_DEST (sub), 0), s2: "predicable") != 0)
1185 break;
1186 sub = SET_SRC (sub);
1187 if (GET_CODE (sub) == CONST_STRING)
1188 {
1189 value = XSTR (sub, 0);
1190 goto found;
1191 }
1192
1193 /* ??? It would be possible to handle this if we really tried.
1194 It's not easy though, and I'm not going to bother until it
1195 really proves necessary. */
1196 error_at (elem->loc, "non-constant value for `predicable'");
1197 return 0;
1198
1199 default:
1200 gcc_unreachable ();
1201 }
1202 }
1203
1204 return predicable_default;
1205
1206 found:
1207 /* Find out which value we're looking at. Multiple alternatives means at
1208 least one is predicable. */
1209 if (strchr (s: value, c: ',') != NULL)
1210 return 1;
1211 if (strcmp (s1: value, s2: predicable_true) == 0)
1212 return 1;
1213 if (strcmp (s1: value, s2: predicable_false) == 0)
1214 return 0;
1215
1216 error_at (elem->loc, "unknown value `%s' for `predicable' attribute", value);
1217 return 0;
1218}
1219
1220/* Find attribute SUBST in ELEM and assign NEW_VALUE to it. */
1221static void
1222change_subst_attribute (class queue_elem *elem,
1223 class queue_elem *subst_elem,
1224 const char *new_value)
1225{
1226 rtvec attrs_vec = XVEC (elem->data, 4);
1227 const char *subst_name = XSTR (subst_elem->data, 0);
1228 int i;
1229
1230 if (! attrs_vec)
1231 return;
1232
1233 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
1234 {
1235 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
1236 if (GET_CODE (cur_attr) != SET_ATTR)
1237 continue;
1238 if (strcmp (XSTR (cur_attr, 0), s2: subst_name) == 0)
1239 {
1240 XSTR (cur_attr, 1) = new_value;
1241 return;
1242 }
1243 }
1244}
1245
1246/* Return true if ELEM has the attribute with the name of DEFINE_SUBST
1247 represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
1248 DEFINE_SUBST isn't applied to patterns without such attribute. In other
1249 words, we suppose the default value of the attribute to be 'no' since it is
1250 always generated automatically in read-rtl.cc. */
1251static bool
1252has_subst_attribute (class queue_elem *elem, class queue_elem *subst_elem)
1253{
1254 rtvec attrs_vec = XVEC (elem->data, 4);
1255 const char *value, *subst_name = XSTR (subst_elem->data, 0);
1256 int i;
1257
1258 if (! attrs_vec)
1259 return false;
1260
1261 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
1262 {
1263 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
1264 switch (GET_CODE (cur_attr))
1265 {
1266 case SET_ATTR:
1267 if (strcmp (XSTR (cur_attr, 0), s2: subst_name) == 0)
1268 {
1269 value = XSTR (cur_attr, 1);
1270 goto found;
1271 }
1272 break;
1273
1274 case SET:
1275 if (GET_CODE (SET_DEST (cur_attr)) != ATTR
1276 || strcmp (XSTR (SET_DEST (cur_attr), 0), s2: subst_name) != 0)
1277 break;
1278 cur_attr = SET_SRC (cur_attr);
1279 if (GET_CODE (cur_attr) == CONST_STRING)
1280 {
1281 value = XSTR (cur_attr, 0);
1282 goto found;
1283 }
1284
1285 /* Only (set_attr "subst" "yes/no") and
1286 (set (attr "subst" (const_string "yes/no")))
1287 are currently allowed. */
1288 error_at (elem->loc, "unsupported value for `%s'", subst_name);
1289 return false;
1290
1291 case SET_ATTR_ALTERNATIVE:
1292 if (strcmp (XSTR (cur_attr, 0), s2: subst_name) == 0)
1293 error_at (elem->loc,
1294 "%s: `set_attr_alternative' is unsupported by "
1295 "`define_subst'", XSTR (elem->data, 0));
1296 return false;
1297
1298
1299 default:
1300 gcc_unreachable ();
1301 }
1302 }
1303
1304 return false;
1305
1306 found:
1307 if (strcmp (s1: value, s2: subst_true) == 0)
1308 return true;
1309 if (strcmp (s1: value, s2: subst_false) == 0)
1310 return false;
1311
1312 error_at (elem->loc, "unknown value `%s' for `%s' attribute",
1313 value, subst_name);
1314 return false;
1315}
1316
1317/* Compare RTL-template of original define_insn X to input RTL-template of
1318 define_subst PT. Return 1 if the templates match, 0 otherwise.
1319 During the comparison, the routine also fills global_array OPERAND_DATA. */
1320static bool
1321subst_pattern_match (rtx x, rtx pt, file_location loc)
1322{
1323 RTX_CODE code, code_pt;
1324 int i, j, len;
1325 const char *fmt, *pred_name;
1326
1327 code = GET_CODE (x);
1328 code_pt = GET_CODE (pt);
1329
1330 if (code_pt == MATCH_OPERAND)
1331 {
1332 /* MATCH_DUP, and MATCH_OP_DUP don't have a specified mode, so we
1333 always accept them. */
1334 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt)
1335 && (code != MATCH_DUP && code != MATCH_OP_DUP))
1336 return false; /* Modes don't match. */
1337
1338 if (code == MATCH_OPERAND)
1339 {
1340 pred_name = XSTR (pt, 1);
1341 if (pred_name[0] != 0)
1342 {
1343 const struct pred_data *pred_pt = lookup_predicate (pred_name);
1344 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
1345 return false; /* Predicates don't match. */
1346 }
1347 }
1348
1349 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
1350 operand_data[XINT (pt, 0)] = x;
1351 return true;
1352 }
1353
1354 if (code_pt == MATCH_OPERATOR)
1355 {
1356 int x_vecexp_pos = -1;
1357
1358 /* Compare modes. */
1359 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt))
1360 return false;
1361
1362 /* In case X is also match_operator, compare predicates. */
1363 if (code == MATCH_OPERATOR)
1364 {
1365 pred_name = XSTR (pt, 1);
1366 if (pred_name[0] != 0)
1367 {
1368 const struct pred_data *pred_pt = lookup_predicate (pred_name);
1369 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
1370 return false;
1371 }
1372 }
1373
1374 /* Compare operands.
1375 MATCH_OPERATOR in input template could match in original template
1376 either 1) MATCH_OPERAND, 2) UNSPEC, 3) ordinary operation (like PLUS).
1377 In the first case operands are at (XVECEXP (x, 2, j)), in the second
1378 - at (XVECEXP (x, 0, j)), in the last one - (XEXP (x, j)).
1379 X_VECEXP_POS variable shows, where to look for these operands. */
1380 if (code == UNSPEC
1381 || code == UNSPEC_VOLATILE)
1382 x_vecexp_pos = 0;
1383 else if (code == MATCH_OPERATOR)
1384 x_vecexp_pos = 2;
1385 else
1386 x_vecexp_pos = -1;
1387
1388 /* MATCH_OPERATOR or UNSPEC case. */
1389 if (x_vecexp_pos >= 0)
1390 {
1391 /* Compare operands number in X and PT. */
1392 if (XVECLEN (x, x_vecexp_pos) != XVECLEN (pt, 2))
1393 return false;
1394 for (j = 0; j < XVECLEN (pt, 2); j++)
1395 if (!subst_pattern_match (XVECEXP (x, x_vecexp_pos, j),
1396 XVECEXP (pt, 2, j), loc))
1397 return false;
1398 }
1399
1400 /* Ordinary operator. */
1401 else
1402 {
1403 /* Compare operands number in X and PT.
1404 We count operands differently for X and PT since we compare
1405 an operator (with operands directly in RTX) and MATCH_OPERATOR
1406 (that has a vector with operands). */
1407 if (GET_RTX_LENGTH (code) != XVECLEN (pt, 2))
1408 return false;
1409 for (j = 0; j < XVECLEN (pt, 2); j++)
1410 if (!subst_pattern_match (XEXP (x, j), XVECEXP (pt, 2, j), loc))
1411 return false;
1412 }
1413
1414 /* Store the operand to OPERAND_DATA array. */
1415 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
1416 operand_data[XINT (pt, 0)] = x;
1417 return true;
1418 }
1419
1420 if (code_pt == MATCH_PAR_DUP
1421 || code_pt == MATCH_DUP
1422 || code_pt == MATCH_OP_DUP
1423 || code_pt == MATCH_SCRATCH
1424 || code_pt == MATCH_PARALLEL)
1425 {
1426 /* Currently interface for these constructions isn't defined -
1427 probably they aren't needed in input template of define_subst at all.
1428 So, for now their usage in define_subst is forbidden. */
1429 error_at (loc, "%s cannot be used in define_subst",
1430 GET_RTX_NAME (code_pt));
1431 }
1432
1433 gcc_assert (code != MATCH_PAR_DUP
1434 && code_pt != MATCH_DUP
1435 && code_pt != MATCH_OP_DUP
1436 && code_pt != MATCH_SCRATCH
1437 && code_pt != MATCH_PARALLEL
1438 && code_pt != MATCH_OPERAND
1439 && code_pt != MATCH_OPERATOR);
1440 /* If PT is none of the handled above, then we match only expressions with
1441 the same code in X. */
1442 if (code != code_pt)
1443 return false;
1444
1445 fmt = GET_RTX_FORMAT (code_pt);
1446 len = GET_RTX_LENGTH (code_pt);
1447
1448 for (i = 0; i < len; i++)
1449 {
1450 if (fmt[i] == '0')
1451 break;
1452
1453 switch (fmt[i])
1454 {
1455 case 'r': case 'p': case 'i': case 'w': case 's':
1456 continue;
1457
1458 case 'e': case 'u':
1459 if (!subst_pattern_match (XEXP (x, i), XEXP (pt, i), loc))
1460 return false;
1461 break;
1462 case 'E':
1463 {
1464 if (XVECLEN (x, i) != XVECLEN (pt, i))
1465 return false;
1466 for (j = 0; j < XVECLEN (pt, i); j++)
1467 if (!subst_pattern_match (XVECEXP (x, i, j),
1468 XVECEXP (pt, i, j), loc))
1469 return false;
1470 break;
1471 }
1472 default:
1473 gcc_unreachable ();
1474 }
1475 }
1476
1477 return true;
1478}
1479
1480/* Examine the attribute "predicable"; discover its boolean values
1481 and its default. */
1482
1483static void
1484identify_predicable_attribute (void)
1485{
1486 class queue_elem *elem;
1487 char *p_true, *p_false;
1488 const char *value;
1489
1490 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
1491 for (elem = define_attr_queue; elem ; elem = elem->next)
1492 if (strcmp (XSTR (elem->data, 0), s2: "predicable") == 0)
1493 goto found;
1494
1495 error_at (define_cond_exec_queue->loc,
1496 "attribute `predicable' not defined");
1497 return;
1498
1499 found:
1500 value = XSTR (elem->data, 1);
1501 p_false = xstrdup (value);
1502 p_true = strchr (s: p_false, c: ',');
1503 if (p_true == NULL || strchr (s: ++p_true, c: ',') != NULL)
1504 {
1505 error_at (elem->loc, "attribute `predicable' is not a boolean");
1506 free (ptr: p_false);
1507 return;
1508 }
1509 p_true[-1] = '\0';
1510
1511 predicable_true = p_true;
1512 predicable_false = p_false;
1513
1514 switch (GET_CODE (XEXP (elem->data, 2)))
1515 {
1516 case CONST_STRING:
1517 value = XSTR (XEXP (elem->data, 2), 0);
1518 break;
1519
1520 case CONST:
1521 error_at (elem->loc, "attribute `predicable' cannot be const");
1522 free (ptr: p_false);
1523 return;
1524
1525 default:
1526 error_at (elem->loc,
1527 "attribute `predicable' must have a constant default");
1528 free (ptr: p_false);
1529 return;
1530 }
1531
1532 if (strcmp (s1: value, s2: p_true) == 0)
1533 predicable_default = 1;
1534 else if (strcmp (s1: value, s2: p_false) == 0)
1535 predicable_default = 0;
1536 else
1537 {
1538 error_at (elem->loc, "unknown value `%s' for `predicable' attribute",
1539 value);
1540 free (ptr: p_false);
1541 }
1542}
1543
1544/* Return the number of alternatives in constraint S. */
1545
1546static int
1547n_alternatives (const char *s)
1548{
1549 int n = 1;
1550
1551 if (s)
1552 while (*s)
1553 n += (*s++ == ',');
1554
1555 return n;
1556}
1557
1558/* The routine scans rtl PATTERN, find match_operand in it and counts
1559 number of alternatives. If PATTERN contains several match_operands
1560 with different number of alternatives, error is emitted, and the
1561 routine returns 0. If all match_operands in PATTERN have the same
1562 number of alternatives, it's stored in N_ALT, and the routine returns 1.
1563 LOC is the location of PATTERN, for error reporting. */
1564static int
1565get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
1566{
1567 const char *fmt;
1568 enum rtx_code code;
1569 int i, j, len;
1570
1571 if (!n_alt)
1572 return 0;
1573
1574 code = GET_CODE (pattern);
1575 switch (code)
1576 {
1577 case MATCH_OPERAND:
1578 i = n_alternatives (XSTR (pattern, 2));
1579 /* n_alternatives returns 1 if constraint string is empty -
1580 here we fix it up. */
1581 if (!*(XSTR (pattern, 2)))
1582 i = 0;
1583 if (*n_alt <= 0)
1584 *n_alt = i;
1585
1586 else if (i && i != *n_alt)
1587 {
1588 error_at (loc, "wrong number of alternatives in operand %d",
1589 XINT (pattern, 0));
1590 return 0;
1591 }
1592
1593 default:
1594 break;
1595 }
1596
1597 fmt = GET_RTX_FORMAT (code);
1598 len = GET_RTX_LENGTH (code);
1599 for (i = 0; i < len; i++)
1600 {
1601 switch (fmt[i])
1602 {
1603 case 'e': case 'u':
1604 if (!get_alternatives_number (XEXP (pattern, i), n_alt, loc))
1605 return 0;
1606 break;
1607
1608 case 'V':
1609 if (XVEC (pattern, i) == NULL)
1610 break;
1611 /* FALLTHRU */
1612
1613 case 'E':
1614 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1615 if (!get_alternatives_number (XVECEXP (pattern, i, j), n_alt, loc))
1616 return 0;
1617 break;
1618
1619 case 'r': case 'p': case 'i': case 'w':
1620 case '0': case 's': case 'S': case 'T':
1621 break;
1622
1623 default:
1624 gcc_unreachable ();
1625 }
1626 }
1627 return 1;
1628}
1629
1630/* Determine how many alternatives there are in INSN, and how many
1631 operands. */
1632
1633static void
1634collect_insn_data (rtx pattern, int *palt, int *pmax)
1635{
1636 const char *fmt;
1637 enum rtx_code code;
1638 int i, j, len;
1639
1640 code = GET_CODE (pattern);
1641 switch (code)
1642 {
1643 case MATCH_OPERAND:
1644 case MATCH_SCRATCH:
1645 i = n_alternatives (XSTR (pattern, code == MATCH_SCRATCH ? 1 : 2));
1646 *palt = (i > *palt ? i : *palt);
1647 /* Fall through. */
1648
1649 case MATCH_OPERATOR:
1650 case MATCH_PARALLEL:
1651 i = XINT (pattern, 0);
1652 if (i > *pmax)
1653 *pmax = i;
1654 break;
1655
1656 default:
1657 break;
1658 }
1659
1660 fmt = GET_RTX_FORMAT (code);
1661 len = GET_RTX_LENGTH (code);
1662 for (i = 0; i < len; i++)
1663 {
1664 switch (fmt[i])
1665 {
1666 case 'e': case 'u':
1667 collect_insn_data (XEXP (pattern, i), palt, pmax);
1668 break;
1669
1670 case 'V':
1671 if (XVEC (pattern, i) == NULL)
1672 break;
1673 /* Fall through. */
1674 case 'E':
1675 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1676 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
1677 break;
1678
1679 case 'r': case 'p': case 'i': case 'w':
1680 case '0': case 's': case 'S': case 'T':
1681 break;
1682
1683 default:
1684 gcc_unreachable ();
1685 }
1686 }
1687}
1688
1689static rtx
1690alter_predicate_for_insn (rtx pattern, int alt, int max_op,
1691 file_location loc)
1692{
1693 const char *fmt;
1694 enum rtx_code code;
1695 int i, j, len;
1696
1697 code = GET_CODE (pattern);
1698 switch (code)
1699 {
1700 case MATCH_OPERAND:
1701 {
1702 const char *c = XSTR (pattern, 2);
1703
1704 if (n_alternatives (s: c) != 1)
1705 {
1706 error_at (loc, "too many alternatives for operand %d",
1707 XINT (pattern, 0));
1708 return NULL;
1709 }
1710
1711 /* Replicate C as needed to fill out ALT alternatives. */
1712 if (c && *c && alt > 1)
1713 {
1714 size_t c_len = strlen (s: c);
1715 size_t len = alt * (c_len + 1);
1716 char *new_c = XNEWVEC (char, len);
1717
1718 memcpy (dest: new_c, src: c, n: c_len);
1719 for (i = 1; i < alt; ++i)
1720 {
1721 new_c[i * (c_len + 1) - 1] = ',';
1722 memcpy (dest: &new_c[i * (c_len + 1)], src: c, n: c_len);
1723 }
1724 new_c[len - 1] = '\0';
1725 XSTR (pattern, 2) = new_c;
1726 }
1727 }
1728 /* Fall through. */
1729
1730 case MATCH_OPERATOR:
1731 case MATCH_SCRATCH:
1732 case MATCH_PARALLEL:
1733 case MATCH_DUP:
1734 XINT (pattern, 0) += max_op;
1735 break;
1736
1737 default:
1738 break;
1739 }
1740
1741 fmt = GET_RTX_FORMAT (code);
1742 len = GET_RTX_LENGTH (code);
1743 for (i = 0; i < len; i++)
1744 {
1745 rtx r;
1746
1747 switch (fmt[i])
1748 {
1749 case 'e': case 'u':
1750 r = alter_predicate_for_insn (XEXP (pattern, i), alt, max_op, loc);
1751 if (r == NULL)
1752 return r;
1753 break;
1754
1755 case 'E':
1756 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1757 {
1758 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
1759 alt, max_op, loc);
1760 if (r == NULL)
1761 return r;
1762 }
1763 break;
1764
1765 case 'r': case 'p': case 'i': case 'w': case '0': case 's':
1766 break;
1767
1768 default:
1769 gcc_unreachable ();
1770 }
1771 }
1772
1773 return pattern;
1774}
1775
1776/* Duplicate constraints in PATTERN. If pattern is from original
1777 rtl-template, we need to duplicate each alternative - for that we
1778 need to use duplicate_each_alternative () as a functor ALTER.
1779 If pattern is from output-pattern of define_subst, we need to
1780 duplicate constraints in another way - with duplicate_alternatives ().
1781 N_DUP is multiplication factor. */
1782static rtx
1783alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
1784{
1785 const char *fmt;
1786 enum rtx_code code;
1787 int i, j, len;
1788
1789 code = GET_CODE (pattern);
1790 switch (code)
1791 {
1792 case MATCH_OPERAND:
1793 XSTR (pattern, 2) = alter (XSTR (pattern, 2), n_dup);
1794 break;
1795 case MATCH_SCRATCH:
1796 XSTR (pattern, 1) = alter (XSTR (pattern, 1), n_dup);
1797 break;
1798
1799 default:
1800 break;
1801 }
1802
1803 fmt = GET_RTX_FORMAT (code);
1804 len = GET_RTX_LENGTH (code);
1805 for (i = 0; i < len; i++)
1806 {
1807 rtx r;
1808
1809 switch (fmt[i])
1810 {
1811 case 'e': case 'u':
1812 r = alter_constraints (XEXP (pattern, i), n_dup, alter);
1813 if (r == NULL)
1814 return r;
1815 break;
1816
1817 case 'E':
1818 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1819 {
1820 r = alter_constraints (XVECEXP (pattern, i, j), n_dup, alter);
1821 if (r == NULL)
1822 return r;
1823 }
1824 break;
1825
1826 case 'r': case 'p': case 'i': case 'w': case '0': case 's':
1827 break;
1828
1829 default:
1830 break;
1831 }
1832 }
1833
1834 return pattern;
1835}
1836
1837static const char *
1838alter_test_for_insn (class queue_elem *ce_elem,
1839 class queue_elem *insn_elem)
1840{
1841 return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1),
1842 XSTR (insn_elem->data, 2));
1843}
1844
1845/* Modify VAL, which is an attribute expression for the "enabled" attribute,
1846 to take "ce_enabled" into account. Return the new expression. */
1847static rtx
1848modify_attr_enabled_ce (rtx val)
1849{
1850 rtx eq_attr, str;
1851 rtx ite;
1852 eq_attr = rtx_alloc (EQ_ATTR);
1853 ite = rtx_alloc (IF_THEN_ELSE);
1854 str = rtx_alloc (CONST_STRING);
1855
1856 XSTR (eq_attr, 0) = "ce_enabled";
1857 XSTR (eq_attr, 1) = "yes";
1858 XSTR (str, 0) = "no";
1859 XEXP (ite, 0) = eq_attr;
1860 XEXP (ite, 1) = val;
1861 XEXP (ite, 2) = str;
1862
1863 return ite;
1864}
1865
1866/* Alter the attribute vector of INSN, which is a COND_EXEC variant created
1867 from a define_insn pattern. We must modify the "predicable" attribute
1868 to be named "ce_enabled", and also change any "enabled" attribute that's
1869 present so that it takes ce_enabled into account.
1870 We rely on the fact that INSN was created with copy_rtx, and modify data
1871 in-place. */
1872
1873static void
1874alter_attrs_for_insn (rtx insn)
1875{
1876 static bool global_changes_made = false;
1877 rtvec vec = XVEC (insn, 4);
1878 rtvec new_vec;
1879 rtx val, set;
1880 int num_elem;
1881 int predicable_idx = -1;
1882 int enabled_idx = -1;
1883 int i;
1884
1885 if (! vec)
1886 return;
1887
1888 num_elem = GET_NUM_ELEM (vec);
1889 for (i = num_elem - 1; i >= 0; --i)
1890 {
1891 rtx sub = RTVEC_ELT (vec, i);
1892 switch (GET_CODE (sub))
1893 {
1894 case SET_ATTR:
1895 if (strcmp (XSTR (sub, 0), s2: "predicable") == 0)
1896 {
1897 predicable_idx = i;
1898 XSTR (sub, 0) = "ce_enabled";
1899 }
1900 else if (strcmp (XSTR (sub, 0), s2: "enabled") == 0)
1901 {
1902 enabled_idx = i;
1903 XSTR (sub, 0) = "nonce_enabled";
1904 }
1905 break;
1906
1907 case SET_ATTR_ALTERNATIVE:
1908 if (strcmp (XSTR (sub, 0), s2: "predicable") == 0)
1909 /* We already give an error elsewhere. */
1910 return;
1911 else if (strcmp (XSTR (sub, 0), s2: "enabled") == 0)
1912 {
1913 enabled_idx = i;
1914 XSTR (sub, 0) = "nonce_enabled";
1915 }
1916 break;
1917
1918 case SET:
1919 if (GET_CODE (SET_DEST (sub)) != ATTR)
1920 break;
1921 if (strcmp (XSTR (SET_DEST (sub), 0), s2: "predicable") == 0)
1922 {
1923 sub = SET_SRC (sub);
1924 if (GET_CODE (sub) == CONST_STRING)
1925 {
1926 predicable_idx = i;
1927 XSTR (sub, 0) = "ce_enabled";
1928 }
1929 else
1930 /* We already give an error elsewhere. */
1931 return;
1932 break;
1933 }
1934 if (strcmp (XSTR (SET_DEST (sub), 0), s2: "enabled") == 0)
1935 {
1936 enabled_idx = i;
1937 XSTR (SET_DEST (sub), 0) = "nonce_enabled";
1938 }
1939 break;
1940
1941 default:
1942 gcc_unreachable ();
1943 }
1944 }
1945 if (predicable_idx == -1)
1946 return;
1947
1948 if (!global_changes_made)
1949 {
1950 class queue_elem *elem;
1951
1952 global_changes_made = true;
1953 add_define_attr (name: "ce_enabled");
1954 add_define_attr (name: "nonce_enabled");
1955
1956 for (elem = define_attr_queue; elem ; elem = elem->next)
1957 if (strcmp (XSTR (elem->data, 0), s2: "enabled") == 0)
1958 {
1959 XEXP (elem->data, 2)
1960 = modify_attr_enabled_ce (XEXP (elem->data, 2));
1961 }
1962 }
1963 if (enabled_idx == -1)
1964 return;
1965
1966 new_vec = rtvec_alloc (num_elem + 1);
1967 for (i = 0; i < num_elem; i++)
1968 RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
1969 val = rtx_alloc (IF_THEN_ELSE);
1970 XEXP (val, 0) = rtx_alloc (EQ_ATTR);
1971 XEXP (val, 1) = rtx_alloc (CONST_STRING);
1972 XEXP (val, 2) = rtx_alloc (CONST_STRING);
1973 XSTR (XEXP (val, 0), 0) = "nonce_enabled";
1974 XSTR (XEXP (val, 0), 1) = "yes";
1975 XSTR (XEXP (val, 1), 0) = "yes";
1976 XSTR (XEXP (val, 2), 0) = "no";
1977 set = rtx_alloc (SET);
1978 SET_DEST (set) = rtx_alloc (ATTR);
1979 XSTR (SET_DEST (set), 0) = "enabled";
1980 SET_SRC (set) = modify_attr_enabled_ce (val);
1981 RTVEC_ELT (new_vec, i) = set;
1982 XVEC (insn, 4) = new_vec;
1983}
1984
1985/* As number of constraints is changed after define_subst, we need to
1986 process attributes as well - we need to duplicate them the same way
1987 that we duplicated constraints in original pattern
1988 ELEM is a queue element, containing our rtl-template,
1989 N_DUP - multiplication factor. */
1990static void
1991alter_attrs_for_subst_insn (class queue_elem * elem, int n_dup)
1992{
1993 rtvec vec = XVEC (elem->data, 4);
1994 int num_elem;
1995 int i;
1996
1997 if (n_dup < 2 || ! vec)
1998 return;
1999
2000 num_elem = GET_NUM_ELEM (vec);
2001 for (i = num_elem - 1; i >= 0; --i)
2002 {
2003 rtx sub = RTVEC_ELT (vec, i);
2004 switch (GET_CODE (sub))
2005 {
2006 case SET_ATTR:
2007 if (strchr (XSTR (sub, 1), c: ',') != NULL)
2008 XSTR (sub, 1) = duplicate_alternatives (XSTR (sub, 1), n_dup);
2009 break;
2010
2011 case SET_ATTR_ALTERNATIVE:
2012 case SET:
2013 error_at (elem->loc,
2014 "%s: `define_subst' does not support attributes "
2015 "assigned by `set' and `set_attr_alternative'",
2016 XSTR (elem->data, 0));
2017 return;
2018
2019 default:
2020 gcc_unreachable ();
2021 }
2022 }
2023}
2024
2025/* Adjust all of the operand numbers in SRC to match the shift they'll
2026 get from an operand displacement of DISP. Return a pointer after the
2027 adjusted string. */
2028
2029static char *
2030shift_output_template (char *dest, const char *src, int disp)
2031{
2032 while (*src)
2033 {
2034 char c = *src++;
2035 *dest++ = c;
2036 if (c == '%')
2037 {
2038 c = *src++;
2039 if (ISDIGIT ((unsigned char) c))
2040 c += disp;
2041 else if (ISALPHA (c))
2042 {
2043 *dest++ = c;
2044 c = *src++ + disp;
2045 }
2046 *dest++ = c;
2047 }
2048 }
2049
2050 return dest;
2051}
2052
2053static const char *
2054alter_output_for_insn (class queue_elem *ce_elem,
2055 class queue_elem *insn_elem,
2056 int alt, int max_op)
2057{
2058 const char *ce_out, *insn_out;
2059 char *result, *p;
2060 size_t len, ce_len, insn_len;
2061
2062 /* ??? Could coordinate with genoutput to not duplicate code here. */
2063
2064 ce_out = XSTR (ce_elem->data, 2);
2065 insn_out = XTMPL (insn_elem->data, 3);
2066 if (!ce_out || *ce_out == '\0')
2067 return insn_out;
2068
2069 ce_len = strlen (s: ce_out);
2070 insn_len = strlen (s: insn_out);
2071
2072 if (*insn_out == '*')
2073 /* You must take care of the predicate yourself. */
2074 return insn_out;
2075
2076 if (*insn_out == '@')
2077 {
2078 len = (ce_len + 1) * alt + insn_len + 1;
2079 p = result = XNEWVEC (char, len);
2080
2081 do
2082 {
2083 do
2084 *p++ = *insn_out++;
2085 while (ISSPACE ((unsigned char) *insn_out));
2086
2087 if (*insn_out != '#')
2088 {
2089 p = shift_output_template (dest: p, src: ce_out, disp: max_op);
2090 *p++ = ' ';
2091 }
2092
2093 do
2094 *p++ = *insn_out++;
2095 while (*insn_out && *insn_out != '\n');
2096 }
2097 while (*insn_out);
2098 *p = '\0';
2099 }
2100 else
2101 {
2102 len = ce_len + 1 + insn_len + 1;
2103 result = XNEWVEC (char, len);
2104
2105 p = shift_output_template (dest: result, src: ce_out, disp: max_op);
2106 *p++ = ' ';
2107 memcpy (dest: p, src: insn_out, n: insn_len + 1);
2108 }
2109
2110 return result;
2111}
2112
2113/* From string STR "a,b,c" produce "a,b,c,a,b,c,a,b,c", i.e. original
2114 string, duplicated N_DUP times. */
2115
2116static const char *
2117duplicate_alternatives (const char * str, int n_dup)
2118{
2119 int i, len, new_len;
2120 char *result, *sp;
2121 const char *cp;
2122
2123 if (n_dup < 2)
2124 return str;
2125
2126 while (ISSPACE (*str))
2127 str++;
2128
2129 if (*str == '\0')
2130 return str;
2131
2132 cp = str;
2133 len = strlen (s: str);
2134 new_len = (len + 1) * n_dup;
2135
2136 sp = result = XNEWVEC (char, new_len);
2137
2138 /* Global modifier characters mustn't be duplicated: skip if found. */
2139 if (*cp == '=' || *cp == '+' || *cp == '%')
2140 {
2141 *sp++ = *cp++;
2142 len--;
2143 }
2144
2145 /* Copy original constraints N_DUP times. */
2146 for (i = 0; i < n_dup; i++, sp += len+1)
2147 {
2148 memcpy (dest: sp, src: cp, n: len);
2149 *(sp+len) = (i == n_dup - 1) ? '\0' : ',';
2150 }
2151
2152 return result;
2153}
2154
2155/* From string STR "a,b,c" produce "a,a,a,b,b,b,c,c,c", i.e. string where
2156 each alternative from the original string is duplicated N_DUP times. */
2157static const char *
2158duplicate_each_alternative (const char * str, int n_dup)
2159{
2160 int i, len, new_len;
2161 char *result, *sp, *ep, *cp;
2162
2163 if (n_dup < 2)
2164 return str;
2165
2166 while (ISSPACE (*str))
2167 str++;
2168
2169 if (*str == '\0')
2170 return str;
2171
2172 cp = xstrdup (str);
2173
2174 new_len = (strlen (s: cp) + 1) * n_dup;
2175
2176 sp = result = XNEWVEC (char, new_len);
2177
2178 /* Global modifier characters mustn't be duplicated: skip if found. */
2179 if (*cp == '=' || *cp == '+' || *cp == '%')
2180 *sp++ = *cp++;
2181
2182 do
2183 {
2184 if ((ep = strchr (s: cp, c: ',')) != NULL)
2185 *ep++ = '\0';
2186 len = strlen (s: cp);
2187
2188 /* Copy a constraint N_DUP times. */
2189 for (i = 0; i < n_dup; i++, sp += len + 1)
2190 {
2191 memcpy (dest: sp, src: cp, n: len);
2192 *(sp+len) = (ep == NULL && i == n_dup - 1) ? '\0' : ',';
2193 }
2194
2195 cp = ep;
2196 }
2197 while (cp != NULL);
2198
2199 return result;
2200}
2201
2202/* Alter the output of INSN whose pattern was modified by
2203 DEFINE_SUBST. We must replicate output strings according
2204 to the new number of alternatives ALT in substituted pattern.
2205 If ALT equals 1, output has one alternative or defined by C
2206 code, then output is returned without any changes. */
2207
2208static const char *
2209alter_output_for_subst_insn (rtx insn, int alt)
2210{
2211 const char *insn_out, *old_out;
2212 char *new_out, *cp;
2213 size_t old_len, new_len;
2214 int j;
2215
2216 insn_out = XTMPL (insn, 3);
2217
2218 if (alt < 2 || *insn_out != '@')
2219 return insn_out;
2220
2221 old_out = insn_out + 1;
2222 while (ISSPACE (*old_out))
2223 old_out++;
2224 old_len = strlen (s: old_out);
2225
2226 new_len = alt * (old_len + 1) + 1;
2227
2228 new_out = XNEWVEC (char, new_len);
2229 new_out[0] = '@';
2230
2231 for (j = 0, cp = new_out + 1; j < alt; j++, cp += old_len + 1)
2232 {
2233 memcpy (dest: cp, src: old_out, n: old_len);
2234 cp[old_len] = (j == alt - 1) ? '\0' : '\n';
2235 }
2236
2237 return new_out;
2238}
2239
2240/* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
2241
2242static void
2243process_one_cond_exec (class queue_elem *ce_elem)
2244{
2245 class queue_elem *insn_elem;
2246 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
2247 {
2248 int alternatives, max_operand;
2249 rtx pred, insn, pattern, split;
2250 char *new_name;
2251 int i;
2252
2253 if (! is_predicable (elem: insn_elem))
2254 continue;
2255
2256 alternatives = 1;
2257 max_operand = -1;
2258 collect_insn_data (pattern: insn_elem->data, palt: &alternatives, pmax: &max_operand);
2259 max_operand += 1;
2260
2261 if (XVECLEN (ce_elem->data, 0) != 1)
2262 {
2263 error_at (ce_elem->loc, "too many patterns in predicate");
2264 return;
2265 }
2266
2267 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
2268 pred = alter_predicate_for_insn (pattern: pred, alt: alternatives, max_op: max_operand,
2269 loc: ce_elem->loc);
2270 if (pred == NULL)
2271 return;
2272
2273 /* Construct a new pattern for the new insn. */
2274 insn = copy_rtx (insn_elem->data);
2275 new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
2276 sprintf (s: new_name, format: "*p %s", XSTR (insn_elem->data, 0));
2277 XSTR (insn, 0) = new_name;
2278 pattern = rtx_alloc (COND_EXEC);
2279 XEXP (pattern, 0) = pred;
2280 XEXP (pattern, 1) = add_implicit_parallel (XVEC (insn, 1));
2281 XVEC (insn, 1) = rtvec_alloc (1);
2282 XVECEXP (insn, 1, 0) = pattern;
2283
2284 if (XVEC (ce_elem->data, 3) != NULL)
2285 {
2286 rtvec attributes = rtvec_alloc (XVECLEN (insn, 4)
2287 + XVECLEN (ce_elem->data, 3));
2288 int i = 0;
2289 int j = 0;
2290 for (i = 0; i < XVECLEN (insn, 4); i++)
2291 RTVEC_ELT (attributes, i) = XVECEXP (insn, 4, i);
2292
2293 for (j = 0; j < XVECLEN (ce_elem->data, 3); j++, i++)
2294 RTVEC_ELT (attributes, i) = XVECEXP (ce_elem->data, 3, j);
2295
2296 XVEC (insn, 4) = attributes;
2297 }
2298
2299 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
2300 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
2301 alt: alternatives, max_op: max_operand);
2302 alter_attrs_for_insn (insn);
2303
2304 /* Put the new pattern on the `other' list so that it
2305 (a) is not reprocessed by other define_cond_exec patterns
2306 (b) appears after all normal define_insn patterns.
2307
2308 ??? B is debatable. If one has normal insns that match
2309 cond_exec patterns, they will be preferred over these
2310 generated patterns. Whether this matters in practice, or if
2311 it's a good thing, or whether we should thread these new
2312 patterns into the define_insn chain just after their generator
2313 is something we'll have to experiment with. */
2314
2315 queue_pattern (pattern: insn, list_tail: &other_tail, loc: insn_elem->loc);
2316
2317 if (!insn_elem->split)
2318 continue;
2319
2320 /* If the original insn came from a define_insn_and_split,
2321 generate a new split to handle the predicated insn. */
2322 split = copy_rtx (insn_elem->split->data);
2323 /* Predicate the pattern matched by the split. */
2324 pattern = rtx_alloc (COND_EXEC);
2325 XEXP (pattern, 0) = pred;
2326 XEXP (pattern, 1) = add_implicit_parallel (XVEC (split, 0));
2327 XVEC (split, 0) = rtvec_alloc (1);
2328 XVECEXP (split, 0, 0) = pattern;
2329
2330 /* Predicate all of the insns generated by the split. */
2331 for (i = 0; i < XVECLEN (split, 2); i++)
2332 {
2333 pattern = rtx_alloc (COND_EXEC);
2334 XEXP (pattern, 0) = pred;
2335 XEXP (pattern, 1) = XVECEXP (split, 2, i);
2336 XVECEXP (split, 2, i) = pattern;
2337 }
2338 /* Add the new split to the queue. */
2339 queue_pattern (pattern: split, list_tail: &other_tail, loc: insn_elem->split->loc);
2340 }
2341}
2342
2343/* Try to apply define_substs to the given ELEM.
2344 Only define_substs, specified via attributes would be applied.
2345 If attribute, requiring define_subst, is set, but no define_subst
2346 was applied, ELEM would be deleted. */
2347
2348static void
2349process_substs_on_one_elem (class queue_elem *elem,
2350 class queue_elem *queue)
2351{
2352 class queue_elem *subst_elem;
2353 int i, j, patterns_match;
2354
2355 for (subst_elem = define_subst_queue;
2356 subst_elem; subst_elem = subst_elem->next)
2357 {
2358 int alternatives, alternatives_subst;
2359 rtx subst_pattern;
2360 rtvec subst_pattern_vec;
2361
2362 if (!has_subst_attribute (elem, subst_elem))
2363 continue;
2364
2365 /* Compare original rtl-pattern from define_insn with input
2366 pattern from define_subst.
2367 Also, check if numbers of alternatives are the same in all
2368 match_operands. */
2369 if (XVECLEN (elem->data, 1) != XVECLEN (subst_elem->data, 1))
2370 continue;
2371 patterns_match = 1;
2372 alternatives = -1;
2373 alternatives_subst = -1;
2374 for (j = 0; j < XVECLEN (elem->data, 1); j++)
2375 {
2376 if (!subst_pattern_match (XVECEXP (elem->data, 1, j),
2377 XVECEXP (subst_elem->data, 1, j),
2378 loc: subst_elem->loc))
2379 {
2380 patterns_match = 0;
2381 break;
2382 }
2383
2384 if (!get_alternatives_number (XVECEXP (elem->data, 1, j),
2385 n_alt: &alternatives, loc: subst_elem->loc))
2386 {
2387 patterns_match = 0;
2388 break;
2389 }
2390 }
2391
2392 /* Check if numbers of alternatives are the same in all
2393 match_operands in output template of define_subst. */
2394 for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
2395 {
2396 if (!get_alternatives_number (XVECEXP (subst_elem->data, 3, j),
2397 n_alt: &alternatives_subst,
2398 loc: subst_elem->loc))
2399 {
2400 patterns_match = 0;
2401 break;
2402 }
2403 }
2404
2405 if (!patterns_match)
2406 continue;
2407
2408 /* Clear array in which we save occupied indexes of operands. */
2409 memset (s: used_operands_numbers, c: 0, n: sizeof (used_operands_numbers));
2410
2411 /* Create a pattern, based on the output one from define_subst. */
2412 subst_pattern_vec = rtvec_alloc (XVECLEN (subst_elem->data, 3));
2413 for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
2414 {
2415 subst_pattern = copy_rtx (XVECEXP (subst_elem->data, 3, j));
2416
2417 /* Duplicate constraints in substitute-pattern. */
2418 subst_pattern = alter_constraints (pattern: subst_pattern, n_dup: alternatives,
2419 alter: duplicate_each_alternative);
2420
2421 subst_pattern = adjust_operands_numbers (subst_pattern);
2422
2423 /* Substitute match_dup and match_op_dup in the new pattern and
2424 duplicate constraints. */
2425 subst_pattern = subst_dup (subst_pattern, alternatives,
2426 alternatives_subst);
2427
2428 replace_duplicating_operands_in_pattern (subst_pattern);
2429
2430 /* We don't need any constraints in DEFINE_EXPAND. */
2431 if (GET_CODE (elem->data) == DEFINE_EXPAND)
2432 remove_constraints (part: subst_pattern);
2433
2434 RTVEC_ELT (subst_pattern_vec, j) = subst_pattern;
2435 }
2436 XVEC (elem->data, 1) = subst_pattern_vec;
2437
2438 for (i = 0; i < MAX_OPERANDS; i++)
2439 match_operand_entries_in_pattern[i] = NULL;
2440
2441 if (GET_CODE (elem->data) == DEFINE_INSN)
2442 {
2443 XTMPL (elem->data, 3) =
2444 alter_output_for_subst_insn (insn: elem->data, alt: alternatives_subst);
2445 alter_attrs_for_subst_insn (elem, n_dup: alternatives_subst);
2446 }
2447
2448 /* Recalculate condition, joining conditions from original and
2449 DEFINE_SUBST input patterns. */
2450 XSTR (elem->data, 2)
2451 = rtx_reader_ptr->join_c_conditions (XSTR (subst_elem->data, 2),
2452 XSTR (elem->data, 2));
2453 /* Mark that subst was applied by changing attribute from "yes"
2454 to "no". */
2455 change_subst_attribute (elem, subst_elem, new_value: subst_false);
2456 }
2457
2458 /* If ELEM contains a subst attribute with value "yes", then we
2459 expected that a subst would be applied, but it wasn't - so,
2460 we need to remove that elementto avoid duplicating. */
2461 for (subst_elem = define_subst_queue;
2462 subst_elem; subst_elem = subst_elem->next)
2463 {
2464 if (has_subst_attribute (elem, subst_elem))
2465 {
2466 remove_from_queue (elem, queue: &queue);
2467 return;
2468 }
2469 }
2470}
2471
2472/* This is a subroutine of mark_operands_used_in_match_dup.
2473 This routine is marks all MATCH_OPERANDs inside PATTERN as occupied. */
2474static void
2475mark_operands_from_match_dup (rtx pattern)
2476{
2477 const char *fmt;
2478 int i, j, len, opno;
2479
2480 if (GET_CODE (pattern) == MATCH_OPERAND
2481 || GET_CODE (pattern) == MATCH_OPERATOR
2482 || GET_CODE (pattern) == MATCH_PARALLEL)
2483 {
2484 opno = XINT (pattern, 0);
2485 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2486 used_operands_numbers [opno] = 1;
2487 }
2488 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2489 len = GET_RTX_LENGTH (GET_CODE (pattern));
2490 for (i = 0; i < len; i++)
2491 {
2492 switch (fmt[i])
2493 {
2494 case 'e': case 'u':
2495 mark_operands_from_match_dup (XEXP (pattern, i));
2496 break;
2497 case 'E':
2498 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2499 mark_operands_from_match_dup (XVECEXP (pattern, i, j));
2500 break;
2501 }
2502 }
2503}
2504
2505/* This is a subroutine of adjust_operands_numbers.
2506 It goes through all expressions in PATTERN and when MATCH_DUP is
2507 met, all MATCH_OPERANDs inside it is marked as occupied. The
2508 process of marking is done by routin mark_operands_from_match_dup. */
2509static void
2510mark_operands_used_in_match_dup (rtx pattern)
2511{
2512 const char *fmt;
2513 int i, j, len, opno;
2514
2515 if (GET_CODE (pattern) == MATCH_DUP)
2516 {
2517 opno = XINT (pattern, 0);
2518 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2519 mark_operands_from_match_dup (pattern: operand_data[opno]);
2520 return;
2521 }
2522 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2523 len = GET_RTX_LENGTH (GET_CODE (pattern));
2524 for (i = 0; i < len; i++)
2525 {
2526 switch (fmt[i])
2527 {
2528 case 'e': case 'u':
2529 mark_operands_used_in_match_dup (XEXP (pattern, i));
2530 break;
2531 case 'E':
2532 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2533 mark_operands_used_in_match_dup (XVECEXP (pattern, i, j));
2534 break;
2535 }
2536 }
2537}
2538
2539/* This is subroutine of renumerate_operands_in_pattern.
2540 It finds first not-occupied operand-index. */
2541static int
2542find_first_unused_number_of_operand ()
2543{
2544 int i;
2545 for (i = 0; i < MAX_OPERANDS; i++)
2546 if (!used_operands_numbers[i])
2547 return i;
2548 return MAX_OPERANDS;
2549}
2550
2551/* This is subroutine of adjust_operands_numbers.
2552 It visits all expressions in PATTERN and assigns not-occupied
2553 operand indexes to MATCH_OPERANDs and MATCH_OPERATORs of this
2554 PATTERN. */
2555static void
2556renumerate_operands_in_pattern (rtx pattern)
2557{
2558 const char *fmt;
2559 enum rtx_code code;
2560 int i, j, len, new_opno;
2561 code = GET_CODE (pattern);
2562
2563 if (code == MATCH_OPERAND
2564 || code == MATCH_OPERATOR)
2565 {
2566 new_opno = find_first_unused_number_of_operand ();
2567 gcc_assert (new_opno >= 0 && new_opno < MAX_OPERANDS);
2568 XINT (pattern, 0) = new_opno;
2569 used_operands_numbers [new_opno] = 1;
2570 }
2571
2572 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2573 len = GET_RTX_LENGTH (GET_CODE (pattern));
2574 for (i = 0; i < len; i++)
2575 {
2576 switch (fmt[i])
2577 {
2578 case 'e': case 'u':
2579 renumerate_operands_in_pattern (XEXP (pattern, i));
2580 break;
2581 case 'E':
2582 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2583 renumerate_operands_in_pattern (XVECEXP (pattern, i, j));
2584 break;
2585 }
2586 }
2587}
2588
2589/* If output pattern of define_subst contains MATCH_DUP, then this
2590 expression would be replaced with the pattern, matched with
2591 MATCH_OPERAND from input pattern. This pattern could contain any
2592 number of MATCH_OPERANDs, MATCH_OPERATORs etc., so it's possible
2593 that a MATCH_OPERAND from output_pattern (if any) would have the
2594 same number, as MATCH_OPERAND from copied pattern. To avoid such
2595 indexes overlapping, we assign new indexes to MATCH_OPERANDs,
2596 laying in the output pattern outside of MATCH_DUPs. */
2597static rtx
2598adjust_operands_numbers (rtx pattern)
2599{
2600 mark_operands_used_in_match_dup (pattern);
2601
2602 renumerate_operands_in_pattern (pattern);
2603
2604 return pattern;
2605}
2606
2607/* Generate RTL expression
2608 (match_dup OPNO)
2609 */
2610static rtx
2611generate_match_dup (int opno)
2612{
2613 rtx return_rtx = rtx_alloc (MATCH_DUP);
2614 PUT_CODE (return_rtx, MATCH_DUP);
2615 XINT (return_rtx, 0) = opno;
2616 return return_rtx;
2617}
2618
2619/* This routine checks all match_operands in PATTERN and if some of
2620 have the same index, it replaces all of them except the first one to
2621 match_dup.
2622 Usually, match_operands with the same indexes are forbidden, but
2623 after define_subst copy an RTL-expression from original template,
2624 indexes of existed and just-copied match_operands could coincide.
2625 To fix it, we replace one of them with match_dup. */
2626static rtx
2627replace_duplicating_operands_in_pattern (rtx pattern)
2628{
2629 const char *fmt;
2630 int i, j, len, opno;
2631 rtx mdup;
2632
2633 if (GET_CODE (pattern) == MATCH_OPERAND)
2634 {
2635 opno = XINT (pattern, 0);
2636 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2637 if (match_operand_entries_in_pattern[opno] == NULL)
2638 {
2639 match_operand_entries_in_pattern[opno] = pattern;
2640 return NULL;
2641 }
2642 else
2643 {
2644 /* Compare predicates before replacing with match_dup. */
2645 if (strcmp (XSTR (pattern, 1),
2646 XSTR (match_operand_entries_in_pattern[opno], 1)))
2647 {
2648 error ("duplicated match_operands with different predicates were"
2649 " found.");
2650 return NULL;
2651 }
2652 return generate_match_dup (opno);
2653 }
2654 }
2655 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2656 len = GET_RTX_LENGTH (GET_CODE (pattern));
2657 for (i = 0; i < len; i++)
2658 {
2659 switch (fmt[i])
2660 {
2661 case 'e': case 'u':
2662 mdup = replace_duplicating_operands_in_pattern (XEXP (pattern, i));
2663 if (mdup)
2664 XEXP (pattern, i) = mdup;
2665 break;
2666 case 'E':
2667 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2668 {
2669 mdup =
2670 replace_duplicating_operands_in_pattern (XVECEXP
2671 (pattern, i, j));
2672 if (mdup)
2673 XVECEXP (pattern, i, j) = mdup;
2674 }
2675 break;
2676 }
2677 }
2678 return NULL;
2679}
2680
2681/* The routine modifies given input PATTERN of define_subst, replacing
2682 MATCH_DUP and MATCH_OP_DUP with operands from define_insn original
2683 pattern, whose operands are stored in OPERAND_DATA array.
2684 It also duplicates constraints in operands - constraints from
2685 define_insn operands are duplicated N_SUBST_ALT times, constraints
2686 from define_subst operands are duplicated N_ALT times.
2687 After the duplication, returned output rtl-pattern contains every
2688 combination of input constraints Vs constraints from define_subst
2689 output. */
2690static rtx
2691subst_dup (rtx pattern, int n_alt, int n_subst_alt)
2692{
2693 const char *fmt;
2694 enum rtx_code code;
2695 int i, j, len, opno;
2696
2697 code = GET_CODE (pattern);
2698 switch (code)
2699 {
2700 case MATCH_DUP:
2701 case MATCH_OP_DUP:
2702 opno = XINT (pattern, 0);
2703
2704 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2705
2706 if (operand_data[opno])
2707 {
2708 pattern = copy_rtx (operand_data[opno]);
2709
2710 /* Duplicate constraints. */
2711 pattern = alter_constraints (pattern, n_dup: n_subst_alt,
2712 alter: duplicate_alternatives);
2713 }
2714 break;
2715
2716 default:
2717 break;
2718 }
2719
2720 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2721 len = GET_RTX_LENGTH (GET_CODE (pattern));
2722 for (i = 0; i < len; i++)
2723 {
2724 switch (fmt[i])
2725 {
2726 case 'e': case 'u':
2727 if (code != MATCH_DUP && code != MATCH_OP_DUP)
2728 XEXP (pattern, i) = subst_dup (XEXP (pattern, i),
2729 n_alt, n_subst_alt);
2730 break;
2731 case 'V':
2732 if (XVEC (pattern, i) == NULL)
2733 break;
2734 /* FALLTHRU */
2735 case 'E':
2736 if (code != MATCH_DUP && code != MATCH_OP_DUP)
2737 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2738 XVECEXP (pattern, i, j) = subst_dup (XVECEXP (pattern, i, j),
2739 n_alt, n_subst_alt);
2740 break;
2741
2742 case 'r': case 'p': case 'i': case 'w':
2743 case '0': case 's': case 'S': case 'T':
2744 break;
2745
2746 default:
2747 gcc_unreachable ();
2748 }
2749 }
2750 return pattern;
2751}
2752
2753/* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
2754 patterns appropriately. */
2755
2756static void
2757process_define_cond_exec (void)
2758{
2759 class queue_elem *elem;
2760
2761 identify_predicable_attribute ();
2762 if (have_error)
2763 return;
2764
2765 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
2766 process_one_cond_exec (ce_elem: elem);
2767}
2768
2769/* If we have any DEFINE_SUBST patterns, expand DEFINE_INSN and
2770 DEFINE_EXPAND patterns appropriately. */
2771
2772static void
2773process_define_subst (void)
2774{
2775 class queue_elem *elem, *elem_attr;
2776
2777 /* Check if each define_subst has corresponding define_subst_attr. */
2778 for (elem = define_subst_queue; elem ; elem = elem->next)
2779 {
2780 for (elem_attr = define_subst_attr_queue;
2781 elem_attr;
2782 elem_attr = elem_attr->next)
2783 if (strcmp (XSTR (elem->data, 0), XSTR (elem_attr->data, 1)) == 0)
2784 goto found;
2785
2786 error_at (elem->loc,
2787 "%s: `define_subst' must have at least one "
2788 "corresponding `define_subst_attr'",
2789 XSTR (elem->data, 0));
2790 return;
2791
2792 found:
2793 continue;
2794 }
2795
2796 for (elem = define_insn_queue; elem ; elem = elem->next)
2797 process_substs_on_one_elem (elem, queue: define_insn_queue);
2798 for (elem = other_queue; elem ; elem = elem->next)
2799 {
2800 if (GET_CODE (elem->data) != DEFINE_EXPAND)
2801 continue;
2802 process_substs_on_one_elem (elem, queue: other_queue);
2803 }
2804}
2805
2806/* A subclass of rtx_reader which reads .md files and calls process_rtx on
2807 the top-level elements. */
2808
2809class gen_reader : public rtx_reader
2810{
2811 public:
2812 gen_reader () : rtx_reader (false) {}
2813 void handle_unknown_directive (file_location, const char *) final override;
2814};
2815
2816void
2817gen_reader::handle_unknown_directive (file_location loc, const char *rtx_name)
2818{
2819 auto_vec<rtx, 32> subrtxs;
2820 if (!read_rtx (rtx_name, rtxen: &subrtxs))
2821 return;
2822
2823 rtx x;
2824 unsigned int i;
2825 FOR_EACH_VEC_ELT (subrtxs, i, x)
2826 process_rtx (desc: x, loc);
2827}
2828
2829/* Add mnemonic STR with length LEN to the mnemonic hash table
2830 MNEMONIC_HTAB. A trailing zero end character is appended to STR
2831 and a permanent heap copy of STR is created. */
2832
2833static void
2834add_mnemonic_string (htab_t mnemonic_htab, const char *str, size_t len)
2835{
2836 char *new_str;
2837 void **slot;
2838 char *str_zero = (char*)alloca (len + 1);
2839
2840 memcpy (dest: str_zero, src: str, n: len);
2841 str_zero[len] = '\0';
2842
2843 slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
2844
2845 if (*slot)
2846 return;
2847
2848 /* Not found; create a permanent copy and add it to the hash table. */
2849 new_str = XNEWVAR (char, len + 1);
2850 memcpy (dest: new_str, src: str_zero, n: len + 1);
2851 *slot = new_str;
2852}
2853
2854/* Scan INSN for mnemonic strings and add them to the mnemonic hash
2855 table in MNEMONIC_HTAB.
2856
2857 The mnemonics cannot be found if they are emitted using C code.
2858
2859 If a mnemonic string contains ';' or a newline the string assumed
2860 to consist of more than a single instruction. The attribute value
2861 will then be set to the user defined default value. */
2862
2863static void
2864gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
2865{
2866 const char *template_code, *cp;
2867 int i;
2868 int vec_len;
2869 rtx set_attr;
2870 char *attr_name;
2871 rtvec new_vec;
2872 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2873
2874 template_code = XTMPL (insn, 3);
2875
2876 /* Skip patterns which use C code to emit the template. */
2877 if (template_code[0] == '*')
2878 return;
2879
2880 if (template_code[0] == '@')
2881 cp = &template_code[1];
2882 else
2883 cp = &template_code[0];
2884
2885 for (i = 0; *cp; )
2886 {
2887 const char *ep, *sp;
2888 size_t size = 0;
2889
2890 while (ISSPACE (*cp))
2891 cp++;
2892
2893 for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
2894 if (!ISSPACE (*ep))
2895 sp = ep + 1;
2896
2897 if (i > 0)
2898 obstack_1grow (string_obstack, ',');
2899
2900 while (cp < sp && ((*cp >= '0' && *cp <= '9')
2901 || (*cp >= 'a' && *cp <= 'z')))
2902
2903 {
2904 obstack_1grow (string_obstack, *cp);
2905 cp++;
2906 size++;
2907 }
2908
2909 while (cp < sp)
2910 {
2911 if (*cp == ';' || (*cp == '\\' && cp[1] == 'n'))
2912 {
2913 /* Don't set a value if there are more than one
2914 instruction in the string. */
2915 obstack_blank_fast (string_obstack, -size);
2916 size = 0;
2917
2918 cp = sp;
2919 break;
2920 }
2921 cp++;
2922 }
2923 if (size == 0)
2924 obstack_1grow (string_obstack, '*');
2925 else
2926 add_mnemonic_string (mnemonic_htab,
2927 str: (char *) obstack_next_free (string_obstack) - size,
2928 len: size);
2929 i++;
2930 }
2931
2932 /* An insn definition might emit an empty string. */
2933 if (obstack_object_size (string_obstack) == 0)
2934 return;
2935
2936 obstack_1grow (string_obstack, '\0');
2937
2938 set_attr = rtx_alloc (SET_ATTR);
2939 XSTR (set_attr, 1) = XOBFINISH (string_obstack, char *);
2940 attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
2941 strcpy (dest: attr_name, MNEMONIC_ATTR_NAME);
2942 XSTR (set_attr, 0) = attr_name;
2943
2944 if (!XVEC (insn, 4))
2945 vec_len = 0;
2946 else
2947 vec_len = XVECLEN (insn, 4);
2948
2949 new_vec = rtvec_alloc (vec_len + 1);
2950 for (i = 0; i < vec_len; i++)
2951 RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i);
2952 RTVEC_ELT (new_vec, vec_len) = set_attr;
2953 XVEC (insn, 4) = new_vec;
2954}
2955
2956/* This function is called for the elements in the mnemonic hashtable
2957 and generates a comma separated list of the mnemonics. */
2958
2959static int
2960mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
2961{
2962 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2963
2964 obstack_grow (string_obstack, (char*) *slot, strlen ((char*) *slot));
2965 obstack_1grow (string_obstack, ',');
2966 return 1;
2967}
2968
2969/* Generate (set_attr "mnemonic" "..") RTXs and append them to every
2970 insn definition in case the back end requests it by defining the
2971 mnemonic attribute. The values for the attribute will be extracted
2972 from the output patterns of the insn definitions as far as
2973 possible. */
2974
2975static void
2976gen_mnemonic_attr (void)
2977{
2978 class queue_elem *elem;
2979 rtx mnemonic_attr = NULL;
2980 htab_t mnemonic_htab;
2981 const char *str, *p;
2982 int i;
2983 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2984
2985 if (have_error)
2986 return;
2987
2988 /* Look for the DEFINE_ATTR for `mnemonic'. */
2989 for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next)
2990 if (GET_CODE (elem->data) == DEFINE_ATTR
2991 && strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0)
2992 {
2993 mnemonic_attr = elem->data;
2994 break;
2995 }
2996
2997 /* A (define_attr "mnemonic" "...") indicates that the back-end
2998 wants a mnemonic attribute to be generated. */
2999 if (!mnemonic_attr)
3000 return;
3001
3002 mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
3003 htab_eq_string, 0, xcalloc, free);
3004
3005 for (elem = define_insn_queue; elem; elem = elem->next)
3006 {
3007 rtx insn = elem->data;
3008 bool found = false;
3009
3010 /* Check if the insn definition already has
3011 (set_attr "mnemonic" ...) or (set (attr "mnemonic") ...). */
3012 if (XVEC (insn, 4))
3013 for (i = 0; i < XVECLEN (insn, 4); i++)
3014 {
3015 rtx set_attr = XVECEXP (insn, 4, i);
3016
3017 switch (GET_CODE (set_attr))
3018 {
3019 case SET_ATTR:
3020 case SET_ATTR_ALTERNATIVE:
3021 if (strcmp (XSTR (set_attr, 0), MNEMONIC_ATTR_NAME) == 0)
3022 found = true;
3023 break;
3024 case SET:
3025 if (GET_CODE (SET_DEST (set_attr)) == ATTR
3026 && strcmp (XSTR (SET_DEST (set_attr), 0),
3027 MNEMONIC_ATTR_NAME) == 0)
3028 found = true;
3029 break;
3030 default:
3031 break;
3032 }
3033 }
3034
3035 if (!found)
3036 gen_mnemonic_setattr (mnemonic_htab, insn);
3037 }
3038
3039 /* Add the user defined values to the hash table. */
3040 str = XSTR (mnemonic_attr, 1);
3041 while ((p = scan_comma_elt (&str)) != NULL)
3042 add_mnemonic_string (mnemonic_htab, str: p, len: str - p);
3043
3044 htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
3045
3046 /* Replace the last ',' with the zero end character. */
3047 *((char *) obstack_next_free (string_obstack) - 1) = '\0';
3048 XSTR (mnemonic_attr, 1) = XOBFINISH (string_obstack, char *);
3049}
3050
3051/* Check if there are DEFINE_ATTRs with the same name. */
3052static void
3053check_define_attr_duplicates ()
3054{
3055 class queue_elem *elem;
3056 htab_t attr_htab;
3057 char * attr_name;
3058 void **slot;
3059
3060 attr_htab = htab_create (500, htab_hash_string, htab_eq_string, NULL);
3061
3062 for (elem = define_attr_queue; elem; elem = elem->next)
3063 {
3064 attr_name = xstrdup (XSTR (elem->data, 0));
3065
3066 slot = htab_find_slot (attr_htab, attr_name, INSERT);
3067
3068 /* Duplicate. */
3069 if (*slot)
3070 {
3071 error_at (elem->loc, "redefinition of attribute '%s'", attr_name);
3072 htab_delete (attr_htab);
3073 return;
3074 }
3075
3076 *slot = attr_name;
3077 }
3078
3079 htab_delete (attr_htab);
3080}
3081
3082/* The entry point for initializing the reader. */
3083
3084rtx_reader *
3085init_rtx_reader_args_cb (int argc, const char **argv,
3086 bool (*parse_opt) (const char *))
3087{
3088 /* Prepare to read input. */
3089 condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
3090 init_predicate_table ();
3091 obstack_init (rtl_obstack);
3092
3093 /* Start at 1, to make 0 available for CODE_FOR_nothing. */
3094 insn_sequence_num = 1;
3095
3096 /* These sequences are not used as indices, so can start at 1 also. */
3097 split_sequence_num = 1;
3098 peephole2_sequence_num = 1;
3099
3100 gen_reader *reader = new gen_reader ();
3101 reader->read_md_files (argc, argv, parse_opt);
3102
3103 if (define_attr_queue != NULL)
3104 check_define_attr_duplicates ();
3105
3106 /* Process define_cond_exec patterns. */
3107 if (define_cond_exec_queue != NULL)
3108 process_define_cond_exec ();
3109
3110 /* Process define_subst patterns. */
3111 if (define_subst_queue != NULL)
3112 process_define_subst ();
3113
3114 if (define_attr_queue != NULL)
3115 gen_mnemonic_attr ();
3116
3117 if (have_error)
3118 {
3119 delete reader;
3120 return NULL;
3121 }
3122
3123 return reader;
3124}
3125
3126/* Programs that don't have their own options can use this entry point
3127 instead. */
3128rtx_reader *
3129init_rtx_reader_args (int argc, const char **argv)
3130{
3131 return init_rtx_reader_args_cb (argc, argv, parse_opt: 0);
3132}
3133
3134/* Count the number of patterns in all queues and return the count. */
3135int
3136count_patterns ()
3137{
3138 int count = 0, truth = 1;
3139 rtx def;
3140 class queue_elem *cur = define_attr_queue;
3141 while (cur)
3142 {
3143 def = cur->data;
3144
3145 truth = maybe_eval_c_test (get_c_test (def));
3146 if (truth || !insn_elision)
3147 count++;
3148 cur = cur->next;
3149 }
3150
3151 cur = define_pred_queue;
3152 while (cur)
3153 {
3154 def = cur->data;
3155
3156 truth = maybe_eval_c_test (get_c_test (def));
3157 if (truth || !insn_elision)
3158 count++;
3159 cur = cur->next;
3160 }
3161
3162 cur = define_insn_queue;
3163 truth = 1;
3164 while (cur)
3165 {
3166 def = cur->data;
3167
3168 truth = maybe_eval_c_test (get_c_test (def));
3169 if (truth || !insn_elision)
3170 count++;
3171 cur = cur->next;
3172 }
3173
3174 cur = other_queue;
3175 truth = 1;
3176 while (cur)
3177 {
3178 def = cur->data;
3179
3180 truth = maybe_eval_c_test (get_c_test (def));
3181 if (truth || !insn_elision)
3182 count++;
3183 cur = cur->next;
3184 }
3185
3186 return count;
3187}
3188
3189/* Try to read a single rtx from the file. Return true on success,
3190 describing it in *INFO. */
3191
3192bool
3193read_md_rtx (md_rtx_info *info)
3194{
3195 int truth, *counter;
3196 rtx def;
3197
3198 /* Discard insn patterns which we know can never match (because
3199 their C test is provably always false). If insn_elision is
3200 false, our caller needs to see all the patterns. Note that the
3201 elided patterns are never counted by the sequence numbering; it
3202 is the caller's responsibility, when insn_elision is false, not
3203 to use elided pattern numbers for anything. */
3204 do
3205 {
3206 class queue_elem **queue, *elem;
3207
3208 /* Read all patterns from a given queue before moving on to the next. */
3209 if (define_attr_queue != NULL)
3210 queue = &define_attr_queue;
3211 else if (define_pred_queue != NULL)
3212 queue = &define_pred_queue;
3213 else if (define_insn_queue != NULL)
3214 queue = &define_insn_queue;
3215 else if (other_queue != NULL)
3216 queue = &other_queue;
3217 else
3218 return false;
3219
3220 elem = *queue;
3221 *queue = elem->next;
3222 def = elem->data;
3223 info->def = def;
3224 info->loc = elem->loc;
3225 free (ptr: elem);
3226
3227 truth = maybe_eval_c_test (get_c_test (def));
3228 }
3229 while (truth == 0 && insn_elision);
3230
3231 /* Perform code-specific processing and pick the appropriate sequence
3232 number counter. */
3233 switch (GET_CODE (def))
3234 {
3235 case DEFINE_INSN:
3236 case DEFINE_EXPAND:
3237 /* insn_sequence_num is used here so the name table will match caller's
3238 idea of insn numbering, whether or not elision is active. */
3239 record_insn_name (insn_sequence_num, XSTR (def, 0));
3240
3241 /* Fall through. */
3242 case DEFINE_PEEPHOLE:
3243 counter = &insn_sequence_num;
3244 break;
3245
3246 case DEFINE_SPLIT:
3247 counter = &split_sequence_num;
3248 break;
3249
3250 case DEFINE_PEEPHOLE2:
3251 counter = &peephole2_sequence_num;
3252 break;
3253
3254 default:
3255 counter = NULL;
3256 break;
3257 }
3258
3259 if (counter)
3260 {
3261 info->index = *counter;
3262 if (truth != 0)
3263 *counter += 1;
3264 }
3265 else
3266 info->index = -1;
3267
3268 if (!rtx_locs)
3269 rtx_locs = new hash_map <rtx, file_location>;
3270 rtx_locs->put (k: info->def, v: info->loc);
3271
3272 return true;
3273}
3274
3275/* Return the file location of DEFINE_* rtx X, which was previously
3276 returned by read_md_rtx. */
3277file_location
3278get_file_location (rtx x)
3279{
3280 gcc_assert (rtx_locs);
3281 file_location *entry = rtx_locs->get (k: x);
3282 gcc_assert (entry);
3283 return *entry;
3284}
3285
3286/* Return the number of possible INSN_CODEs. Only meaningful once the
3287 whole file has been processed. */
3288unsigned int
3289get_num_insn_codes ()
3290{
3291 return insn_sequence_num;
3292}
3293
3294/* Return the C test that says whether definition rtx DEF can be used,
3295 or "" if it can be used unconditionally. */
3296
3297const char *
3298get_c_test (rtx x)
3299{
3300 switch (GET_CODE (x))
3301 {
3302 case DEFINE_INSN:
3303 case DEFINE_EXPAND:
3304 case DEFINE_SUBST:
3305 return XSTR (x, 2);
3306
3307 case DEFINE_SPLIT:
3308 case DEFINE_PEEPHOLE:
3309 case DEFINE_PEEPHOLE2:
3310 return XSTR (x, 1);
3311
3312 default:
3313 return "";
3314 }
3315}
3316
3317/* Helper functions for insn elision. */
3318
3319/* Compute a hash function of a c_test structure, which is keyed
3320 by its ->expr field. */
3321hashval_t
3322hash_c_test (const void *x)
3323{
3324 const struct c_test *a = (const struct c_test *) x;
3325 const unsigned char *base, *s = (const unsigned char *) a->expr;
3326 hashval_t hash;
3327 unsigned char c;
3328 unsigned int len;
3329
3330 base = s;
3331 hash = 0;
3332
3333 while ((c = *s++) != '\0')
3334 {
3335 hash += c + (c << 17);
3336 hash ^= hash >> 2;
3337 }
3338
3339 len = s - base;
3340 hash += len + (len << 17);
3341 hash ^= hash >> 2;
3342
3343 return hash;
3344}
3345
3346/* Compare two c_test expression structures. */
3347int
3348cmp_c_test (const void *x, const void *y)
3349{
3350 const struct c_test *a = (const struct c_test *) x;
3351 const struct c_test *b = (const struct c_test *) y;
3352
3353 return !strcmp (s1: a->expr, s2: b->expr);
3354}
3355
3356/* Given a string representing a C test expression, look it up in the
3357 condition_table and report whether or not its value is known
3358 at compile time. Returns a tristate: 1 for known true, 0 for
3359 known false, -1 for unknown. */
3360int
3361maybe_eval_c_test (const char *expr)
3362{
3363 const struct c_test *test;
3364 struct c_test dummy;
3365
3366 if (expr[0] == 0)
3367 return 1;
3368
3369 dummy.expr = expr;
3370 test = (const struct c_test *)htab_find (condition_table, &dummy);
3371 if (!test)
3372 return -1;
3373 return test->value;
3374}
3375
3376/* Record the C test expression EXPR in the condition_table, with
3377 value VAL. Duplicates clobber previous entries. */
3378
3379void
3380add_c_test (const char *expr, int value)
3381{
3382 struct c_test *test;
3383
3384 if (expr[0] == 0)
3385 return;
3386
3387 test = XNEW (struct c_test);
3388 test->expr = expr;
3389 test->value = value;
3390
3391 *(htab_find_slot (condition_table, test, INSERT)) = test;
3392}
3393
3394/* For every C test, call CALLBACK with two arguments: a pointer to
3395 the condition structure and INFO. Stops when CALLBACK returns zero. */
3396void
3397traverse_c_tests (htab_trav callback, void *info)
3398{
3399 if (condition_table)
3400 htab_traverse (condition_table, callback, info);
3401}
3402
3403/* Helper functions for define_predicate and define_special_predicate
3404 processing. Shared between genrecog.cc and genpreds.cc. */
3405
3406static htab_t predicate_table;
3407struct pred_data *first_predicate;
3408static struct pred_data **last_predicate = &first_predicate;
3409
3410static hashval_t
3411hash_struct_pred_data (const void *ptr)
3412{
3413 return htab_hash_string (((const struct pred_data *)ptr)->name);
3414}
3415
3416static int
3417eq_struct_pred_data (const void *a, const void *b)
3418{
3419 return !strcmp (s1: ((const struct pred_data *)a)->name,
3420 s2: ((const struct pred_data *)b)->name);
3421}
3422
3423struct pred_data *
3424lookup_predicate (const char *name)
3425{
3426 struct pred_data key;
3427 key.name = name;
3428 return (struct pred_data *) htab_find (predicate_table, &key);
3429}
3430
3431/* Record that predicate PRED can accept CODE. */
3432
3433void
3434add_predicate_code (struct pred_data *pred, enum rtx_code code)
3435{
3436 if (!pred->codes[code])
3437 {
3438 pred->num_codes++;
3439 pred->codes[code] = true;
3440
3441 if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
3442 pred->allows_non_const = true;
3443
3444 if (code != REG
3445 && code != SUBREG
3446 && code != MEM
3447 && code != CONCAT
3448 && code != PARALLEL
3449 && code != STRICT_LOW_PART
3450 && code != ZERO_EXTRACT
3451 && code != SCRATCH)
3452 pred->allows_non_lvalue = true;
3453
3454 if (pred->num_codes == 1)
3455 pred->singleton = code;
3456 else if (pred->num_codes == 2)
3457 pred->singleton = UNKNOWN;
3458 }
3459}
3460
3461void
3462add_predicate (struct pred_data *pred)
3463{
3464 void **slot = htab_find_slot (predicate_table, pred, INSERT);
3465 if (*slot)
3466 {
3467 error ("duplicate predicate definition for '%s'", pred->name);
3468 return;
3469 }
3470 *slot = pred;
3471 *last_predicate = pred;
3472 last_predicate = &pred->next;
3473}
3474
3475/* This array gives the initial content of the predicate table. It
3476 has entries for all predicates defined in recog.cc. */
3477
3478struct std_pred_table
3479{
3480 const char *name;
3481 bool special;
3482 bool allows_const_p;
3483 RTX_CODE codes[NUM_RTX_CODE];
3484};
3485
3486static const struct std_pred_table std_preds[] = {
3487 {.name: "general_operand", .special: false, .allows_const_p: true, .codes: {SUBREG, REG, MEM}},
3488 {.name: "address_operand", .special: true, .allows_const_p: true, .codes: {SUBREG, REG, MEM, PLUS, MINUS, MULT,
3489 ZERO_EXTEND, SIGN_EXTEND, AND}},
3490 {.name: "register_operand", .special: false, .allows_const_p: false, .codes: {SUBREG, REG}},
3491 {.name: "pmode_register_operand", .special: true, .allows_const_p: false, .codes: {SUBREG, REG}},
3492 {.name: "scratch_operand", .special: false, .allows_const_p: false, .codes: {SCRATCH, REG}},
3493 {.name: "immediate_operand", .special: false, .allows_const_p: true, .codes: {UNKNOWN}},
3494 {.name: "const_int_operand", .special: false, .allows_const_p: false, .codes: {CONST_INT}},
3495#if TARGET_SUPPORTS_WIDE_INT
3496 {.name: "const_scalar_int_operand", .special: false, .allows_const_p: false, .codes: {CONST_INT, CONST_WIDE_INT}},
3497 {.name: "const_double_operand", .special: false, .allows_const_p: false, .codes: {CONST_DOUBLE}},
3498#else
3499 {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
3500#endif
3501 {.name: "nonimmediate_operand", .special: false, .allows_const_p: false, .codes: {SUBREG, REG, MEM}},
3502 {.name: "nonmemory_operand", .special: false, .allows_const_p: true, .codes: {SUBREG, REG}},
3503 {.name: "push_operand", .special: false, .allows_const_p: false, .codes: {MEM}},
3504 {.name: "pop_operand", .special: false, .allows_const_p: false, .codes: {MEM}},
3505 {.name: "memory_operand", .special: false, .allows_const_p: false, .codes: {SUBREG, MEM}},
3506 {.name: "indirect_operand", .special: false, .allows_const_p: false, .codes: {SUBREG, MEM}},
3507 {.name: "ordered_comparison_operator", .special: false, .allows_const_p: false, .codes: {EQ, NE,
3508 LE, LT, GE, GT,
3509 LEU, LTU, GEU, GTU}},
3510 {.name: "comparison_operator", .special: false, .allows_const_p: false, .codes: {EQ, NE,
3511 LE, LT, GE, GT,
3512 LEU, LTU, GEU, GTU,
3513 UNORDERED, ORDERED,
3514 UNEQ, UNGE, UNGT,
3515 UNLE, UNLT, LTGT}}
3516};
3517#define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
3518
3519/* Initialize the table of predicate definitions, starting with
3520 the information we have on generic predicates. */
3521
3522static void
3523init_predicate_table (void)
3524{
3525 size_t i, j;
3526 struct pred_data *pred;
3527
3528 predicate_table = htab_create_alloc (37, hash_struct_pred_data,
3529 eq_struct_pred_data, 0,
3530 xcalloc, free);
3531
3532 for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
3533 {
3534 pred = XCNEW (struct pred_data);
3535 pred->name = std_preds[i].name;
3536 pred->special = std_preds[i].special;
3537
3538 for (j = 0; std_preds[i].codes[j] != 0; j++)
3539 add_predicate_code (pred, code: std_preds[i].codes[j]);
3540
3541 if (std_preds[i].allows_const_p)
3542 for (j = 0; j < NUM_RTX_CODE; j++)
3543 if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
3544 add_predicate_code (pred, code: (enum rtx_code) j);
3545
3546 add_predicate (pred);
3547 }
3548}
3549
3550/* These functions allow linkage with print-rtl.cc. Also, some generators
3551 like to annotate their output with insn names. */
3552
3553/* Holds an array of names indexed by insn_code_number. */
3554static char **insn_name_ptr = 0;
3555static int insn_name_ptr_size = 0;
3556
3557const char *
3558get_insn_name (int code)
3559{
3560 if (code < insn_name_ptr_size)
3561 return insn_name_ptr[code];
3562 else
3563 return NULL;
3564}
3565
3566static void
3567record_insn_name (int code, const char *name)
3568{
3569 static const char *last_real_name = "insn";
3570 static int last_real_code = 0;
3571 char *new_name;
3572
3573 if (insn_name_ptr_size <= code)
3574 {
3575 int new_size;
3576 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
3577 insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
3578 memset (s: insn_name_ptr + insn_name_ptr_size, c: 0,
3579 n: sizeof (char *) * (new_size - insn_name_ptr_size));
3580 insn_name_ptr_size = new_size;
3581 }
3582
3583 if (!name || name[0] == '\0')
3584 {
3585 new_name = XNEWVAR (char, strlen (last_real_name) + 10);
3586 sprintf (s: new_name, format: "%s+%d", last_real_name, code - last_real_code);
3587 }
3588 else
3589 {
3590 last_real_name = new_name = xstrdup (name);
3591 last_real_code = code;
3592 }
3593
3594 insn_name_ptr[code] = new_name;
3595}
3596
3597/* Make STATS describe the operands that appear in rtx X. */
3598
3599static void
3600get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
3601{
3602 RTX_CODE code;
3603 int i;
3604 int len;
3605 const char *fmt;
3606
3607 if (x == NULL_RTX)
3608 return;
3609
3610 code = GET_CODE (x);
3611 switch (code)
3612 {
3613 case MATCH_OPERAND:
3614 case MATCH_OPERATOR:
3615 case MATCH_PARALLEL:
3616 stats->max_opno = MAX (stats->max_opno, XINT (x, 0));
3617 break;
3618
3619 case MATCH_DUP:
3620 case MATCH_OP_DUP:
3621 case MATCH_PAR_DUP:
3622 stats->num_dups++;
3623 stats->max_dup_opno = MAX (stats->max_dup_opno, XINT (x, 0));
3624 break;
3625
3626 case MATCH_SCRATCH:
3627 if (stats->min_scratch_opno == -1)
3628 stats->min_scratch_opno = XINT (x, 0);
3629 else
3630 stats->min_scratch_opno = MIN (stats->min_scratch_opno, XINT (x, 0));
3631 stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
3632 break;
3633
3634 default:
3635 break;
3636 }
3637
3638 fmt = GET_RTX_FORMAT (code);
3639 len = GET_RTX_LENGTH (code);
3640 for (i = 0; i < len; i++)
3641 {
3642 if (fmt[i] == 'e' || fmt[i] == 'u')
3643 get_pattern_stats_1 (stats, XEXP (x, i));
3644 else if (fmt[i] == 'E')
3645 {
3646 int j;
3647 for (j = 0; j < XVECLEN (x, i); j++)
3648 get_pattern_stats_1 (stats, XVECEXP (x, i, j));
3649 }
3650 }
3651}
3652
3653/* Make STATS describe the operands that appear in instruction pattern
3654 PATTERN. */
3655
3656void
3657get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
3658{
3659 int i, len;
3660
3661 stats->max_opno = -1;
3662 stats->max_dup_opno = -1;
3663 stats->min_scratch_opno = -1;
3664 stats->max_scratch_opno = -1;
3665 stats->num_dups = 0;
3666
3667 len = GET_NUM_ELEM (pattern);
3668 for (i = 0; i < len; i++)
3669 get_pattern_stats_1 (stats, RTVEC_ELT (pattern, i));
3670
3671 stats->num_generator_args = stats->max_opno + 1;
3672 stats->num_insn_operands = MAX (stats->max_opno,
3673 stats->max_scratch_opno) + 1;
3674 stats->num_operand_vars = MAX (stats->max_opno,
3675 MAX (stats->max_dup_opno,
3676 stats->max_scratch_opno)) + 1;
3677}
3678
3679/* Return the emit_* function that should be used for pattern X, or NULL
3680 if we can't pick a particular type at compile time and should instead
3681 fall back to "emit". */
3682
3683const char *
3684get_emit_function (rtx x)
3685{
3686 switch (classify_insn (x))
3687 {
3688 case INSN:
3689 return "emit_insn";
3690
3691 case CALL_INSN:
3692 return "emit_call_insn";
3693
3694 case JUMP_INSN:
3695 return "emit_jump_insn";
3696
3697 case UNKNOWN:
3698 return NULL;
3699
3700 default:
3701 gcc_unreachable ();
3702 }
3703}
3704
3705/* Return true if we must emit a barrier after pattern X. */
3706
3707bool
3708needs_barrier_p (rtx x)
3709{
3710 return (GET_CODE (x) == SET
3711 && GET_CODE (SET_DEST (x)) == PC
3712 && GET_CODE (SET_SRC (x)) == LABEL_REF);
3713}
3714
3715#define NS "NULL"
3716#define ZS "'\\0'"
3717#define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
3718#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
3719#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
3720#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
3721#define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 },
3722#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3723#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
3724#define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
3725#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3726#define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 },
3727#define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
3728
3729/* An array of all optabs. Note that the same optab can appear more
3730 than once, with a different pattern. */
3731optab_def optabs[] = {
3732 { .name: "unknown_optab", NULL, NS, ZS, NS, .op: unknown_optab, .fcode: UNKNOWN, .rcode: UNKNOWN, .kind: 0 },
3733#include "optabs.def"
3734};
3735
3736/* The number of entries in optabs[]. */
3737unsigned int num_optabs = ARRAY_SIZE (optabs);
3738
3739#undef OPTAB_CL
3740#undef OPTAB_CX
3741#undef OPTAB_CD
3742#undef OPTAB_NL
3743#undef OPTAB_NC
3744#undef OPTAB_NX
3745#undef OPTAB_VL
3746#undef OPTAB_VC
3747#undef OPTAB_VX
3748#undef OPTAB_DC
3749#undef OPTAB_D
3750
3751/* Return true if instruction NAME matches pattern PAT, storing information
3752 about the match in P if so. */
3753
3754static bool
3755match_pattern (optab_pattern *p, const char *name, const char *pat)
3756{
3757 bool force_float = false;
3758 bool force_int = false;
3759 bool force_partial_int = false;
3760 bool force_fixed = false;
3761
3762 if (pat == NULL)
3763 return false;
3764 for (; ; ++pat)
3765 {
3766 if (*pat != '$')
3767 {
3768 if (*pat != *name++)
3769 return false;
3770 if (*pat == '\0')
3771 return true;
3772 continue;
3773 }
3774 switch (*++pat)
3775 {
3776 case 'I':
3777 force_int = 1;
3778 break;
3779 case 'P':
3780 force_partial_int = 1;
3781 break;
3782 case 'F':
3783 force_float = 1;
3784 break;
3785 case 'Q':
3786 force_fixed = 1;
3787 break;
3788
3789 case 'a':
3790 case 'b':
3791 {
3792 int i;
3793
3794 /* This loop will stop at the first prefix match, so
3795 look through the modes in reverse order, in case
3796 there are extra CC modes and CC is a prefix of the
3797 CC modes (as it should be). */
3798 for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
3799 {
3800 const char *p, *q;
3801 for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
3802 if (TOLOWER (*p) != *q)
3803 break;
3804 if (*p == 0
3805 && (! force_int || mode_class[i] == MODE_INT
3806 || mode_class[i] == MODE_VECTOR_INT)
3807 && (! force_partial_int
3808 || mode_class[i] == MODE_INT
3809 || mode_class[i] == MODE_PARTIAL_INT
3810 || mode_class[i] == MODE_VECTOR_INT)
3811 && (! force_float
3812 || mode_class[i] == MODE_FLOAT
3813 || mode_class[i] == MODE_DECIMAL_FLOAT
3814 || mode_class[i] == MODE_COMPLEX_FLOAT
3815 || mode_class[i] == MODE_VECTOR_FLOAT)
3816 && (! force_fixed
3817 || mode_class[i] == MODE_FRACT
3818 || mode_class[i] == MODE_UFRACT
3819 || mode_class[i] == MODE_ACCUM
3820 || mode_class[i] == MODE_UACCUM
3821 || mode_class[i] == MODE_VECTOR_FRACT
3822 || mode_class[i] == MODE_VECTOR_UFRACT
3823 || mode_class[i] == MODE_VECTOR_ACCUM
3824 || mode_class[i] == MODE_VECTOR_UACCUM))
3825 break;
3826 }
3827
3828 if (i < 0)
3829 return false;
3830 name += strlen (GET_MODE_NAME (i));
3831 if (*pat == 'a')
3832 p->m1 = i;
3833 else
3834 p->m2 = i;
3835
3836 force_int = false;
3837 force_partial_int = false;
3838 force_float = false;
3839 force_fixed = false;
3840 }
3841 break;
3842
3843 default:
3844 gcc_unreachable ();
3845 }
3846 }
3847}
3848
3849/* Return true if NAME is the name of an optab, describing it in P if so. */
3850
3851bool
3852find_optab (optab_pattern *p, const char *name)
3853{
3854 if (*name == 0 || *name == '*')
3855 return false;
3856
3857 /* See if NAME matches one of the patterns we have for the optabs
3858 we know about. */
3859 for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
3860 {
3861 p->m1 = p->m2 = 0;
3862 if (match_pattern (p, name, pat: optabs[pindex].pattern))
3863 {
3864 p->name = name;
3865 p->op = optabs[pindex].op;
3866 p->sort_num = (p->op << 20) | (p->m2 << 10) | p->m1;
3867 return true;
3868 }
3869 }
3870 return false;
3871}
3872

source code of gcc/gensupport.cc