AVR: Provide built-ins for strlen where the string lives in some AS.
[gcc.git] / gcc / gensupport.cc
blob80f1976faf1d7ffa714fdb61b8595774e43234ce
1 /* Support routines for the various generation passes.
2 Copyright (C) 2000-2025 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
33 #define MAX_OPERANDS 40
35 static rtx operand_data[MAX_OPERANDS];
36 static rtx match_operand_entries_in_pattern[MAX_OPERANDS];
37 static char used_operands_numbers[MAX_OPERANDS];
38 /* List of entries which are part of the new syntax. */
39 hash_set<rtx> compact_syntax;
42 /* In case some macros used by files we include need it, define this here. */
43 int target_flags;
45 int insn_elision = 1;
47 static struct obstack obstack;
48 struct obstack *rtl_obstack = &obstack;
50 /* Counter for named patterns and INSN_CODEs. */
51 static int insn_sequence_num;
53 /* Counter for define_splits. */
54 static int split_sequence_num;
56 /* Counter for define_peephole2s. */
57 static int peephole2_sequence_num;
59 static int predicable_default;
60 static const char *predicable_true;
61 static const char *predicable_false;
63 static const char *subst_true = "yes";
64 static const char *subst_false = "no";
66 static htab_t condition_table;
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. */
72 class queue_elem
74 public:
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;
83 #define MNEMONIC_ATTR_NAME "mnemonic"
84 #define MNEMONIC_HTAB_SIZE 1024
86 static class queue_elem *define_attr_queue;
87 static class queue_elem **define_attr_tail = &define_attr_queue;
88 static class queue_elem *define_pred_queue;
89 static class queue_elem **define_pred_tail = &define_pred_queue;
90 static class queue_elem *define_insn_queue;
91 static class queue_elem **define_insn_tail = &define_insn_queue;
92 static class queue_elem *define_cond_exec_queue;
93 static class queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
94 static class queue_elem *define_subst_queue;
95 static class queue_elem **define_subst_tail = &define_subst_queue;
96 static class queue_elem *other_queue;
97 static class queue_elem **other_tail = &other_queue;
98 static class queue_elem *define_subst_attr_queue;
99 static class queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
101 /* Mapping from DEFINE_* rtxes to their location in the source file. */
102 static hash_map <rtx, file_location> *rtx_locs;
104 static void remove_constraints (rtx);
106 static int is_predicable (class queue_elem *);
107 static void identify_predicable_attribute (void);
108 static int n_alternatives (const char *);
109 static void collect_insn_data (rtx, int *, int *);
110 static const char *alter_test_for_insn (class queue_elem *,
111 class queue_elem *);
112 static char *shift_output_template (char *, const char *, int);
113 static const char *alter_output_for_insn (class queue_elem *,
114 class queue_elem *,
115 int, int);
116 static void process_one_cond_exec (class queue_elem *);
117 static void process_define_cond_exec (void);
118 static void init_predicate_table (void);
119 static void record_insn_name (int, const char *);
121 static bool has_subst_attribute (class queue_elem *, class queue_elem *);
122 static const char * alter_output_for_subst_insn (rtx, int);
123 static void alter_attrs_for_subst_insn (class queue_elem *, int);
124 static void process_substs_on_one_elem (class queue_elem *,
125 class queue_elem *);
126 static rtx subst_dup (rtx, int, int);
127 static void process_define_subst (void);
129 static const char * duplicate_alternatives (const char *, int);
130 static const char * duplicate_each_alternative (const char * str, int n_dup);
132 typedef const char * (*constraints_handler_t) (const char *, int);
133 static rtx alter_constraints (rtx, int, constraints_handler_t);
134 static rtx adjust_operands_numbers (rtx);
135 static rtx replace_duplicating_operands_in_pattern (rtx);
137 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
138 the gensupport programs. */
141 gen_rtx_CONST_INT (machine_mode ARG_UNUSED (mode),
142 HOST_WIDE_INT arg)
144 rtx rt = rtx_alloc (CONST_INT);
146 XWINT (rt, 0) = arg;
147 return rt;
150 /* Return the rtx pattern specified by the list of rtxes in a
151 define_insn or define_split. */
154 add_implicit_parallel (rtvec vec)
156 if (GET_NUM_ELEM (vec) == 1)
157 return RTVEC_ELT (vec, 0);
158 else
160 rtx pattern = rtx_alloc (PARALLEL);
161 XVEC (pattern, 0) = vec;
162 return pattern;
166 /* Predicate handling.
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.
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.
180 validate_pattern will warn about predicates that allow non-lvalues
181 when they appear in destination operands.
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.
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
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. */
202 #define N 0
203 #define Y 1
204 #define I 2
206 #define TRISTATE_AND(a,b) \
207 ((a) == I ? ((b) == N ? N : I) : \
208 (b) == I ? ((a) == N ? N : I) : \
209 (a) && (b))
211 #define TRISTATE_OR(a,b) \
212 ((a) == I ? ((b) == Y ? Y : I) : \
213 (b) == I ? ((a) == Y ? Y : I) : \
214 (a) || (b))
216 #define TRISTATE_NOT(a) \
217 ((a) == I ? I : !(a))
219 /* 0 means no warning about that code yet, 1 means warned. */
220 static char did_you_mean_codes[NUM_RTX_CODE];
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. */
226 void
227 compute_test_codes (rtx exp, file_location loc, char *codes)
229 char op0_codes[NUM_RTX_CODE];
230 char op1_codes[NUM_RTX_CODE];
231 char op2_codes[NUM_RTX_CODE];
232 int i;
234 switch (GET_CODE (exp))
236 case AND:
237 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
238 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
239 for (i = 0; i < NUM_RTX_CODE; i++)
240 codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
241 break;
243 case IOR:
244 compute_test_codes (XEXP (exp, 0), loc, op0_codes);
245 compute_test_codes (XEXP (exp, 1), loc, 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, op0_codes);
251 for (i = 0; i < NUM_RTX_CODE; i++)
252 codes[i] = TRISTATE_NOT (op0_codes[i]);
253 break;
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, op0_codes);
258 compute_test_codes (XEXP (exp, 1), loc, op1_codes);
259 compute_test_codes (XEXP (exp, 2), loc, 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;
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')
272 memset (codes, Y, NUM_RTX_CODE);
273 break;
276 memset (codes, N, NUM_RTX_CODE);
278 const char *next_code = XSTR (exp, 0);
279 const char *code;
281 if (*next_code == '\0')
283 error_at (loc, "empty match_code expression");
284 break;
287 while ((code = scan_comma_elt (&next_code)) != 0)
289 size_t n = next_code - code;
290 int found_it = 0;
292 for (i = 0; i < NUM_RTX_CODE; i++)
293 if (!strncmp (code, GET_RTX_NAME (i), n)
294 && GET_RTX_NAME (i)[n] == '\0')
296 codes[i] = Y;
297 found_it = 1;
298 break;
300 if (!found_it)
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 (code, GET_RTX_NAME (i), n)
306 && GET_RTX_NAME (i)[n] == '\0'
307 && !did_you_mean_codes[i])
309 did_you_mean_codes[i] = 1;
310 message_at (loc, "(did you mean \"%s\"?)",
311 GET_RTX_NAME (i));
316 break;
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. */
322 struct pred_data *p = lookup_predicate (XSTR (exp, 1));
323 if (!p)
325 error_at (loc, "reference to unknown predicate '%s'",
326 XSTR (exp, 1));
327 break;
329 for (i = 0; i < NUM_RTX_CODE; i++)
330 codes[i] = p->codes[i] ? I : N;
332 break;
335 case MATCH_TEST:
336 /* (match_test WHATEVER) is completely indeterminate. */
337 memset (codes, I, NUM_RTX_CODE);
338 break;
340 default:
341 error_at (loc, "'%s' cannot be used in predicates or constraints",
342 GET_RTX_NAME (GET_CODE (exp)));
343 memset (codes, I, NUM_RTX_CODE);
344 break;
348 #undef TRISTATE_OR
349 #undef TRISTATE_AND
350 #undef TRISTATE_NOT
352 /* Return true if NAME is a valid predicate name. */
354 static bool
355 valid_predicate_name_p (const char *name)
357 const char *p;
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;
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. */
371 static void
372 process_define_predicate (rtx desc, file_location loc)
374 struct pred_data *pred;
375 char codes[NUM_RTX_CODE];
376 int i;
378 if (!valid_predicate_name_p (XSTR (desc, 0)))
380 error_at (loc, "%s: predicate name must be a valid C function name",
381 XSTR (desc, 0));
382 return;
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;
392 compute_test_codes (XEXP (desc, 1), loc, codes);
394 for (i = 0; i < NUM_RTX_CODE; i++)
395 if (codes[i] != N)
396 add_predicate_code (pred, (enum rtx_code) i);
398 add_predicate (pred);
400 #undef I
401 #undef N
402 #undef Y
404 /* Maps register filter conditions to the associated filter identifier. */
405 static hash_map<nofree_string_hash, unsigned int> register_filter_map;
407 /* All register filter conditions, indexed by identifier. */
408 vec<const char *> register_filters;
410 /* Return the unique identifier for filter condition FILTER. Identifiers
411 are assigned automatically when the define_register_constraint is
412 parsed. */
414 unsigned int
415 get_register_filter_id (const char *filter)
417 unsigned int *slot = register_filter_map.get (filter);
418 gcc_assert (slot);
419 return *slot;
422 /* Process define_register_constraint directive DESC, at location LOC. */
424 static void
425 process_define_register_constraint (rtx desc, file_location loc)
427 /* Assign identifiers to each unique register filter condition. */
428 if (const char *filter = XSTR (desc, 3))
430 bool existed = false;
431 unsigned int &id = register_filter_map.get_or_insert (filter, &existed);
432 if (!existed)
434 id = register_filters.length ();
435 if (id == 32)
436 fatal_at (loc, "too many distinct register filters, maximum"
437 " is 32");
438 register_filters.safe_push (filter);
443 /* Queue PATTERN on LIST_TAIL. Return the address of the new queue
444 element. */
446 static class queue_elem *
447 queue_pattern (rtx pattern, class queue_elem ***list_tail,
448 file_location loc)
450 class queue_elem *e = XNEW (class queue_elem);
451 e->data = pattern;
452 e->loc = loc;
453 e->next = NULL;
454 e->split = NULL;
455 **list_tail = e;
456 *list_tail = &e->next;
457 return e;
460 /* Remove element ELEM from QUEUE. */
461 static void
462 remove_from_queue (class queue_elem *elem, class queue_elem **queue)
464 class queue_elem *prev, *e;
465 prev = NULL;
466 for (e = *queue; e ; e = e->next)
468 if (e == elem)
469 break;
470 prev = e;
472 if (e == NULL)
473 return;
475 if (prev)
476 prev->next = elem->next;
477 else
478 *queue = elem->next;
481 /* Build a define_attr for an binary attribute with name NAME and
482 possible values "yes" and "no", and queue it. */
483 static void
484 add_define_attr (const char *name)
486 class queue_elem *e = XNEW (class queue_elem);
487 rtx t1 = rtx_alloc (DEFINE_ATTR);
488 XSTR (t1, 0) = name;
489 XSTR (t1, 1) = "no,yes";
490 XEXP (t1, 2) = rtx_alloc (CONST_STRING);
491 XSTR (XEXP (t1, 2), 0) = "yes";
492 e->data = t1;
493 e->loc = file_location ("built-in", -1, -1);
494 e->next = define_attr_queue;
495 define_attr_queue = e;
499 /* Recursively remove constraints from an rtx. */
501 static void
502 remove_constraints (rtx part)
504 int i, j;
505 const char *format_ptr;
507 if (part == 0)
508 return;
510 if (GET_CODE (part) == MATCH_OPERAND)
511 XSTR (part, 2) = "";
512 else if (GET_CODE (part) == MATCH_SCRATCH)
513 XSTR (part, 1) = "";
515 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
517 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
518 switch (*format_ptr++)
520 case 'e':
521 case 'u':
522 remove_constraints (XEXP (part, i));
523 break;
524 case 'E':
525 if (XVEC (part, i) != NULL)
526 for (j = 0; j < XVECLEN (part, i); j++)
527 remove_constraints (XVECEXP (part, i, j));
528 break;
532 /* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs
533 with MATCH_OP_DUPs in X. */
535 static rtx
536 replace_operands_with_dups (rtx x)
538 if (x == 0)
539 return x;
541 rtx newx;
542 if (GET_CODE (x) == MATCH_OPERAND)
544 newx = rtx_alloc (MATCH_DUP);
545 XINT (newx, 0) = XINT (x, 0);
546 x = newx;
548 else if (GET_CODE (x) == MATCH_OPERATOR)
550 newx = rtx_alloc (MATCH_OP_DUP);
551 XINT (newx, 0) = XINT (x, 0);
552 XVEC (newx, 1) = XVEC (x, 2);
553 x = newx;
555 else
556 newx = shallow_copy_rtx (x);
558 const char *format_ptr = GET_RTX_FORMAT (GET_CODE (x));
559 for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
560 switch (*format_ptr++)
562 case 'e':
563 case 'u':
564 XEXP (newx, i) = replace_operands_with_dups (XEXP (x, i));
565 break;
566 case 'E':
567 if (XVEC (x, i) != NULL)
569 XVEC (newx, i) = rtvec_alloc (XVECLEN (x, i));
570 for (int j = 0; j < XVECLEN (x, i); j++)
571 XVECEXP (newx, i, j)
572 = replace_operands_with_dups (XVECEXP (x, i, j));
574 break;
576 return newx;
579 /* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into
580 a sequence that should be generated by the splitter. */
582 static rtvec
583 gen_rewrite_sequence (rtvec vec)
585 rtvec new_vec = rtvec_alloc (1);
586 rtx x = add_implicit_parallel (vec);
587 RTVEC_ELT (new_vec, 0) = replace_operands_with_dups (x);
588 return new_vec;
591 /* The following is for handling the compact syntax for constraints and
592 attributes.
594 The normal syntax looks like this:
597 (match_operand: 0 "s_register_operand" "r,I,k")
598 (match_operand: 2 "s_register_operand" "r,k,I")
601 <asm>
602 <asm>
603 <asm>"
605 (set_attr "length" "4,8,8")
607 The compact syntax looks like this:
610 (match_operand: 0 "s_register_operand")
611 (match_operand: 2 "s_register_operand")
613 {@ [cons: 0, 2; attrs: length]
614 [r,r; 4] <asm>
615 [I,k; 8] <asm>
616 [k,I; 8] <asm>
619 [<other attributes>]
621 This is the only place where this syntax needs to be handled. Relevant
622 patterns are transformed from compact to the normal syntax before they are
623 queued, so none of the gen* programs need to know about this syntax at all.
625 Conversion process (convert_syntax):
627 0) Check that pattern actually uses new syntax (check for {@ ... }).
629 1) Get the "layout", i.e. the "[cons: 0 2; attrs: length]" from the above
630 example. cons must come first; both are optional. Set up two vecs,
631 convec and attrvec, for holding the results of the transformation.
633 2) For each alternative: parse the list of constraints and/or attributes,
634 and enqueue them in the relevant lists in convec and attrvec. By the end
635 of this process, convec[N].con and attrvec[N].con should contain regular
636 syntax constraint/attribute lists like "r,I,k". Copy the asm to a string
637 as we go.
639 3) Search the rtx and write the constraint and attribute lists into the
640 correct places. Write the asm back into the template. */
642 /* Helper class for shuffling constraints/attributes in convert_syntax and
643 add_constraints/add_attributes. This includes commas but not whitespace. */
645 class conlist {
646 private:
647 std::string con;
649 public:
650 std::string name;
651 int idx = -1;
653 conlist () = default;
655 /* [ns..ns + len) should be a string with the id of the rtx to match
656 i.e. if rtx is the relevant match_operand or match_scratch then
657 [ns..ns + len) should equal itoa (XINT (rtx, 0)), and if set_attr then
658 [ns..ns + len) should equal XSTR (rtx, 0). */
659 conlist (const char *ns, unsigned int len, bool numeric)
661 /* Trim leading whitespaces. */
662 while (len > 0 && ISBLANK (*ns))
664 ns++;
665 len--;
668 /* Trim trailing whitespace. */
669 for (int i = len - 1; i >= 0; i--, len--)
670 if (!ISBLANK (ns[i]))
671 break;
673 /* Parse off any modifiers. */
674 while (len > 0 && !ISALNUM (*ns))
676 con += *(ns++);
677 len--;
680 name.assign (ns, len);
681 if (numeric)
682 idx = strtol (name.c_str (), (char **)NULL, 10);
685 /* Adds a character to the end of the string. */
686 void add (char c)
688 con += c;
691 /* Output the string in the form of a brand-new char *, then effectively
692 clear the internal string by resetting len to 0. */
693 char *out ()
695 /* Final character is always a trailing comma, so strip it out. */
696 char *q = xstrndup (con.c_str (), con.size () - 1);
697 con.clear ();
698 return q;
702 typedef std::vector<conlist> vec_conlist;
704 /* Add constraints to an rtx. This function is similar to remove_constraints.
705 Errors if adding the constraints would overwrite existing constraints. */
707 static void
708 add_constraints (rtx part, file_location loc, vec_conlist &cons)
710 const char *format_ptr;
712 if (part == NULL_RTX)
713 return;
715 /* If match_op or match_scr, check if we have the right one, and if so, copy
716 over the constraint list. */
717 if (GET_CODE (part) == MATCH_OPERAND || GET_CODE (part) == MATCH_SCRATCH)
719 int field = GET_CODE (part) == MATCH_OPERAND ? 2 : 1;
720 unsigned id = XINT (part, 0);
722 if (id >= cons.size () || cons[id].idx == -1)
723 return;
725 if (XSTR (part, field)[0] != '\0')
727 error_at (loc, "can't mix normal and compact constraint syntax");
728 return;
730 XSTR (part, field) = cons[id].out ();
731 cons[id].idx = -1;
734 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
736 /* Recursively search the rtx. */
737 for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
738 switch (*format_ptr++)
740 case 'e':
741 case 'u':
742 add_constraints (XEXP (part, i), loc, cons);
743 break;
744 case 'E':
745 if (XVEC (part, i) != NULL)
746 for (int j = 0; j < XVECLEN (part, i); j++)
747 add_constraints (XVECEXP (part, i, j), loc, cons);
748 break;
749 default:
750 continue;
754 /* Add ATTRS to definition X's attribute list. */
756 static void
757 add_attributes (rtx x, vec_conlist &attrs)
759 unsigned int attr_index = GET_CODE (x) == DEFINE_INSN ? 4 : 3;
760 rtvec orig = XVEC (x, attr_index);
761 if (orig)
763 size_t n_curr = XVECLEN (x, attr_index);
764 rtvec copy = rtvec_alloc (n_curr + attrs.size ());
766 /* Create a shallow copy of existing entries. */
767 memcpy (&copy->elem[attrs.size ()], &orig->elem[0],
768 sizeof (rtx) * n_curr);
769 XVEC (x, attr_index) = copy;
771 else
772 XVEC (x, attr_index) = rtvec_alloc (attrs.size ());
774 /* Create the new elements. */
775 for (unsigned i = 0; i < attrs.size (); i++)
777 rtx attr = rtx_alloc (SET_ATTR);
778 XSTR (attr, 0) = xstrdup (attrs[i].name.c_str ());
779 XSTR (attr, 1) = attrs[i].out ();
780 XVECEXP (x, attr_index, i) = attr;
784 /* Consumes spaces and tabs. */
786 static inline void
787 skip_spaces (const char **str)
789 while (ISBLANK (**str))
790 (*str)++;
793 /* Consumes the given character, if it's there. */
795 static inline bool
796 expect_char (const char **str, char c)
798 if (**str != c)
799 return false;
800 (*str)++;
801 return true;
804 /* Parses the section layout that follows a "{@" if using new syntax. Builds
805 a vector for a single section. E.g. if we have "attrs: length, arch]..."
806 then list will have two elements, the first for "length" and the second
807 for "arch". */
809 static void
810 parse_section_layout (file_location loc, const char **templ, const char *label,
811 vec_conlist &list, bool numeric)
813 const char *name_start;
814 size_t label_len = strlen (label);
815 if (strncmp (label, *templ, label_len) == 0)
817 *templ += label_len;
819 /* Gather the names. */
820 while (**templ != ';' && **templ != ']')
822 skip_spaces (templ);
823 name_start = *templ;
824 int len = 0;
825 char val = (*templ)[len];
826 while (val != ',' && val != ';' && val != ']')
828 if (val == 0 || val == '\n')
829 fatal_at (loc, "missing ']'");
830 val = (*templ)[++len];
832 *templ += len;
833 if (val == ',')
834 (*templ)++;
835 list.push_back (conlist (name_start, len, numeric));
840 /* Parse a section, a section is defined as a named space separated list, e.g.
842 foo: a, b, c
844 is a section named "foo" with entries a, b and c. */
846 static void
847 parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no,
848 vec_conlist &list, file_location loc, const char *name)
850 unsigned int i;
852 /* Go through the list, one character at a time, adding said character
853 to the correct string. */
854 for (i = 0; **templ != ']' && **templ != ';'; (*templ)++)
855 if (!ISBLANK (**templ))
857 if (**templ == 0 || **templ == '\n')
858 fatal_at (loc, "missing ']'");
859 list[i].add (**templ);
860 if (**templ == ',')
862 ++i;
863 if (i == n_elems)
864 fatal_at (loc, "too many %ss in alternative %d: expected %d",
865 name, alt_no, n_elems);
869 if (i + 1 < n_elems)
870 fatal_at (loc, "too few %ss in alternative %d: expected %d, got %d",
871 name, alt_no, n_elems, i);
873 list[i].add (',');
876 /* The compact syntax has more convience syntaxes. As such we post process
877 the lines to get them back to something the normal syntax understands. */
879 static void
880 preprocess_compact_syntax (file_location loc, int alt_no, std::string &line,
881 std::string &last_line)
883 /* Check if we're copying the last statement. */
884 if (line.find ("^") == 0 && line.size () == 1)
886 if (last_line.empty ())
887 fatal_at (loc, "found instruction to copy previous line (^) in"
888 "alternative %d but no previous line to copy", alt_no);
889 line = last_line;
890 return;
893 std::string result;
894 std::string buffer;
895 /* Check if we have << which means return c statement. */
896 if (line.find ("<<") == 0)
898 result.append ("* return ");
899 const char *chunk = line.c_str () + 2;
900 skip_spaces (&chunk);
901 result.append (chunk);
903 else
904 result.append (line);
906 line = result;
907 return;
910 /* Converts an rtx from compact syntax to normal syntax if possible. */
912 static void
913 convert_syntax (rtx x, file_location loc)
915 int alt_no;
916 unsigned int templ_index;
917 const char *templ;
918 vec_conlist tconvec, convec, attrvec;
920 templ_index = 3;
921 gcc_assert (GET_CODE (x) == DEFINE_INSN);
923 templ = XTMPL (x, templ_index);
925 /* Templates with constraints start with "{@". */
926 if (strncmp ("*{@", templ, 3))
927 return;
929 /* Get the layout for the template. */
930 templ += 3;
931 skip_spaces (&templ);
933 if (!expect_char (&templ, '['))
934 fatal_at (loc, "expecing `[' to begin section list");
936 skip_spaces (&templ);
938 parse_section_layout (loc, &templ, "cons:", tconvec, true);
940 if (*templ != ']')
942 if (*templ == ';')
943 skip_spaces (&(++templ));
944 parse_section_layout (loc, &templ, "attrs:", attrvec, false);
947 if (!expect_char (&templ, ']'))
948 fatal_at (loc, "expecting `]` to end section list - section list must have "
949 "cons first, attrs second");
951 /* We will write the un-constrainified template into new_templ. */
952 std::string new_templ;
953 new_templ.append ("@");
955 /* Skip to the first proper line. */
956 skip_spaces (&templ);
957 if (*templ == 0)
958 fatal_at (loc, "'{@...}' blocks must have at least one alternative");
959 if (*templ != '\n')
960 fatal_at (loc, "unexpected character '%c' after ']'", *templ);
961 templ++;
963 alt_no = 0;
964 std::string last_line;
966 /* Process the alternatives. */
967 while (*(templ - 1) != '\0')
969 /* Skip leading whitespace. */
970 std::string buffer;
971 skip_spaces (&templ);
973 /* Check if we're at the end. */
974 if (templ[0] == '}' && templ[1] == '\0')
975 break;
977 if (expect_char (&templ, '['))
979 new_templ += '\n';
980 new_templ.append (buffer);
981 /* Parse the constraint list, then the attribute list. */
982 if (tconvec.size () > 0)
983 parse_section (&templ, tconvec.size (), alt_no, tconvec, loc,
984 "constraint");
986 if (attrvec.size () > 0)
988 if (tconvec.size () > 0 && !expect_char (&templ, ';'))
989 fatal_at (loc, "expected `;' to separate constraints "
990 "and attributes in alternative %d", alt_no);
992 parse_section (&templ, attrvec.size (), alt_no,
993 attrvec, loc, "attribute");
996 if (!expect_char (&templ, ']'))
997 fatal_at (loc, "expected end of constraint/attribute list but "
998 "missing an ending `]' in alternative %d", alt_no);
1000 else if (templ[0] == '/' && templ[1] == '/')
1002 templ += 2;
1003 /* Glob till newline or end of string. */
1004 while (*templ != '\n' || *templ != '\0')
1005 templ++;
1007 /* Skip any newlines or whitespaces needed. */
1008 while (ISSPACE(*templ))
1009 templ++;
1010 continue;
1012 else if (templ[0] == '/' && templ[1] == '*')
1014 templ += 2;
1015 /* Glob till newline or end of multiline comment. */
1016 while (templ[0] != 0 && templ[0] != '*' && templ[1] != '/')
1017 templ++;
1019 while (templ[0] != '*' || templ[1] != '/')
1021 if (templ[0] == 0)
1022 fatal_at (loc, "unterminated '/*'");
1023 templ++;
1025 templ += 2;
1027 /* Skip any newlines or whitespaces needed. */
1028 while (ISSPACE(*templ))
1029 templ++;
1030 continue;
1032 else
1033 fatal_at (loc, "expected constraint/attribute list at beginning of "
1034 "alternative %d but missing a starting `['", alt_no);
1036 /* Skip whitespace between list and asm. */
1037 skip_spaces (&templ);
1039 /* Copy asm to new template. */
1040 std::string line;
1041 while (*templ != '\n' && *templ != '\0')
1042 line += *templ++;
1044 /* Apply any pre-processing needed to the line. */
1045 preprocess_compact_syntax (loc, alt_no, line, last_line);
1046 new_templ.append (line);
1047 last_line = line;
1049 /* Normal "*..." syntax expects the closing quote to be on the final
1050 line of asm, whereas we allow the closing "}" to be on its own line.
1051 Postpone copying the '\n' until we know that there is another
1052 alternative in the list. */
1053 while (ISSPACE (*templ))
1054 templ++;
1055 ++alt_no;
1058 /* Check for any duplicate cons entries and sort based on i. */
1059 for (auto e : tconvec)
1061 unsigned idx = e.idx;
1062 if (idx >= convec.size ())
1063 convec.resize (idx + 1);
1065 if (convec[idx].idx >= 0)
1066 fatal_at (loc, "duplicate cons number found: %d", idx);
1067 convec[idx] = e;
1069 tconvec.clear ();
1071 /* Write the constraints and attributes into their proper places. */
1072 if (convec.size () > 0)
1073 add_constraints (x, loc, convec);
1075 if (attrvec.size () > 0)
1076 add_attributes (x, attrvec);
1078 /* Copy over the new un-constrainified template. */
1079 XTMPL (x, templ_index) = xstrdup (new_templ.c_str ());
1081 /* Register for later checks during iterator expansions. */
1082 compact_syntax.add (x);
1085 /* Process a top level rtx in some way, queuing as appropriate. */
1087 static void
1088 process_rtx (rtx desc, file_location loc)
1090 switch (GET_CODE (desc))
1092 case DEFINE_INSN:
1093 convert_syntax (desc, loc);
1094 queue_pattern (desc, &define_insn_tail, loc);
1095 break;
1097 case DEFINE_COND_EXEC:
1098 queue_pattern (desc, &define_cond_exec_tail, loc);
1099 break;
1101 case DEFINE_SUBST:
1102 queue_pattern (desc, &define_subst_tail, loc);
1103 break;
1105 case DEFINE_SUBST_ATTR:
1106 queue_pattern (desc, &define_subst_attr_tail, loc);
1107 break;
1109 case DEFINE_ATTR:
1110 case DEFINE_ENUM_ATTR:
1111 queue_pattern (desc, &define_attr_tail, loc);
1112 break;
1114 case DEFINE_PREDICATE:
1115 case DEFINE_SPECIAL_PREDICATE:
1116 process_define_predicate (desc, loc);
1117 queue_pattern (desc, &define_pred_tail, loc);
1118 break;
1120 case DEFINE_REGISTER_CONSTRAINT:
1121 process_define_register_constraint (desc, loc);
1122 queue_pattern (desc, &define_pred_tail, loc);
1123 break;
1125 case DEFINE_CONSTRAINT:
1126 case DEFINE_MEMORY_CONSTRAINT:
1127 case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
1128 case DEFINE_RELAXED_MEMORY_CONSTRAINT:
1129 case DEFINE_ADDRESS_CONSTRAINT:
1130 queue_pattern (desc, &define_pred_tail, loc);
1131 break;
1133 case DEFINE_INSN_AND_SPLIT:
1134 case DEFINE_INSN_AND_REWRITE:
1136 const char *split_cond;
1137 rtx split;
1138 rtvec attr;
1139 int i;
1140 class queue_elem *insn_elem;
1141 class queue_elem *split_elem;
1142 int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6);
1144 /* Create a split with values from the insn_and_split. */
1145 split = rtx_alloc (DEFINE_SPLIT);
1147 i = XVECLEN (desc, 1);
1148 XVEC (split, 0) = rtvec_alloc (i);
1149 while (--i >= 0)
1151 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
1152 remove_constraints (XVECEXP (split, 0, i));
1155 /* If the split condition starts with "&&", append it to the
1156 insn condition to create the new split condition. */
1157 split_cond = XSTR (desc, 4);
1158 if (split_cond[0] == '&' && split_cond[1] == '&')
1160 rtx_reader_ptr->copy_md_ptr_loc (split_cond + 2, split_cond);
1161 split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
1162 split_cond + 2);
1164 else if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
1165 error_at (loc, "the rewrite condition must start with `&&'");
1166 XSTR (split, 1) = split_cond;
1167 if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
1168 XVEC (split, 2) = gen_rewrite_sequence (XVEC (desc, 1));
1169 else
1170 XVEC (split, 2) = XVEC (desc, 5);
1171 XSTR (split, 3) = XSTR (desc, split_code);
1173 /* Fix up the DEFINE_INSN. */
1174 attr = XVEC (desc, split_code + 1);
1175 PUT_CODE (desc, DEFINE_INSN);
1176 XVEC (desc, 4) = attr;
1177 convert_syntax (desc, loc);
1179 /* Queue them. */
1180 insn_elem = queue_pattern (desc, &define_insn_tail, loc);
1181 split_elem = queue_pattern (split, &other_tail, loc);
1182 insn_elem->split = split_elem;
1183 break;
1186 default:
1187 queue_pattern (desc, &other_tail, loc);
1188 break;
1192 /* Return true if attribute PREDICABLE is true for ELEM, which holds
1193 a DEFINE_INSN. */
1195 static int
1196 is_predicable (class queue_elem *elem)
1198 rtvec vec = XVEC (elem->data, 4);
1199 const char *value;
1200 int i;
1202 if (! vec)
1203 return predicable_default;
1205 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
1207 rtx sub = RTVEC_ELT (vec, i);
1208 switch (GET_CODE (sub))
1210 case SET_ATTR:
1211 if (strcmp (XSTR (sub, 0), "predicable") == 0)
1213 value = XSTR (sub, 1);
1214 goto found;
1216 break;
1218 case SET_ATTR_ALTERNATIVE:
1219 if (strcmp (XSTR (sub, 0), "predicable") == 0)
1221 error_at (elem->loc, "multiple alternatives for `predicable'");
1222 return 0;
1224 break;
1226 case SET:
1227 if (GET_CODE (SET_DEST (sub)) != ATTR
1228 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
1229 break;
1230 sub = SET_SRC (sub);
1231 if (GET_CODE (sub) == CONST_STRING)
1233 value = XSTR (sub, 0);
1234 goto found;
1237 /* ??? It would be possible to handle this if we really tried.
1238 It's not easy though, and I'm not going to bother until it
1239 really proves necessary. */
1240 error_at (elem->loc, "non-constant value for `predicable'");
1241 return 0;
1243 default:
1244 gcc_unreachable ();
1248 return predicable_default;
1250 found:
1251 /* Find out which value we're looking at. Multiple alternatives means at
1252 least one is predicable. */
1253 if (strchr (value, ',') != NULL)
1254 return 1;
1255 if (strcmp (value, predicable_true) == 0)
1256 return 1;
1257 if (strcmp (value, predicable_false) == 0)
1258 return 0;
1260 error_at (elem->loc, "unknown value `%s' for `predicable' attribute", value);
1261 return 0;
1264 /* Find attribute SUBST in ELEM and assign NEW_VALUE to it. */
1265 static void
1266 change_subst_attribute (class queue_elem *elem,
1267 class queue_elem *subst_elem,
1268 const char *new_value)
1270 rtvec attrs_vec = XVEC (elem->data, 4);
1271 const char *subst_name = XSTR (subst_elem->data, 0);
1272 int i;
1274 if (! attrs_vec)
1275 return;
1277 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
1279 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
1280 if (GET_CODE (cur_attr) != SET_ATTR)
1281 continue;
1282 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
1284 XSTR (cur_attr, 1) = new_value;
1285 return;
1290 /* Return true if ELEM has the attribute with the name of DEFINE_SUBST
1291 represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
1292 DEFINE_SUBST isn't applied to patterns without such attribute. In other
1293 words, we suppose the default value of the attribute to be 'no' since it is
1294 always generated automatically in read-rtl.cc. */
1295 static bool
1296 has_subst_attribute (class queue_elem *elem, class queue_elem *subst_elem)
1298 rtvec attrs_vec = XVEC (elem->data, 4);
1299 const char *value, *subst_name = XSTR (subst_elem->data, 0);
1300 int i;
1302 if (! attrs_vec)
1303 return false;
1305 for (i = GET_NUM_ELEM (attrs_vec) - 1; i >= 0; --i)
1307 rtx cur_attr = RTVEC_ELT (attrs_vec, i);
1308 switch (GET_CODE (cur_attr))
1310 case SET_ATTR:
1311 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
1313 value = XSTR (cur_attr, 1);
1314 goto found;
1316 break;
1318 case SET:
1319 if (GET_CODE (SET_DEST (cur_attr)) != ATTR
1320 || strcmp (XSTR (SET_DEST (cur_attr), 0), subst_name) != 0)
1321 break;
1322 cur_attr = SET_SRC (cur_attr);
1323 if (GET_CODE (cur_attr) == CONST_STRING)
1325 value = XSTR (cur_attr, 0);
1326 goto found;
1329 /* Only (set_attr "subst" "yes/no") and
1330 (set (attr "subst" (const_string "yes/no")))
1331 are currently allowed. */
1332 error_at (elem->loc, "unsupported value for `%s'", subst_name);
1333 return false;
1335 case SET_ATTR_ALTERNATIVE:
1336 if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
1337 error_at (elem->loc,
1338 "%s: `set_attr_alternative' is unsupported by "
1339 "`define_subst'", XSTR (elem->data, 0));
1340 return false;
1343 default:
1344 gcc_unreachable ();
1348 return false;
1350 found:
1351 if (strcmp (value, subst_true) == 0)
1352 return true;
1353 if (strcmp (value, subst_false) == 0)
1354 return false;
1356 error_at (elem->loc, "unknown value `%s' for `%s' attribute",
1357 value, subst_name);
1358 return false;
1361 /* Compare RTL-template of original define_insn X to input RTL-template of
1362 define_subst PT. Return 1 if the templates match, 0 otherwise.
1363 During the comparison, the routine also fills global_array OPERAND_DATA. */
1364 static bool
1365 subst_pattern_match (rtx x, rtx pt, file_location loc)
1367 RTX_CODE code, code_pt;
1368 int i, j, len;
1369 const char *fmt, *pred_name;
1371 code = GET_CODE (x);
1372 code_pt = GET_CODE (pt);
1374 if (code_pt == MATCH_OPERAND)
1376 /* MATCH_DUP, and MATCH_OP_DUP don't have a specified mode, so we
1377 always accept them. */
1378 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt)
1379 && (code != MATCH_DUP && code != MATCH_OP_DUP))
1380 return false; /* Modes don't match. */
1382 if (code == MATCH_OPERAND)
1384 pred_name = XSTR (pt, 1);
1385 if (pred_name[0] != 0)
1387 const struct pred_data *pred_pt = lookup_predicate (pred_name);
1388 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
1389 return false; /* Predicates don't match. */
1393 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
1394 operand_data[XINT (pt, 0)] = x;
1395 return true;
1398 if (code_pt == MATCH_OPERATOR)
1400 int x_vecexp_pos = -1;
1402 /* Compare modes. */
1403 if (GET_MODE (pt) != VOIDmode && GET_MODE (x) != GET_MODE (pt))
1404 return false;
1406 /* In case X is also match_operator, compare predicates. */
1407 if (code == MATCH_OPERATOR)
1409 pred_name = XSTR (pt, 1);
1410 if (pred_name[0] != 0)
1412 const struct pred_data *pred_pt = lookup_predicate (pred_name);
1413 if (!pred_pt || pred_pt != lookup_predicate (XSTR (x, 1)))
1414 return false;
1418 /* Compare operands.
1419 MATCH_OPERATOR in input template could match in original template
1420 either 1) MATCH_OPERAND, 2) UNSPEC, 3) ordinary operation (like PLUS).
1421 In the first case operands are at (XVECEXP (x, 2, j)), in the second
1422 - at (XVECEXP (x, 0, j)), in the last one - (XEXP (x, j)).
1423 X_VECEXP_POS variable shows, where to look for these operands. */
1424 if (code == UNSPEC
1425 || code == UNSPEC_VOLATILE)
1426 x_vecexp_pos = 0;
1427 else if (code == MATCH_OPERATOR)
1428 x_vecexp_pos = 2;
1429 else
1430 x_vecexp_pos = -1;
1432 /* MATCH_OPERATOR or UNSPEC case. */
1433 if (x_vecexp_pos >= 0)
1435 /* Compare operands number in X and PT. */
1436 if (XVECLEN (x, x_vecexp_pos) != XVECLEN (pt, 2))
1437 return false;
1438 for (j = 0; j < XVECLEN (pt, 2); j++)
1439 if (!subst_pattern_match (XVECEXP (x, x_vecexp_pos, j),
1440 XVECEXP (pt, 2, j), loc))
1441 return false;
1444 /* Ordinary operator. */
1445 else
1447 /* Compare operands number in X and PT.
1448 We count operands differently for X and PT since we compare
1449 an operator (with operands directly in RTX) and MATCH_OPERATOR
1450 (that has a vector with operands). */
1451 if (GET_RTX_LENGTH (code) != XVECLEN (pt, 2))
1452 return false;
1453 for (j = 0; j < XVECLEN (pt, 2); j++)
1454 if (!subst_pattern_match (XEXP (x, j), XVECEXP (pt, 2, j), loc))
1455 return false;
1458 /* Store the operand to OPERAND_DATA array. */
1459 gcc_assert (XINT (pt, 0) >= 0 && XINT (pt, 0) < MAX_OPERANDS);
1460 operand_data[XINT (pt, 0)] = x;
1461 return true;
1464 if (code_pt == MATCH_PAR_DUP
1465 || code_pt == MATCH_DUP
1466 || code_pt == MATCH_OP_DUP
1467 || code_pt == MATCH_SCRATCH
1468 || code_pt == MATCH_PARALLEL)
1470 /* Currently interface for these constructions isn't defined -
1471 probably they aren't needed in input template of define_subst at all.
1472 So, for now their usage in define_subst is forbidden. */
1473 error_at (loc, "%s cannot be used in define_subst",
1474 GET_RTX_NAME (code_pt));
1477 gcc_assert (code != MATCH_PAR_DUP
1478 && code_pt != MATCH_DUP
1479 && code_pt != MATCH_OP_DUP
1480 && code_pt != MATCH_SCRATCH
1481 && code_pt != MATCH_PARALLEL
1482 && code_pt != MATCH_OPERAND
1483 && code_pt != MATCH_OPERATOR);
1484 /* If PT is none of the handled above, then we match only expressions with
1485 the same code in X. */
1486 if (code != code_pt)
1487 return false;
1489 fmt = GET_RTX_FORMAT (code_pt);
1490 len = GET_RTX_LENGTH (code_pt);
1492 for (i = 0; i < len; i++)
1494 if (fmt[i] == '0')
1495 break;
1497 switch (fmt[i])
1499 case 'r': case 'p': case 'i': case 'w': case 's': case 'L':
1500 continue;
1502 case 'e': case 'u':
1503 if (!subst_pattern_match (XEXP (x, i), XEXP (pt, i), loc))
1504 return false;
1505 break;
1506 case 'E':
1508 if (XVECLEN (x, i) != XVECLEN (pt, i))
1509 return false;
1510 for (j = 0; j < XVECLEN (pt, i); j++)
1511 if (!subst_pattern_match (XVECEXP (x, i, j),
1512 XVECEXP (pt, i, j), loc))
1513 return false;
1514 break;
1516 default:
1517 gcc_unreachable ();
1521 return true;
1524 /* Examine the attribute "predicable"; discover its boolean values
1525 and its default. */
1527 static void
1528 identify_predicable_attribute (void)
1530 class queue_elem *elem;
1531 char *p_true, *p_false;
1532 const char *value;
1534 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
1535 for (elem = define_attr_queue; elem ; elem = elem->next)
1536 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
1537 goto found;
1539 error_at (define_cond_exec_queue->loc,
1540 "attribute `predicable' not defined");
1541 return;
1543 found:
1544 value = XSTR (elem->data, 1);
1545 p_false = xstrdup (value);
1546 p_true = strchr (p_false, ',');
1547 if (p_true == NULL || strchr (++p_true, ',') != NULL)
1549 error_at (elem->loc, "attribute `predicable' is not a boolean");
1550 free (p_false);
1551 return;
1553 p_true[-1] = '\0';
1555 predicable_true = p_true;
1556 predicable_false = p_false;
1558 switch (GET_CODE (XEXP (elem->data, 2)))
1560 case CONST_STRING:
1561 value = XSTR (XEXP (elem->data, 2), 0);
1562 break;
1564 case CONST:
1565 error_at (elem->loc, "attribute `predicable' cannot be const");
1566 free (p_false);
1567 return;
1569 default:
1570 error_at (elem->loc,
1571 "attribute `predicable' must have a constant default");
1572 free (p_false);
1573 return;
1576 if (strcmp (value, p_true) == 0)
1577 predicable_default = 1;
1578 else if (strcmp (value, p_false) == 0)
1579 predicable_default = 0;
1580 else
1582 error_at (elem->loc, "unknown value `%s' for `predicable' attribute",
1583 value);
1584 free (p_false);
1588 /* Return the number of alternatives in constraint S. */
1590 static int
1591 n_alternatives (const char *s)
1593 int n = 1;
1595 if (s)
1596 while (*s)
1597 n += (*s++ == ',');
1599 return n;
1602 /* The routine scans rtl PATTERN, find match_operand in it and counts
1603 number of alternatives. If PATTERN contains several match_operands
1604 with different number of alternatives, error is emitted, and the
1605 routine returns 0. If all match_operands in PATTERN have the same
1606 number of alternatives, it's stored in N_ALT, and the routine returns 1.
1607 LOC is the location of PATTERN, for error reporting. */
1608 static int
1609 get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
1611 const char *fmt;
1612 enum rtx_code code;
1613 int i, j, len;
1615 if (!n_alt)
1616 return 0;
1618 code = GET_CODE (pattern);
1619 switch (code)
1621 case MATCH_OPERAND:
1622 i = n_alternatives (XSTR (pattern, 2));
1623 /* n_alternatives returns 1 if constraint string is empty -
1624 here we fix it up. */
1625 if (!*(XSTR (pattern, 2)))
1626 i = 0;
1627 if (*n_alt <= 0)
1628 *n_alt = i;
1630 else if (i && i != *n_alt)
1632 error_at (loc, "wrong number of alternatives in operand %d",
1633 XINT (pattern, 0));
1634 return 0;
1637 default:
1638 break;
1641 fmt = GET_RTX_FORMAT (code);
1642 len = GET_RTX_LENGTH (code);
1643 for (i = 0; i < len; i++)
1645 switch (fmt[i])
1647 case 'e': case 'u':
1648 if (!get_alternatives_number (XEXP (pattern, i), n_alt, loc))
1649 return 0;
1650 break;
1652 case 'V':
1653 if (XVEC (pattern, i) == NULL)
1654 break;
1655 /* FALLTHRU */
1657 case 'E':
1658 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1659 if (!get_alternatives_number (XVECEXP (pattern, i, j), n_alt, loc))
1660 return 0;
1661 break;
1663 case 'r': case 'p': case 'i': case 'w':
1664 case '0': case 's': case 'S': case 'T':
1665 case 'L':
1666 break;
1668 default:
1669 gcc_unreachable ();
1672 return 1;
1675 /* Determine how many alternatives there are in INSN, and how many
1676 operands. */
1678 static void
1679 collect_insn_data (rtx pattern, int *palt, int *pmax)
1681 const char *fmt;
1682 enum rtx_code code;
1683 int i, j, len;
1685 code = GET_CODE (pattern);
1686 switch (code)
1688 case MATCH_OPERAND:
1689 case MATCH_SCRATCH:
1690 i = n_alternatives (XSTR (pattern, code == MATCH_SCRATCH ? 1 : 2));
1691 *palt = (i > *palt ? i : *palt);
1692 /* Fall through. */
1694 case MATCH_OPERATOR:
1695 case MATCH_PARALLEL:
1696 i = XINT (pattern, 0);
1697 if (i > *pmax)
1698 *pmax = i;
1699 break;
1701 default:
1702 break;
1705 fmt = GET_RTX_FORMAT (code);
1706 len = GET_RTX_LENGTH (code);
1707 for (i = 0; i < len; i++)
1709 switch (fmt[i])
1711 case 'e': case 'u':
1712 collect_insn_data (XEXP (pattern, i), palt, pmax);
1713 break;
1715 case 'V':
1716 if (XVEC (pattern, i) == NULL)
1717 break;
1718 /* Fall through. */
1719 case 'E':
1720 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1721 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
1722 break;
1724 case 'r': case 'p': case 'i': case 'w':
1725 case '0': case 's': case 'S': case 'T':
1726 case 'L':
1727 break;
1729 default:
1730 gcc_unreachable ();
1735 static rtx
1736 alter_predicate_for_insn (rtx pattern, int alt, int max_op,
1737 file_location loc)
1739 const char *fmt;
1740 enum rtx_code code;
1741 int i, j, len;
1743 code = GET_CODE (pattern);
1744 switch (code)
1746 case MATCH_OPERAND:
1748 const char *c = XSTR (pattern, 2);
1750 if (n_alternatives (c) != 1)
1752 error_at (loc, "too many alternatives for operand %d",
1753 XINT (pattern, 0));
1754 return NULL;
1757 /* Replicate C as needed to fill out ALT alternatives. */
1758 if (c && *c && alt > 1)
1760 size_t c_len = strlen (c);
1761 size_t len = alt * (c_len + 1);
1762 char *new_c = XNEWVEC (char, len);
1764 memcpy (new_c, c, c_len);
1765 for (i = 1; i < alt; ++i)
1767 new_c[i * (c_len + 1) - 1] = ',';
1768 memcpy (&new_c[i * (c_len + 1)], c, c_len);
1770 new_c[len - 1] = '\0';
1771 XSTR (pattern, 2) = new_c;
1774 /* Fall through. */
1776 case MATCH_OPERATOR:
1777 case MATCH_SCRATCH:
1778 case MATCH_PARALLEL:
1779 case MATCH_DUP:
1780 XINT (pattern, 0) += max_op;
1781 break;
1783 default:
1784 break;
1787 fmt = GET_RTX_FORMAT (code);
1788 len = GET_RTX_LENGTH (code);
1789 for (i = 0; i < len; i++)
1791 rtx r;
1793 switch (fmt[i])
1795 case 'e': case 'u':
1796 r = alter_predicate_for_insn (XEXP (pattern, i), alt, max_op, loc);
1797 if (r == NULL)
1798 return r;
1799 break;
1801 case 'E':
1802 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1804 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
1805 alt, max_op, loc);
1806 if (r == NULL)
1807 return r;
1809 break;
1811 case 'r': case 'p': case 'i': case 'w': case '0': case 's': case 'L':
1812 break;
1814 default:
1815 gcc_unreachable ();
1819 return pattern;
1822 /* Duplicate constraints in PATTERN. If pattern is from original
1823 rtl-template, we need to duplicate each alternative - for that we
1824 need to use duplicate_each_alternative () as a functor ALTER.
1825 If pattern is from output-pattern of define_subst, we need to
1826 duplicate constraints in another way - with duplicate_alternatives ().
1827 N_DUP is multiplication factor. */
1828 static rtx
1829 alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
1831 const char *fmt;
1832 enum rtx_code code;
1833 int i, j, len;
1835 code = GET_CODE (pattern);
1836 switch (code)
1838 case MATCH_OPERAND:
1839 XSTR (pattern, 2) = alter (XSTR (pattern, 2), n_dup);
1840 break;
1841 case MATCH_SCRATCH:
1842 XSTR (pattern, 1) = alter (XSTR (pattern, 1), n_dup);
1843 break;
1845 default:
1846 break;
1849 fmt = GET_RTX_FORMAT (code);
1850 len = GET_RTX_LENGTH (code);
1851 for (i = 0; i < len; i++)
1853 rtx r;
1855 switch (fmt[i])
1857 case 'e': case 'u':
1858 r = alter_constraints (XEXP (pattern, i), n_dup, alter);
1859 if (r == NULL)
1860 return r;
1861 break;
1863 case 'E':
1864 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
1866 r = alter_constraints (XVECEXP (pattern, i, j), n_dup, alter);
1867 if (r == NULL)
1868 return r;
1870 break;
1872 case 'r': case 'p': case 'i': case 'w': case '0': case 's': case 'L':
1873 break;
1875 default:
1876 break;
1880 return pattern;
1883 static const char *
1884 alter_test_for_insn (class queue_elem *ce_elem,
1885 class queue_elem *insn_elem)
1887 return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1),
1888 XSTR (insn_elem->data, 2));
1891 /* Modify VAL, which is an attribute expression for the "enabled" attribute,
1892 to take "ce_enabled" into account. Return the new expression. */
1893 static rtx
1894 modify_attr_enabled_ce (rtx val)
1896 rtx eq_attr, str;
1897 rtx ite;
1898 eq_attr = rtx_alloc (EQ_ATTR);
1899 ite = rtx_alloc (IF_THEN_ELSE);
1900 str = rtx_alloc (CONST_STRING);
1902 XSTR (eq_attr, 0) = "ce_enabled";
1903 XSTR (eq_attr, 1) = "yes";
1904 XSTR (str, 0) = "no";
1905 XEXP (ite, 0) = eq_attr;
1906 XEXP (ite, 1) = val;
1907 XEXP (ite, 2) = str;
1909 return ite;
1912 /* Alter the attribute vector of INSN, which is a COND_EXEC variant created
1913 from a define_insn pattern. We must modify the "predicable" attribute
1914 to be named "ce_enabled", and also change any "enabled" attribute that's
1915 present so that it takes ce_enabled into account.
1916 We rely on the fact that INSN was created with copy_rtx, and modify data
1917 in-place. */
1919 static void
1920 alter_attrs_for_insn (rtx insn)
1922 static bool global_changes_made = false;
1923 rtvec vec = XVEC (insn, 4);
1924 rtvec new_vec;
1925 rtx val, set;
1926 int num_elem;
1927 int predicable_idx = -1;
1928 int enabled_idx = -1;
1929 int i;
1931 if (! vec)
1932 return;
1934 num_elem = GET_NUM_ELEM (vec);
1935 for (i = num_elem - 1; i >= 0; --i)
1937 rtx sub = RTVEC_ELT (vec, i);
1938 switch (GET_CODE (sub))
1940 case SET_ATTR:
1941 if (strcmp (XSTR (sub, 0), "predicable") == 0)
1943 predicable_idx = i;
1944 XSTR (sub, 0) = "ce_enabled";
1946 else if (strcmp (XSTR (sub, 0), "enabled") == 0)
1948 enabled_idx = i;
1949 XSTR (sub, 0) = "nonce_enabled";
1951 break;
1953 case SET_ATTR_ALTERNATIVE:
1954 if (strcmp (XSTR (sub, 0), "predicable") == 0)
1955 /* We already give an error elsewhere. */
1956 return;
1957 else if (strcmp (XSTR (sub, 0), "enabled") == 0)
1959 enabled_idx = i;
1960 XSTR (sub, 0) = "nonce_enabled";
1962 break;
1964 case SET:
1965 if (GET_CODE (SET_DEST (sub)) != ATTR)
1966 break;
1967 if (strcmp (XSTR (SET_DEST (sub), 0), "predicable") == 0)
1969 sub = SET_SRC (sub);
1970 if (GET_CODE (sub) == CONST_STRING)
1972 predicable_idx = i;
1973 XSTR (sub, 0) = "ce_enabled";
1975 else
1976 /* We already give an error elsewhere. */
1977 return;
1978 break;
1980 if (strcmp (XSTR (SET_DEST (sub), 0), "enabled") == 0)
1982 enabled_idx = i;
1983 XSTR (SET_DEST (sub), 0) = "nonce_enabled";
1985 break;
1987 default:
1988 gcc_unreachable ();
1991 if (predicable_idx == -1)
1992 return;
1994 if (!global_changes_made)
1996 class queue_elem *elem;
1998 global_changes_made = true;
1999 add_define_attr ("ce_enabled");
2000 add_define_attr ("nonce_enabled");
2002 for (elem = define_attr_queue; elem ; elem = elem->next)
2003 if (strcmp (XSTR (elem->data, 0), "enabled") == 0)
2005 XEXP (elem->data, 2)
2006 = modify_attr_enabled_ce (XEXP (elem->data, 2));
2009 if (enabled_idx == -1)
2010 return;
2012 new_vec = rtvec_alloc (num_elem + 1);
2013 for (i = 0; i < num_elem; i++)
2014 RTVEC_ELT (new_vec, i) = RTVEC_ELT (vec, i);
2015 val = rtx_alloc (IF_THEN_ELSE);
2016 XEXP (val, 0) = rtx_alloc (EQ_ATTR);
2017 XEXP (val, 1) = rtx_alloc (CONST_STRING);
2018 XEXP (val, 2) = rtx_alloc (CONST_STRING);
2019 XSTR (XEXP (val, 0), 0) = "nonce_enabled";
2020 XSTR (XEXP (val, 0), 1) = "yes";
2021 XSTR (XEXP (val, 1), 0) = "yes";
2022 XSTR (XEXP (val, 2), 0) = "no";
2023 set = rtx_alloc (SET);
2024 SET_DEST (set) = rtx_alloc (ATTR);
2025 XSTR (SET_DEST (set), 0) = "enabled";
2026 SET_SRC (set) = modify_attr_enabled_ce (val);
2027 RTVEC_ELT (new_vec, i) = set;
2028 XVEC (insn, 4) = new_vec;
2031 /* As number of constraints is changed after define_subst, we need to
2032 process attributes as well - we need to duplicate them the same way
2033 that we duplicated constraints in original pattern
2034 ELEM is a queue element, containing our rtl-template,
2035 N_DUP - multiplication factor. */
2036 static void
2037 alter_attrs_for_subst_insn (class queue_elem * elem, int n_dup)
2039 rtvec vec = XVEC (elem->data, 4);
2040 int num_elem;
2041 int i;
2043 if (n_dup < 2 || ! vec)
2044 return;
2046 num_elem = GET_NUM_ELEM (vec);
2047 for (i = num_elem - 1; i >= 0; --i)
2049 rtx sub = RTVEC_ELT (vec, i);
2050 switch (GET_CODE (sub))
2052 case SET_ATTR:
2053 if (strchr (XSTR (sub, 1), ',') != NULL)
2054 XSTR (sub, 1) = duplicate_alternatives (XSTR (sub, 1), n_dup);
2055 break;
2057 case SET_ATTR_ALTERNATIVE:
2058 case SET:
2059 error_at (elem->loc,
2060 "%s: `define_subst' does not support attributes "
2061 "assigned by `set' and `set_attr_alternative'",
2062 XSTR (elem->data, 0));
2063 return;
2065 default:
2066 gcc_unreachable ();
2071 /* Adjust all of the operand numbers in SRC to match the shift they'll
2072 get from an operand displacement of DISP. Return a pointer after the
2073 adjusted string. */
2075 static char *
2076 shift_output_template (char *dest, const char *src, int disp)
2078 while (*src)
2080 char c = *src++;
2081 *dest++ = c;
2082 if (c == '%')
2084 c = *src++;
2085 if (ISDIGIT ((unsigned char) c))
2086 c += disp;
2087 else if (ISALPHA (c))
2089 *dest++ = c;
2090 c = *src++ + disp;
2092 *dest++ = c;
2096 return dest;
2099 static const char *
2100 alter_output_for_insn (class queue_elem *ce_elem,
2101 class queue_elem *insn_elem,
2102 int alt, int max_op)
2104 const char *ce_out, *insn_out;
2105 char *result, *p;
2106 size_t len, ce_len, insn_len;
2108 /* ??? Could coordinate with genoutput to not duplicate code here. */
2110 ce_out = XSTR (ce_elem->data, 2);
2111 insn_out = XTMPL (insn_elem->data, 3);
2112 if (!ce_out || *ce_out == '\0')
2113 return insn_out;
2115 ce_len = strlen (ce_out);
2116 insn_len = strlen (insn_out);
2118 if (*insn_out == '*')
2119 /* You must take care of the predicate yourself. */
2120 return insn_out;
2122 if (*insn_out == '@')
2124 len = (ce_len + 1) * alt + insn_len + 1;
2125 p = result = XNEWVEC (char, len);
2130 *p++ = *insn_out++;
2131 while (ISSPACE ((unsigned char) *insn_out));
2133 if (*insn_out != '#')
2135 p = shift_output_template (p, ce_out, max_op);
2136 *p++ = ' ';
2140 *p++ = *insn_out++;
2141 while (*insn_out && *insn_out != '\n');
2143 while (*insn_out);
2144 *p = '\0';
2146 else
2148 len = ce_len + 1 + insn_len + 1;
2149 result = XNEWVEC (char, len);
2151 p = shift_output_template (result, ce_out, max_op);
2152 *p++ = ' ';
2153 memcpy (p, insn_out, insn_len + 1);
2156 return result;
2159 /* From string STR "a,b,c" produce "a,b,c,a,b,c,a,b,c", i.e. original
2160 string, duplicated N_DUP times. */
2162 static const char *
2163 duplicate_alternatives (const char * str, int n_dup)
2165 int i, len, new_len;
2166 char *result, *sp;
2167 const char *cp;
2169 if (n_dup < 2)
2170 return str;
2172 while (ISSPACE (*str))
2173 str++;
2175 if (*str == '\0')
2176 return str;
2178 cp = str;
2179 len = strlen (str);
2180 new_len = (len + 1) * n_dup;
2182 sp = result = XNEWVEC (char, new_len);
2184 /* Global modifier characters mustn't be duplicated: skip if found. */
2185 if (*cp == '=' || *cp == '+' || *cp == '%')
2187 *sp++ = *cp++;
2188 len--;
2191 /* Copy original constraints N_DUP times. */
2192 for (i = 0; i < n_dup; i++, sp += len+1)
2194 memcpy (sp, cp, len);
2195 *(sp+len) = (i == n_dup - 1) ? '\0' : ',';
2198 return result;
2201 /* From string STR "a,b,c" produce "a,a,a,b,b,b,c,c,c", i.e. string where
2202 each alternative from the original string is duplicated N_DUP times. */
2203 static const char *
2204 duplicate_each_alternative (const char * str, int n_dup)
2206 int i, len, new_len;
2207 char *result, *sp, *ep, *cp;
2209 if (n_dup < 2)
2210 return str;
2212 while (ISSPACE (*str))
2213 str++;
2215 if (*str == '\0')
2216 return str;
2218 cp = xstrdup (str);
2220 new_len = (strlen (cp) + 1) * n_dup;
2222 sp = result = XNEWVEC (char, new_len);
2224 /* Global modifier characters mustn't be duplicated: skip if found. */
2225 if (*cp == '=' || *cp == '+' || *cp == '%')
2226 *sp++ = *cp++;
2230 if ((ep = strchr (cp, ',')) != NULL)
2231 *ep++ = '\0';
2232 len = strlen (cp);
2234 /* Copy a constraint N_DUP times. */
2235 for (i = 0; i < n_dup; i++, sp += len + 1)
2237 memcpy (sp, cp, len);
2238 *(sp+len) = (ep == NULL && i == n_dup - 1) ? '\0' : ',';
2241 cp = ep;
2243 while (cp != NULL);
2245 return result;
2248 /* Alter the output of INSN whose pattern was modified by
2249 DEFINE_SUBST. We must replicate output strings according
2250 to the new number of alternatives ALT in substituted pattern.
2251 If ALT equals 1, output has one alternative or defined by C
2252 code, then output is returned without any changes. */
2254 static const char *
2255 alter_output_for_subst_insn (rtx insn, int alt)
2257 const char *insn_out, *old_out;
2258 char *new_out, *cp;
2259 size_t old_len, new_len;
2260 int j;
2262 insn_out = XTMPL (insn, 3);
2264 if (alt < 2 || *insn_out != '@')
2265 return insn_out;
2267 old_out = insn_out + 1;
2268 while (ISSPACE (*old_out))
2269 old_out++;
2270 old_len = strlen (old_out);
2272 new_len = alt * (old_len + 1) + 1;
2274 new_out = XNEWVEC (char, new_len);
2275 new_out[0] = '@';
2277 for (j = 0, cp = new_out + 1; j < alt; j++, cp += old_len + 1)
2279 memcpy (cp, old_out, old_len);
2280 cp[old_len] = (j == alt - 1) ? '\0' : '\n';
2283 return new_out;
2286 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
2288 static void
2289 process_one_cond_exec (class queue_elem *ce_elem)
2291 class queue_elem *insn_elem;
2292 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
2294 int alternatives, max_operand;
2295 rtx pred, insn, pattern, split;
2296 char *new_name;
2297 int i;
2299 if (! is_predicable (insn_elem))
2300 continue;
2302 alternatives = 1;
2303 max_operand = -1;
2304 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
2305 max_operand += 1;
2307 if (XVECLEN (ce_elem->data, 0) != 1)
2309 error_at (ce_elem->loc, "too many patterns in predicate");
2310 return;
2313 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
2314 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
2315 ce_elem->loc);
2316 if (pred == NULL)
2317 return;
2319 /* Construct a new pattern for the new insn. */
2320 insn = copy_rtx (insn_elem->data);
2321 new_name = XNEWVAR (char, strlen XSTR (insn_elem->data, 0) + 4);
2322 sprintf (new_name, "*p %s", XSTR (insn_elem->data, 0));
2323 XSTR (insn, 0) = new_name;
2324 pattern = rtx_alloc (COND_EXEC);
2325 XEXP (pattern, 0) = pred;
2326 XEXP (pattern, 1) = add_implicit_parallel (XVEC (insn, 1));
2327 XVEC (insn, 1) = rtvec_alloc (1);
2328 XVECEXP (insn, 1, 0) = pattern;
2330 if (XVEC (ce_elem->data, 3) != NULL)
2332 rtvec attributes = rtvec_alloc (XVECLEN (insn, 4)
2333 + XVECLEN (ce_elem->data, 3));
2334 int i = 0;
2335 int j = 0;
2336 for (i = 0; i < XVECLEN (insn, 4); i++)
2337 RTVEC_ELT (attributes, i) = XVECEXP (insn, 4, i);
2339 for (j = 0; j < XVECLEN (ce_elem->data, 3); j++, i++)
2340 RTVEC_ELT (attributes, i) = XVECEXP (ce_elem->data, 3, j);
2342 XVEC (insn, 4) = attributes;
2345 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
2346 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
2347 alternatives, max_operand);
2348 alter_attrs_for_insn (insn);
2350 /* Put the new pattern on the `other' list so that it
2351 (a) is not reprocessed by other define_cond_exec patterns
2352 (b) appears after all normal define_insn patterns.
2354 ??? B is debatable. If one has normal insns that match
2355 cond_exec patterns, they will be preferred over these
2356 generated patterns. Whether this matters in practice, or if
2357 it's a good thing, or whether we should thread these new
2358 patterns into the define_insn chain just after their generator
2359 is something we'll have to experiment with. */
2361 queue_pattern (insn, &other_tail, insn_elem->loc);
2363 if (!insn_elem->split)
2364 continue;
2366 /* If the original insn came from a define_insn_and_split,
2367 generate a new split to handle the predicated insn. */
2368 split = copy_rtx (insn_elem->split->data);
2369 /* Predicate the pattern matched by the split. */
2370 pattern = rtx_alloc (COND_EXEC);
2371 XEXP (pattern, 0) = pred;
2372 XEXP (pattern, 1) = add_implicit_parallel (XVEC (split, 0));
2373 XVEC (split, 0) = rtvec_alloc (1);
2374 XVECEXP (split, 0, 0) = pattern;
2376 /* Predicate all of the insns generated by the split. */
2377 for (i = 0; i < XVECLEN (split, 2); i++)
2379 pattern = rtx_alloc (COND_EXEC);
2380 XEXP (pattern, 0) = pred;
2381 XEXP (pattern, 1) = XVECEXP (split, 2, i);
2382 XVECEXP (split, 2, i) = pattern;
2384 /* Add the new split to the queue. */
2385 queue_pattern (split, &other_tail, insn_elem->split->loc);
2389 /* Try to apply define_substs to the given ELEM.
2390 Only define_substs, specified via attributes would be applied.
2391 If attribute, requiring define_subst, is set, but no define_subst
2392 was applied, ELEM would be deleted. */
2394 static void
2395 process_substs_on_one_elem (class queue_elem *elem,
2396 class queue_elem *queue)
2398 class queue_elem *subst_elem;
2399 int i, j, patterns_match;
2401 for (subst_elem = define_subst_queue;
2402 subst_elem; subst_elem = subst_elem->next)
2404 int alternatives, alternatives_subst;
2405 rtx subst_pattern;
2406 rtvec subst_pattern_vec;
2408 if (!has_subst_attribute (elem, subst_elem))
2409 continue;
2411 /* Compare original rtl-pattern from define_insn with input
2412 pattern from define_subst.
2413 Also, check if numbers of alternatives are the same in all
2414 match_operands. */
2415 if (XVECLEN (elem->data, 1) != XVECLEN (subst_elem->data, 1))
2416 continue;
2417 patterns_match = 1;
2418 alternatives = -1;
2419 alternatives_subst = -1;
2420 for (j = 0; j < XVECLEN (elem->data, 1); j++)
2422 if (!subst_pattern_match (XVECEXP (elem->data, 1, j),
2423 XVECEXP (subst_elem->data, 1, j),
2424 subst_elem->loc))
2426 patterns_match = 0;
2427 break;
2430 if (!get_alternatives_number (XVECEXP (elem->data, 1, j),
2431 &alternatives, subst_elem->loc))
2433 patterns_match = 0;
2434 break;
2438 /* Check if numbers of alternatives are the same in all
2439 match_operands in output template of define_subst. */
2440 for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
2442 if (!get_alternatives_number (XVECEXP (subst_elem->data, 3, j),
2443 &alternatives_subst,
2444 subst_elem->loc))
2446 patterns_match = 0;
2447 break;
2451 if (!patterns_match)
2452 continue;
2454 /* Clear array in which we save occupied indexes of operands. */
2455 memset (used_operands_numbers, 0, sizeof (used_operands_numbers));
2457 /* Create a pattern, based on the output one from define_subst. */
2458 subst_pattern_vec = rtvec_alloc (XVECLEN (subst_elem->data, 3));
2459 for (j = 0; j < XVECLEN (subst_elem->data, 3); j++)
2461 subst_pattern = copy_rtx (XVECEXP (subst_elem->data, 3, j));
2463 /* Duplicate constraints in substitute-pattern. */
2464 subst_pattern = alter_constraints (subst_pattern, alternatives,
2465 duplicate_each_alternative);
2467 subst_pattern = adjust_operands_numbers (subst_pattern);
2469 /* Substitute match_dup and match_op_dup in the new pattern and
2470 duplicate constraints. */
2471 subst_pattern = subst_dup (subst_pattern, alternatives,
2472 alternatives_subst);
2474 replace_duplicating_operands_in_pattern (subst_pattern);
2476 /* We don't need any constraints in DEFINE_EXPAND. */
2477 if (GET_CODE (elem->data) == DEFINE_EXPAND)
2478 remove_constraints (subst_pattern);
2480 RTVEC_ELT (subst_pattern_vec, j) = subst_pattern;
2482 XVEC (elem->data, 1) = subst_pattern_vec;
2484 for (i = 0; i < MAX_OPERANDS; i++)
2485 match_operand_entries_in_pattern[i] = NULL;
2487 if (GET_CODE (elem->data) == DEFINE_INSN)
2489 XTMPL (elem->data, 3) =
2490 alter_output_for_subst_insn (elem->data, alternatives_subst);
2491 alter_attrs_for_subst_insn (elem, alternatives_subst);
2494 /* Recalculate condition, joining conditions from original and
2495 DEFINE_SUBST input patterns. */
2496 XSTR (elem->data, 2)
2497 = rtx_reader_ptr->join_c_conditions (XSTR (subst_elem->data, 2),
2498 XSTR (elem->data, 2));
2499 /* Mark that subst was applied by changing attribute from "yes"
2500 to "no". */
2501 change_subst_attribute (elem, subst_elem, subst_false);
2504 /* If ELEM contains a subst attribute with value "yes", then we
2505 expected that a subst would be applied, but it wasn't - so,
2506 we need to remove that elementto avoid duplicating. */
2507 for (subst_elem = define_subst_queue;
2508 subst_elem; subst_elem = subst_elem->next)
2510 if (has_subst_attribute (elem, subst_elem))
2512 remove_from_queue (elem, &queue);
2513 return;
2518 /* This is a subroutine of mark_operands_used_in_match_dup.
2519 This routine is marks all MATCH_OPERANDs inside PATTERN as occupied. */
2520 static void
2521 mark_operands_from_match_dup (rtx pattern)
2523 const char *fmt;
2524 int i, j, len, opno;
2526 if (GET_CODE (pattern) == MATCH_OPERAND
2527 || GET_CODE (pattern) == MATCH_OPERATOR
2528 || GET_CODE (pattern) == MATCH_PARALLEL)
2530 opno = XINT (pattern, 0);
2531 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2532 used_operands_numbers [opno] = 1;
2534 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2535 len = GET_RTX_LENGTH (GET_CODE (pattern));
2536 for (i = 0; i < len; i++)
2538 switch (fmt[i])
2540 case 'e': case 'u':
2541 mark_operands_from_match_dup (XEXP (pattern, i));
2542 break;
2543 case 'E':
2544 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2545 mark_operands_from_match_dup (XVECEXP (pattern, i, j));
2546 break;
2551 /* This is a subroutine of adjust_operands_numbers.
2552 It goes through all expressions in PATTERN and when MATCH_DUP is
2553 met, all MATCH_OPERANDs inside it is marked as occupied. The
2554 process of marking is done by routin mark_operands_from_match_dup. */
2555 static void
2556 mark_operands_used_in_match_dup (rtx pattern)
2558 const char *fmt;
2559 int i, j, len, opno;
2561 if (GET_CODE (pattern) == MATCH_DUP)
2563 opno = XINT (pattern, 0);
2564 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2565 mark_operands_from_match_dup (operand_data[opno]);
2566 return;
2568 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2569 len = GET_RTX_LENGTH (GET_CODE (pattern));
2570 for (i = 0; i < len; i++)
2572 switch (fmt[i])
2574 case 'e': case 'u':
2575 mark_operands_used_in_match_dup (XEXP (pattern, i));
2576 break;
2577 case 'E':
2578 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2579 mark_operands_used_in_match_dup (XVECEXP (pattern, i, j));
2580 break;
2585 /* This is subroutine of renumerate_operands_in_pattern.
2586 It finds first not-occupied operand-index. */
2587 static int
2588 find_first_unused_number_of_operand ()
2590 int i;
2591 for (i = 0; i < MAX_OPERANDS; i++)
2592 if (!used_operands_numbers[i])
2593 return i;
2594 return MAX_OPERANDS;
2597 /* This is subroutine of adjust_operands_numbers.
2598 It visits all expressions in PATTERN and assigns not-occupied
2599 operand indexes to MATCH_OPERANDs and MATCH_OPERATORs of this
2600 PATTERN. */
2601 static void
2602 renumerate_operands_in_pattern (rtx pattern)
2604 const char *fmt;
2605 enum rtx_code code;
2606 int i, j, len, new_opno;
2607 code = GET_CODE (pattern);
2609 if (code == MATCH_OPERAND
2610 || code == MATCH_OPERATOR)
2612 new_opno = find_first_unused_number_of_operand ();
2613 gcc_assert (new_opno >= 0 && new_opno < MAX_OPERANDS);
2614 XINT (pattern, 0) = new_opno;
2615 used_operands_numbers [new_opno] = 1;
2618 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2619 len = GET_RTX_LENGTH (GET_CODE (pattern));
2620 for (i = 0; i < len; i++)
2622 switch (fmt[i])
2624 case 'e': case 'u':
2625 renumerate_operands_in_pattern (XEXP (pattern, i));
2626 break;
2627 case 'E':
2628 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2629 renumerate_operands_in_pattern (XVECEXP (pattern, i, j));
2630 break;
2635 /* If output pattern of define_subst contains MATCH_DUP, then this
2636 expression would be replaced with the pattern, matched with
2637 MATCH_OPERAND from input pattern. This pattern could contain any
2638 number of MATCH_OPERANDs, MATCH_OPERATORs etc., so it's possible
2639 that a MATCH_OPERAND from output_pattern (if any) would have the
2640 same number, as MATCH_OPERAND from copied pattern. To avoid such
2641 indexes overlapping, we assign new indexes to MATCH_OPERANDs,
2642 laying in the output pattern outside of MATCH_DUPs. */
2643 static rtx
2644 adjust_operands_numbers (rtx pattern)
2646 mark_operands_used_in_match_dup (pattern);
2648 renumerate_operands_in_pattern (pattern);
2650 return pattern;
2653 /* Generate RTL expression
2654 (match_dup OPNO)
2656 static rtx
2657 generate_match_dup (int opno)
2659 rtx return_rtx = rtx_alloc (MATCH_DUP);
2660 PUT_CODE (return_rtx, MATCH_DUP);
2661 XINT (return_rtx, 0) = opno;
2662 return return_rtx;
2665 /* This routine checks all match_operands in PATTERN and if some of
2666 have the same index, it replaces all of them except the first one to
2667 match_dup.
2668 Usually, match_operands with the same indexes are forbidden, but
2669 after define_subst copy an RTL-expression from original template,
2670 indexes of existed and just-copied match_operands could coincide.
2671 To fix it, we replace one of them with match_dup. */
2672 static rtx
2673 replace_duplicating_operands_in_pattern (rtx pattern)
2675 const char *fmt;
2676 int i, j, len, opno;
2677 rtx mdup;
2679 if (GET_CODE (pattern) == MATCH_OPERAND)
2681 opno = XINT (pattern, 0);
2682 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2683 if (match_operand_entries_in_pattern[opno] == NULL)
2685 match_operand_entries_in_pattern[opno] = pattern;
2686 return NULL;
2688 else
2690 /* Compare predicates before replacing with match_dup. */
2691 if (strcmp (XSTR (pattern, 1),
2692 XSTR (match_operand_entries_in_pattern[opno], 1)))
2694 error ("duplicated match_operands with different predicates were"
2695 " found.");
2696 return NULL;
2698 return generate_match_dup (opno);
2701 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2702 len = GET_RTX_LENGTH (GET_CODE (pattern));
2703 for (i = 0; i < len; i++)
2705 switch (fmt[i])
2707 case 'e': case 'u':
2708 mdup = replace_duplicating_operands_in_pattern (XEXP (pattern, i));
2709 if (mdup)
2710 XEXP (pattern, i) = mdup;
2711 break;
2712 case 'E':
2713 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2715 mdup =
2716 replace_duplicating_operands_in_pattern (XVECEXP
2717 (pattern, i, j));
2718 if (mdup)
2719 XVECEXP (pattern, i, j) = mdup;
2721 break;
2724 return NULL;
2727 /* The routine modifies given input PATTERN of define_subst, replacing
2728 MATCH_DUP and MATCH_OP_DUP with operands from define_insn original
2729 pattern, whose operands are stored in OPERAND_DATA array.
2730 It also duplicates constraints in operands - constraints from
2731 define_insn operands are duplicated N_SUBST_ALT times, constraints
2732 from define_subst operands are duplicated N_ALT times.
2733 After the duplication, returned output rtl-pattern contains every
2734 combination of input constraints Vs constraints from define_subst
2735 output. */
2736 static rtx
2737 subst_dup (rtx pattern, int n_alt, int n_subst_alt)
2739 const char *fmt;
2740 enum rtx_code code;
2741 int i, j, len, opno;
2743 code = GET_CODE (pattern);
2744 switch (code)
2746 case MATCH_DUP:
2747 case MATCH_OP_DUP:
2748 opno = XINT (pattern, 0);
2750 gcc_assert (opno >= 0 && opno < MAX_OPERANDS);
2752 if (operand_data[opno])
2754 pattern = copy_rtx (operand_data[opno]);
2756 /* Duplicate constraints. */
2757 pattern = alter_constraints (pattern, n_subst_alt,
2758 duplicate_alternatives);
2760 break;
2762 default:
2763 break;
2766 fmt = GET_RTX_FORMAT (GET_CODE (pattern));
2767 len = GET_RTX_LENGTH (GET_CODE (pattern));
2768 for (i = 0; i < len; i++)
2770 switch (fmt[i])
2772 case 'e': case 'u':
2773 if (code != MATCH_DUP && code != MATCH_OP_DUP)
2774 XEXP (pattern, i) = subst_dup (XEXP (pattern, i),
2775 n_alt, n_subst_alt);
2776 break;
2777 case 'V':
2778 if (XVEC (pattern, i) == NULL)
2779 break;
2780 /* FALLTHRU */
2781 case 'E':
2782 if (code != MATCH_DUP && code != MATCH_OP_DUP)
2783 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
2784 XVECEXP (pattern, i, j) = subst_dup (XVECEXP (pattern, i, j),
2785 n_alt, n_subst_alt);
2786 break;
2788 case 'r': case 'p': case 'i': case 'w':
2789 case '0': case 's': case 'S': case 'T':
2790 case 'L':
2791 break;
2793 default:
2794 gcc_unreachable ();
2797 return pattern;
2800 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
2801 patterns appropriately. */
2803 static void
2804 process_define_cond_exec (void)
2806 class queue_elem *elem;
2808 identify_predicable_attribute ();
2809 if (have_error)
2810 return;
2812 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
2813 process_one_cond_exec (elem);
2816 /* If we have any DEFINE_SUBST patterns, expand DEFINE_INSN and
2817 DEFINE_EXPAND patterns appropriately. */
2819 static void
2820 process_define_subst (void)
2822 class queue_elem *elem, *elem_attr;
2824 /* Check if each define_subst has corresponding define_subst_attr. */
2825 for (elem = define_subst_queue; elem ; elem = elem->next)
2827 for (elem_attr = define_subst_attr_queue;
2828 elem_attr;
2829 elem_attr = elem_attr->next)
2830 if (strcmp (XSTR (elem->data, 0), XSTR (elem_attr->data, 1)) == 0)
2831 goto found;
2833 error_at (elem->loc,
2834 "%s: `define_subst' must have at least one "
2835 "corresponding `define_subst_attr'",
2836 XSTR (elem->data, 0));
2837 return;
2839 found:
2840 continue;
2843 for (elem = define_insn_queue; elem ; elem = elem->next)
2844 process_substs_on_one_elem (elem, define_insn_queue);
2845 for (elem = other_queue; elem ; elem = elem->next)
2847 if (GET_CODE (elem->data) != DEFINE_EXPAND)
2848 continue;
2849 process_substs_on_one_elem (elem, other_queue);
2853 /* A subclass of rtx_reader which reads .md files and calls process_rtx on
2854 the top-level elements. */
2856 class gen_reader : public rtx_reader
2858 public:
2859 gen_reader () : rtx_reader (false) {}
2860 void handle_unknown_directive (file_location, const char *) final override;
2863 void
2864 gen_reader::handle_unknown_directive (file_location loc, const char *rtx_name)
2866 auto_vec<rtx, 32> subrtxs;
2867 if (!read_rtx (rtx_name, &subrtxs))
2868 return;
2870 rtx x;
2871 unsigned int i;
2872 FOR_EACH_VEC_ELT (subrtxs, i, x)
2873 process_rtx (x, loc);
2876 /* Add mnemonic STR with length LEN to the mnemonic hash table
2877 MNEMONIC_HTAB. A trailing zero end character is appended to STR
2878 and a permanent heap copy of STR is created. */
2880 static void
2881 add_mnemonic_string (htab_t mnemonic_htab, const char *str, size_t len)
2883 char *new_str;
2884 void **slot;
2885 char *str_zero = (char*)alloca (len + 1);
2887 memcpy (str_zero, str, len);
2888 str_zero[len] = '\0';
2890 slot = htab_find_slot (mnemonic_htab, str_zero, INSERT);
2892 if (*slot)
2893 return;
2895 /* Not found; create a permanent copy and add it to the hash table. */
2896 new_str = XNEWVAR (char, len + 1);
2897 memcpy (new_str, str_zero, len + 1);
2898 *slot = new_str;
2901 /* Scan INSN for mnemonic strings and add them to the mnemonic hash
2902 table in MNEMONIC_HTAB.
2904 The mnemonics cannot be found if they are emitted using C code.
2906 If a mnemonic string contains ';' or a newline the string assumed
2907 to consist of more than a single instruction. The attribute value
2908 will then be set to the user defined default value. */
2910 static void
2911 gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
2913 const char *template_code, *cp;
2914 int i;
2915 int vec_len;
2916 rtx set_attr;
2917 char *attr_name;
2918 rtvec new_vec;
2919 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
2921 template_code = XTMPL (insn, 3);
2923 /* Skip patterns which use C code to emit the template. */
2924 if (template_code[0] == '*')
2925 return;
2927 if (template_code[0] == '@')
2928 cp = &template_code[1];
2929 else
2930 cp = &template_code[0];
2932 for (i = 0; *cp; )
2934 const char *ep, *sp;
2935 size_t size = 0;
2937 while (ISSPACE (*cp))
2938 cp++;
2940 for (ep = sp = cp; !IS_VSPACE (*ep) && *ep != '\0'; ++ep)
2941 if (!ISSPACE (*ep))
2942 sp = ep + 1;
2944 if (i > 0)
2945 obstack_1grow (string_obstack, ',');
2947 while (cp < sp && ((*cp >= '0' && *cp <= '9')
2948 || (*cp >= 'a' && *cp <= 'z')))
2951 obstack_1grow (string_obstack, *cp);
2952 cp++;
2953 size++;
2956 while (cp < sp)
2958 if (*cp == ';' || (*cp == '\\' && cp[1] == 'n'))
2960 /* Don't set a value if there are more than one
2961 instruction in the string. */
2962 obstack_blank_fast (string_obstack, -size);
2963 size = 0;
2965 cp = sp;
2966 break;
2968 cp++;
2970 if (size == 0)
2971 obstack_1grow (string_obstack, '*');
2972 else
2973 add_mnemonic_string (mnemonic_htab,
2974 (char *) obstack_next_free (string_obstack) - size,
2975 size);
2976 i++;
2979 /* An insn definition might emit an empty string. */
2980 if (obstack_object_size (string_obstack) == 0)
2981 return;
2983 obstack_1grow (string_obstack, '\0');
2985 set_attr = rtx_alloc (SET_ATTR);
2986 XSTR (set_attr, 1) = XOBFINISH (string_obstack, char *);
2987 attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
2988 strcpy (attr_name, MNEMONIC_ATTR_NAME);
2989 XSTR (set_attr, 0) = attr_name;
2991 if (!XVEC (insn, 4))
2992 vec_len = 0;
2993 else
2994 vec_len = XVECLEN (insn, 4);
2996 new_vec = rtvec_alloc (vec_len + 1);
2997 for (i = 0; i < vec_len; i++)
2998 RTVEC_ELT (new_vec, i) = XVECEXP (insn, 4, i);
2999 RTVEC_ELT (new_vec, vec_len) = set_attr;
3000 XVEC (insn, 4) = new_vec;
3003 /* This function is called for the elements in the mnemonic hashtable
3004 and generates a comma separated list of the mnemonics. */
3006 static int
3007 mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
3009 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
3011 obstack_grow (string_obstack, (char*) *slot, strlen ((char*) *slot));
3012 obstack_1grow (string_obstack, ',');
3013 return 1;
3016 /* Generate (set_attr "mnemonic" "..") RTXs and append them to every
3017 insn definition in case the back end requests it by defining the
3018 mnemonic attribute. The values for the attribute will be extracted
3019 from the output patterns of the insn definitions as far as
3020 possible. */
3022 static void
3023 gen_mnemonic_attr (void)
3025 class queue_elem *elem;
3026 rtx mnemonic_attr = NULL;
3027 htab_t mnemonic_htab;
3028 const char *str, *p;
3029 int i;
3030 struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
3032 if (have_error)
3033 return;
3035 /* Look for the DEFINE_ATTR for `mnemonic'. */
3036 for (elem = define_attr_queue; elem != *define_attr_tail; elem = elem->next)
3037 if (GET_CODE (elem->data) == DEFINE_ATTR
3038 && strcmp (XSTR (elem->data, 0), MNEMONIC_ATTR_NAME) == 0)
3040 mnemonic_attr = elem->data;
3041 break;
3044 /* A (define_attr "mnemonic" "...") indicates that the back-end
3045 wants a mnemonic attribute to be generated. */
3046 if (!mnemonic_attr)
3047 return;
3049 mnemonic_htab = htab_create_alloc (MNEMONIC_HTAB_SIZE, htab_hash_string,
3050 htab_eq_string, 0, xcalloc, free);
3052 for (elem = define_insn_queue; elem; elem = elem->next)
3054 rtx insn = elem->data;
3055 bool found = false;
3057 /* Check if the insn definition already has
3058 (set_attr "mnemonic" ...) or (set (attr "mnemonic") ...). */
3059 if (XVEC (insn, 4))
3060 for (i = 0; i < XVECLEN (insn, 4); i++)
3062 rtx set_attr = XVECEXP (insn, 4, i);
3064 switch (GET_CODE (set_attr))
3066 case SET_ATTR:
3067 case SET_ATTR_ALTERNATIVE:
3068 if (strcmp (XSTR (set_attr, 0), MNEMONIC_ATTR_NAME) == 0)
3069 found = true;
3070 break;
3071 case SET:
3072 if (GET_CODE (SET_DEST (set_attr)) == ATTR
3073 && strcmp (XSTR (SET_DEST (set_attr), 0),
3074 MNEMONIC_ATTR_NAME) == 0)
3075 found = true;
3076 break;
3077 default:
3078 break;
3082 if (!found)
3083 gen_mnemonic_setattr (mnemonic_htab, insn);
3086 /* Add the user defined values to the hash table. */
3087 str = XSTR (mnemonic_attr, 1);
3088 while ((p = scan_comma_elt (&str)) != NULL)
3089 add_mnemonic_string (mnemonic_htab, p, str - p);
3091 htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
3093 /* Replace the last ',' with the zero end character. */
3094 *((char *) obstack_next_free (string_obstack) - 1) = '\0';
3095 XSTR (mnemonic_attr, 1) = XOBFINISH (string_obstack, char *);
3098 /* Check if there are DEFINE_ATTRs with the same name. */
3099 static void
3100 check_define_attr_duplicates ()
3102 class queue_elem *elem;
3103 htab_t attr_htab;
3104 char * attr_name;
3105 void **slot;
3107 attr_htab = htab_create (500, htab_hash_string, htab_eq_string, NULL);
3109 for (elem = define_attr_queue; elem; elem = elem->next)
3111 attr_name = xstrdup (XSTR (elem->data, 0));
3113 slot = htab_find_slot (attr_htab, attr_name, INSERT);
3115 /* Duplicate. */
3116 if (*slot)
3118 error_at (elem->loc, "redefinition of attribute '%s'", attr_name);
3119 htab_delete (attr_htab);
3120 return;
3123 *slot = attr_name;
3126 htab_delete (attr_htab);
3129 /* The entry point for initializing the reader. */
3131 rtx_reader *
3132 init_rtx_reader_args_cb (int argc, const char **argv,
3133 bool (*parse_opt) (const char *))
3135 /* Prepare to read input. */
3136 condition_table = htab_create (500, hash_c_test, cmp_c_test, NULL);
3137 init_predicate_table ();
3138 obstack_init (rtl_obstack);
3140 /* Start at 1, to make 0 available for CODE_FOR_nothing. */
3141 insn_sequence_num = 1;
3143 /* These sequences are not used as indices, so can start at 1 also. */
3144 split_sequence_num = 1;
3145 peephole2_sequence_num = 1;
3147 gen_reader *reader = new gen_reader ();
3148 reader->read_md_files (argc, argv, parse_opt);
3150 if (define_attr_queue != NULL)
3151 check_define_attr_duplicates ();
3153 /* Process define_cond_exec patterns. */
3154 if (define_cond_exec_queue != NULL)
3155 process_define_cond_exec ();
3157 /* Process define_subst patterns. */
3158 if (define_subst_queue != NULL)
3159 process_define_subst ();
3161 if (define_attr_queue != NULL)
3162 gen_mnemonic_attr ();
3164 if (have_error)
3166 delete reader;
3167 return NULL;
3170 return reader;
3173 /* Programs that don't have their own options can use this entry point
3174 instead. */
3175 rtx_reader *
3176 init_rtx_reader_args (int argc, const char **argv)
3178 return init_rtx_reader_args_cb (argc, argv, 0);
3181 /* Count the number of patterns in all queues and return the count. */
3183 count_patterns ()
3185 int count = 0, truth = 1;
3186 rtx def;
3187 class queue_elem *cur = define_attr_queue;
3188 while (cur)
3190 def = cur->data;
3192 truth = maybe_eval_c_test (get_c_test (def));
3193 if (truth || !insn_elision)
3194 count++;
3195 cur = cur->next;
3198 cur = define_pred_queue;
3199 while (cur)
3201 def = cur->data;
3203 truth = maybe_eval_c_test (get_c_test (def));
3204 if (truth || !insn_elision)
3205 count++;
3206 cur = cur->next;
3209 cur = define_insn_queue;
3210 truth = 1;
3211 while (cur)
3213 def = cur->data;
3215 truth = maybe_eval_c_test (get_c_test (def));
3216 if (truth || !insn_elision)
3217 count++;
3218 cur = cur->next;
3221 cur = other_queue;
3222 truth = 1;
3223 while (cur)
3225 def = cur->data;
3227 truth = maybe_eval_c_test (get_c_test (def));
3228 if (truth || !insn_elision)
3229 count++;
3230 cur = cur->next;
3233 return count;
3236 /* Try to read a single rtx from the file. Return true on success,
3237 describing it in *INFO. */
3239 bool
3240 read_md_rtx (md_rtx_info *info)
3242 int truth, *counter;
3243 rtx def;
3245 /* Discard insn patterns which we know can never match (because
3246 their C test is provably always false). If insn_elision is
3247 false, our caller needs to see all the patterns. Note that the
3248 elided patterns are never counted by the sequence numbering; it
3249 is the caller's responsibility, when insn_elision is false, not
3250 to use elided pattern numbers for anything. */
3253 class queue_elem **queue, *elem;
3255 /* Read all patterns from a given queue before moving on to the next. */
3256 if (define_attr_queue != NULL)
3257 queue = &define_attr_queue;
3258 else if (define_pred_queue != NULL)
3259 queue = &define_pred_queue;
3260 else if (define_insn_queue != NULL)
3261 queue = &define_insn_queue;
3262 else if (other_queue != NULL)
3263 queue = &other_queue;
3264 else
3265 return false;
3267 elem = *queue;
3268 *queue = elem->next;
3269 def = elem->data;
3270 info->def = def;
3271 info->loc = elem->loc;
3272 free (elem);
3274 truth = maybe_eval_c_test (get_c_test (def));
3276 while (truth == 0 && insn_elision);
3278 /* Perform code-specific processing and pick the appropriate sequence
3279 number counter. */
3280 switch (GET_CODE (def))
3282 case DEFINE_INSN:
3283 case DEFINE_EXPAND:
3284 /* insn_sequence_num is used here so the name table will match caller's
3285 idea of insn numbering, whether or not elision is active. */
3286 record_insn_name (insn_sequence_num, XSTR (def, 0));
3288 /* Fall through. */
3289 case DEFINE_PEEPHOLE:
3290 counter = &insn_sequence_num;
3291 break;
3293 case DEFINE_SPLIT:
3294 counter = &split_sequence_num;
3295 break;
3297 case DEFINE_PEEPHOLE2:
3298 counter = &peephole2_sequence_num;
3299 break;
3301 default:
3302 counter = NULL;
3303 break;
3306 if (counter)
3308 info->index = *counter;
3309 if (truth != 0)
3310 *counter += 1;
3312 else
3313 info->index = -1;
3315 if (!rtx_locs)
3316 rtx_locs = new hash_map <rtx, file_location>;
3317 rtx_locs->put (info->def, info->loc);
3319 return true;
3322 /* Return the file location of DEFINE_* rtx X, which was previously
3323 returned by read_md_rtx. */
3324 file_location
3325 get_file_location (rtx x)
3327 gcc_assert (rtx_locs);
3328 file_location *entry = rtx_locs->get (x);
3329 gcc_assert (entry);
3330 return *entry;
3333 /* Return the number of possible INSN_CODEs. Only meaningful once the
3334 whole file has been processed. */
3335 unsigned int
3336 get_num_insn_codes ()
3338 return insn_sequence_num;
3341 /* Return the C test that says whether definition rtx DEF can be used,
3342 or "" if it can be used unconditionally. */
3344 const char *
3345 get_c_test (rtx x)
3347 switch (GET_CODE (x))
3349 case DEFINE_INSN:
3350 case DEFINE_EXPAND:
3351 case DEFINE_SUBST:
3352 return XSTR (x, 2);
3354 case DEFINE_SPLIT:
3355 case DEFINE_PEEPHOLE:
3356 case DEFINE_PEEPHOLE2:
3357 return XSTR (x, 1);
3359 default:
3360 return "";
3364 /* Helper functions for insn elision. */
3366 /* Compute a hash function of a c_test structure, which is keyed
3367 by its ->expr field. */
3368 hashval_t
3369 hash_c_test (const void *x)
3371 const struct c_test *a = (const struct c_test *) x;
3372 const unsigned char *base, *s = (const unsigned char *) a->expr;
3373 hashval_t hash;
3374 unsigned char c;
3375 unsigned int len;
3377 base = s;
3378 hash = 0;
3380 while ((c = *s++) != '\0')
3382 hash += c + (c << 17);
3383 hash ^= hash >> 2;
3386 len = s - base;
3387 hash += len + (len << 17);
3388 hash ^= hash >> 2;
3390 return hash;
3393 /* Compare two c_test expression structures. */
3395 cmp_c_test (const void *x, const void *y)
3397 const struct c_test *a = (const struct c_test *) x;
3398 const struct c_test *b = (const struct c_test *) y;
3400 return !strcmp (a->expr, b->expr);
3403 /* Given a string representing a C test expression, look it up in the
3404 condition_table and report whether or not its value is known
3405 at compile time. Returns a tristate: 1 for known true, 0 for
3406 known false, -1 for unknown. */
3408 maybe_eval_c_test (const char *expr)
3410 const struct c_test *test;
3411 struct c_test dummy;
3413 if (expr[0] == 0)
3414 return 1;
3416 dummy.expr = expr;
3417 test = (const struct c_test *)htab_find (condition_table, &dummy);
3418 if (!test)
3419 return -1;
3420 return test->value;
3423 /* Record the C test expression EXPR in the condition_table, with
3424 value VAL. Duplicates clobber previous entries. */
3426 void
3427 add_c_test (const char *expr, int value)
3429 struct c_test *test;
3431 if (expr[0] == 0)
3432 return;
3434 test = XNEW (struct c_test);
3435 test->expr = expr;
3436 test->value = value;
3438 *(htab_find_slot (condition_table, test, INSERT)) = test;
3441 /* For every C test, call CALLBACK with two arguments: a pointer to
3442 the condition structure and INFO. Stops when CALLBACK returns zero. */
3443 void
3444 traverse_c_tests (htab_trav callback, void *info)
3446 if (condition_table)
3447 htab_traverse (condition_table, callback, info);
3450 /* Helper functions for define_predicate and define_special_predicate
3451 processing. Shared between genrecog.cc and genpreds.cc. */
3453 static htab_t predicate_table;
3454 struct pred_data *first_predicate;
3455 static struct pred_data **last_predicate = &first_predicate;
3457 static hashval_t
3458 hash_struct_pred_data (const void *ptr)
3460 return htab_hash_string (((const struct pred_data *)ptr)->name);
3463 static int
3464 eq_struct_pred_data (const void *a, const void *b)
3466 return !strcmp (((const struct pred_data *)a)->name,
3467 ((const struct pred_data *)b)->name);
3470 struct pred_data *
3471 lookup_predicate (const char *name)
3473 struct pred_data key;
3474 key.name = name;
3475 return (struct pred_data *) htab_find (predicate_table, &key);
3478 /* Record that predicate PRED can accept CODE. */
3480 void
3481 add_predicate_code (struct pred_data *pred, enum rtx_code code)
3483 if (!pred->codes[code])
3485 pred->num_codes++;
3486 pred->codes[code] = true;
3488 if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
3489 pred->allows_non_const = true;
3491 if (code != REG
3492 && code != SUBREG
3493 && code != MEM
3494 && code != CONCAT
3495 && code != PARALLEL
3496 && code != STRICT_LOW_PART
3497 && code != ZERO_EXTRACT
3498 && code != SCRATCH)
3499 pred->allows_non_lvalue = true;
3501 if (pred->num_codes == 1)
3502 pred->singleton = code;
3503 else if (pred->num_codes == 2)
3504 pred->singleton = UNKNOWN;
3508 void
3509 add_predicate (struct pred_data *pred)
3511 void **slot = htab_find_slot (predicate_table, pred, INSERT);
3512 if (*slot)
3514 error ("duplicate predicate definition for '%s'", pred->name);
3515 return;
3517 *slot = pred;
3518 *last_predicate = pred;
3519 last_predicate = &pred->next;
3522 /* This array gives the initial content of the predicate table. It
3523 has entries for all predicates defined in recog.cc. */
3525 struct std_pred_table
3527 const char *name;
3528 bool special;
3529 bool allows_const_p;
3530 RTX_CODE codes[NUM_RTX_CODE];
3533 static const struct std_pred_table std_preds[] = {
3534 {"general_operand", false, true, {SUBREG, REG, MEM}},
3535 {"address_operand", true, true, {SUBREG, REG, MEM, PLUS, MINUS, MULT,
3536 ZERO_EXTEND, SIGN_EXTEND, AND}},
3537 {"register_operand", false, false, {SUBREG, REG}},
3538 {"pmode_register_operand", true, false, {SUBREG, REG}},
3539 {"scratch_operand", false, false, {SCRATCH, REG}},
3540 {"immediate_operand", false, true, {UNKNOWN}},
3541 {"const_int_operand", false, false, {CONST_INT}},
3542 #if TARGET_SUPPORTS_WIDE_INT
3543 {"const_scalar_int_operand", false, false, {CONST_INT, CONST_WIDE_INT}},
3544 {"const_double_operand", false, false, {CONST_DOUBLE}},
3545 #else
3546 {"const_double_operand", false, false, {CONST_INT, CONST_DOUBLE}},
3547 #endif
3548 {"nonimmediate_operand", false, false, {SUBREG, REG, MEM}},
3549 {"nonmemory_operand", false, true, {SUBREG, REG}},
3550 {"push_operand", false, false, {MEM}},
3551 {"pop_operand", false, false, {MEM}},
3552 {"memory_operand", false, false, {SUBREG, MEM}},
3553 {"indirect_operand", false, false, {SUBREG, MEM}},
3554 {"ordered_comparison_operator", false, false, {EQ, NE,
3555 LE, LT, GE, GT,
3556 LEU, LTU, GEU, GTU}},
3557 {"comparison_operator", false, false, {EQ, NE,
3558 LE, LT, GE, GT,
3559 LEU, LTU, GEU, GTU,
3560 UNORDERED, ORDERED,
3561 UNEQ, UNGE, UNGT,
3562 UNLE, UNLT, LTGT}}
3564 #define NUM_KNOWN_STD_PREDS ARRAY_SIZE (std_preds)
3566 /* Initialize the table of predicate definitions, starting with
3567 the information we have on generic predicates. */
3569 static void
3570 init_predicate_table (void)
3572 size_t i, j;
3573 struct pred_data *pred;
3575 predicate_table = htab_create_alloc (37, hash_struct_pred_data,
3576 eq_struct_pred_data, 0,
3577 xcalloc, free);
3579 for (i = 0; i < NUM_KNOWN_STD_PREDS; i++)
3581 pred = XCNEW (struct pred_data);
3582 pred->name = std_preds[i].name;
3583 pred->special = std_preds[i].special;
3585 for (j = 0; std_preds[i].codes[j] != 0; j++)
3586 add_predicate_code (pred, std_preds[i].codes[j]);
3588 if (std_preds[i].allows_const_p)
3589 for (j = 0; j < NUM_RTX_CODE; j++)
3590 if (GET_RTX_CLASS (j) == RTX_CONST_OBJ)
3591 add_predicate_code (pred, (enum rtx_code) j);
3593 add_predicate (pred);
3597 /* These functions allow linkage with print-rtl.cc. Also, some generators
3598 like to annotate their output with insn names. */
3600 /* Holds an array of names indexed by insn_code_number. */
3601 static char **insn_name_ptr = 0;
3602 static int insn_name_ptr_size = 0;
3604 const char *
3605 get_insn_name (int code)
3607 if (code < insn_name_ptr_size)
3608 return insn_name_ptr[code];
3609 else
3610 return NULL;
3613 static void
3614 record_insn_name (int code, const char *name)
3616 static const char *last_real_name = "insn";
3617 static int last_real_code = 0;
3618 char *new_name;
3620 if (insn_name_ptr_size <= code)
3622 int new_size;
3623 new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
3624 insn_name_ptr = XRESIZEVEC (char *, insn_name_ptr, new_size);
3625 memset (insn_name_ptr + insn_name_ptr_size, 0,
3626 sizeof (char *) * (new_size - insn_name_ptr_size));
3627 insn_name_ptr_size = new_size;
3630 if (!name || name[0] == '\0')
3632 new_name = XNEWVAR (char, strlen (last_real_name) + 10);
3633 sprintf (new_name, "%s+%d", last_real_name, code - last_real_code);
3635 else
3637 last_real_name = new_name = xstrdup (name);
3638 last_real_code = code;
3641 insn_name_ptr[code] = new_name;
3644 /* Make STATS describe the operands that appear in rtx X. */
3646 static void
3647 get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
3649 RTX_CODE code;
3650 int i;
3651 int len;
3652 const char *fmt;
3654 if (x == NULL_RTX)
3655 return;
3657 code = GET_CODE (x);
3658 switch (code)
3660 case MATCH_OPERAND:
3661 case MATCH_OPERATOR:
3662 case MATCH_PARALLEL:
3663 stats->max_opno = MAX (stats->max_opno, XINT (x, 0));
3664 break;
3666 case MATCH_DUP:
3667 case MATCH_OP_DUP:
3668 case MATCH_PAR_DUP:
3669 stats->num_dups++;
3670 stats->max_dup_opno = MAX (stats->max_dup_opno, XINT (x, 0));
3671 break;
3673 case MATCH_SCRATCH:
3674 if (stats->min_scratch_opno == -1)
3675 stats->min_scratch_opno = XINT (x, 0);
3676 else
3677 stats->min_scratch_opno = MIN (stats->min_scratch_opno, XINT (x, 0));
3678 stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
3679 break;
3681 default:
3682 break;
3685 fmt = GET_RTX_FORMAT (code);
3686 len = GET_RTX_LENGTH (code);
3687 for (i = 0; i < len; i++)
3689 if (fmt[i] == 'e' || fmt[i] == 'u')
3690 get_pattern_stats_1 (stats, XEXP (x, i));
3691 else if (fmt[i] == 'E')
3693 int j;
3694 for (j = 0; j < XVECLEN (x, i); j++)
3695 get_pattern_stats_1 (stats, XVECEXP (x, i, j));
3700 /* Make STATS describe the operands that appear in instruction pattern
3701 PATTERN. */
3703 void
3704 get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
3706 int i, len;
3708 stats->max_opno = -1;
3709 stats->max_dup_opno = -1;
3710 stats->min_scratch_opno = -1;
3711 stats->max_scratch_opno = -1;
3712 stats->num_dups = 0;
3714 len = GET_NUM_ELEM (pattern);
3715 for (i = 0; i < len; i++)
3716 get_pattern_stats_1 (stats, RTVEC_ELT (pattern, i));
3718 stats->num_generator_args = stats->max_opno + 1;
3719 stats->num_insn_operands = MAX (stats->max_opno,
3720 stats->max_scratch_opno) + 1;
3721 stats->num_operand_vars = MAX (stats->max_opno,
3722 MAX (stats->max_dup_opno,
3723 stats->max_scratch_opno)) + 1;
3726 /* Return the emit_* function that should be used for pattern X, or NULL
3727 if we can't pick a particular type at compile time and should instead
3728 fall back to "emit". */
3730 const char *
3731 get_emit_function (rtx x)
3733 switch (classify_insn (x))
3735 case INSN:
3736 return "emit_insn";
3738 case CALL_INSN:
3739 return "emit_call_insn";
3741 case JUMP_INSN:
3742 return "emit_jump_insn";
3744 case UNKNOWN:
3745 return NULL;
3747 default:
3748 gcc_unreachable ();
3752 /* Return true if we must emit a barrier after pattern X. */
3754 bool
3755 needs_barrier_p (rtx x)
3757 return (GET_CODE (x) == SET
3758 && GET_CODE (SET_DEST (x)) == PC
3759 && GET_CODE (SET_SRC (x)) == LABEL_REF);
3762 #define NS "NULL"
3763 #define ZS "'\\0'"
3764 #define OPTAB_CL(o, p, c, b, l) { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
3765 #define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
3766 #define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
3767 #define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
3768 #define OPTAB_NC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 3 },
3769 #define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3770 #define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
3771 #define OPTAB_VC(o, p, c) { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
3772 #define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
3773 #define OPTAB_DC(o, p, c) { #o, p, NS, ZS, NS, o, c, c, 4 },
3774 #define OPTAB_D(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
3776 /* An array of all optabs. Note that the same optab can appear more
3777 than once, with a different pattern. */
3778 optab_def optabs[] = {
3779 { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
3780 #include "optabs.def"
3783 /* The number of entries in optabs[]. */
3784 unsigned int num_optabs = ARRAY_SIZE (optabs);
3786 #undef OPTAB_CL
3787 #undef OPTAB_CX
3788 #undef OPTAB_CD
3789 #undef OPTAB_NL
3790 #undef OPTAB_NC
3791 #undef OPTAB_NX
3792 #undef OPTAB_VL
3793 #undef OPTAB_VC
3794 #undef OPTAB_VX
3795 #undef OPTAB_DC
3796 #undef OPTAB_D
3798 /* Return true if instruction NAME matches pattern PAT, storing information
3799 about the match in P if so. */
3801 static bool
3802 match_pattern (optab_pattern *p, const char *name, const char *pat)
3804 bool force_float = false;
3805 bool force_int = false;
3806 bool force_partial_int = false;
3807 bool force_fixed = false;
3809 if (pat == NULL)
3810 return false;
3811 for (; ; ++pat)
3813 if (*pat != '$')
3815 if (*pat != *name++)
3816 return false;
3817 if (*pat == '\0')
3818 return true;
3819 continue;
3821 switch (*++pat)
3823 case 'I':
3824 force_int = 1;
3825 break;
3826 case 'P':
3827 force_partial_int = 1;
3828 break;
3829 case 'F':
3830 force_float = 1;
3831 break;
3832 case 'Q':
3833 force_fixed = 1;
3834 break;
3836 case 'a':
3837 case 'b':
3839 int i;
3841 /* This loop will stop at the first prefix match, so
3842 look through the modes in reverse order, in case
3843 there are extra CC modes and CC is a prefix of the
3844 CC modes (as it should be). */
3845 for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
3847 const char *p, *q;
3848 for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
3849 if (TOLOWER (*p) != *q)
3850 break;
3851 if (*p == 0
3852 && (! force_int || mode_class[i] == MODE_INT
3853 || mode_class[i] == MODE_VECTOR_INT)
3854 && (! force_partial_int
3855 || mode_class[i] == MODE_INT
3856 || mode_class[i] == MODE_PARTIAL_INT
3857 || mode_class[i] == MODE_VECTOR_INT)
3858 && (! force_float
3859 || mode_class[i] == MODE_FLOAT
3860 || mode_class[i] == MODE_DECIMAL_FLOAT
3861 || mode_class[i] == MODE_COMPLEX_FLOAT
3862 || mode_class[i] == MODE_VECTOR_FLOAT)
3863 && (! force_fixed
3864 || mode_class[i] == MODE_FRACT
3865 || mode_class[i] == MODE_UFRACT
3866 || mode_class[i] == MODE_ACCUM
3867 || mode_class[i] == MODE_UACCUM
3868 || mode_class[i] == MODE_VECTOR_FRACT
3869 || mode_class[i] == MODE_VECTOR_UFRACT
3870 || mode_class[i] == MODE_VECTOR_ACCUM
3871 || mode_class[i] == MODE_VECTOR_UACCUM))
3872 break;
3875 if (i < 0)
3876 return false;
3877 name += strlen (GET_MODE_NAME (i));
3878 if (*pat == 'a')
3879 p->m1 = i;
3880 else
3881 p->m2 = i;
3883 force_int = false;
3884 force_partial_int = false;
3885 force_float = false;
3886 force_fixed = false;
3888 break;
3890 default:
3891 gcc_unreachable ();
3896 /* Return true if NAME is the name of an optab, describing it in P if so. */
3898 bool
3899 find_optab (optab_pattern *p, const char *name)
3901 if (*name == 0 || *name == '*')
3902 return false;
3904 /* See if NAME matches one of the patterns we have for the optabs
3905 we know about. */
3906 for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
3908 p->m1 = p->m2 = 0;
3909 if (match_pattern (p, name, optabs[pindex].pattern))
3911 p->name = name;
3912 p->op = optabs[pindex].op;
3913 p->sort_num = (p->op << 20) | (p->m2 << 10) | p->m1;
3914 return true;
3917 return false;
3920 /* Find the file to write into next. We try to evenly distribute the contents
3921 over the different files. */
3923 #define SIZED_BASED_CHUNKS 1
3925 FILE *
3926 choose_output (const vec<FILE *> &parts, unsigned &idx)
3928 if (parts.length () == 0)
3929 gcc_unreachable ();
3930 #ifdef SIZED_BASED_CHUNKS
3931 FILE *shortest = NULL;
3932 long min = 0;
3933 idx = 0;
3934 for (unsigned i = 0; i < parts.length (); i++)
3936 FILE *part = parts[i];
3937 long len = ftell (part);
3938 if (!shortest || min > len)
3940 shortest = part;
3941 min = len;
3942 idx = i;
3945 return shortest;
3946 #else
3947 static int current_file;
3948 idx = current_file++ % parts.length ();
3949 return parts[idx];
3950 #endif