gensupport.c (init_include_reader): Merge into ...
[gcc.git] / gcc / gensupport.c
1 /* Support routines for the various generation passes.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include "hconfig.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "obstack.h"
25 #include "errors.h"
26 #include "gensupport.h"
27
28
29 /* In case some macros used by files we include need it, define this here. */
30 int target_flags;
31
32 static struct obstack obstack;
33 struct obstack *rtl_obstack = &obstack;
34
35 #define obstack_chunk_alloc xmalloc
36 #define obstack_chunk_free free
37
38 static int sequence_num;
39 static int errors;
40
41 static int predicable_default;
42 static const char *predicable_true;
43 static const char *predicable_false;
44
45 static char *base_dir = NULL;
46
47 /* We initially queue all patterns, process the define_insn and
48 define_cond_exec patterns, then return them one at a time. */
49
50 struct queue_elem
51 {
52 rtx data;
53 int lineno;
54 struct queue_elem *next;
55 };
56
57 static struct queue_elem *define_attr_queue;
58 static struct queue_elem **define_attr_tail = &define_attr_queue;
59 static struct queue_elem *define_insn_queue;
60 static struct queue_elem **define_insn_tail = &define_insn_queue;
61 static struct queue_elem *define_cond_exec_queue;
62 static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
63 static struct queue_elem *other_queue;
64 static struct queue_elem **other_tail = &other_queue;
65
66 static void queue_pattern PARAMS ((rtx, struct queue_elem ***, int));
67
68 /* Current maximum length of directory names in the search path
69 for include files. (Altered as we get more of them.) */
70
71 size_t max_include_len;
72
73 struct file_name_list
74 {
75 struct file_name_list *next;
76 const char *fname;
77 };
78
79 struct file_name_list *first_dir_md_include = 0; /* First dir to search */
80 /* First dir to search for <file> */
81 struct file_name_list *first_bracket_include = 0;
82 struct file_name_list *last_dir_md_include = 0; /* Last in chain */
83
84 static void remove_constraints PARAMS ((rtx));
85 static void process_rtx PARAMS ((rtx, int));
86
87 static int is_predicable PARAMS ((struct queue_elem *));
88 static void identify_predicable_attribute PARAMS ((void));
89 static int n_alternatives PARAMS ((const char *));
90 static void collect_insn_data PARAMS ((rtx, int *, int *));
91 static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
92 static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
93 struct queue_elem *));
94 static char *shift_output_template PARAMS ((char *, const char *, int));
95 static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
96 struct queue_elem *,
97 int, int));
98 static void process_one_cond_exec PARAMS ((struct queue_elem *));
99 static void process_define_cond_exec PARAMS ((void));
100 static void process_include PARAMS ((rtx, int));
101 static char *save_string PARAMS ((const char *, int));
102 \f
103 void
104 message_with_line VPARAMS ((int lineno, const char *msg, ...))
105 {
106 VA_OPEN (ap, msg);
107 VA_FIXEDARG (ap, int, lineno);
108 VA_FIXEDARG (ap, const char *, msg);
109
110 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
111 vfprintf (stderr, msg, ap);
112 fputc ('\n', stderr);
113
114 VA_CLOSE (ap);
115 }
116
117 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
118 the gensupport programs. */
119
120 rtx
121 gen_rtx_CONST_INT (mode, arg)
122 enum machine_mode mode ATTRIBUTE_UNUSED;
123 HOST_WIDE_INT arg;
124 {
125 rtx rt = rtx_alloc (CONST_INT);
126
127 XWINT (rt, 0) = arg;
128 return rt;
129 }
130 \f
131 /* Queue PATTERN on LIST_TAIL. */
132
133 static void
134 queue_pattern (pattern, list_tail, lineno)
135 rtx pattern;
136 struct queue_elem ***list_tail;
137 int lineno;
138 {
139 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
140 e->data = pattern;
141 e->lineno = lineno;
142 e->next = NULL;
143 **list_tail = e;
144 *list_tail = &e->next;
145 }
146
147 /* Recursively remove constraints from an rtx. */
148
149 static void
150 remove_constraints (part)
151 rtx part;
152 {
153 int i, j;
154 const char *format_ptr;
155
156 if (part == 0)
157 return;
158
159 if (GET_CODE (part) == MATCH_OPERAND)
160 XSTR (part, 2) = "";
161 else if (GET_CODE (part) == MATCH_SCRATCH)
162 XSTR (part, 1) = "";
163
164 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
165
166 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
167 switch (*format_ptr++)
168 {
169 case 'e':
170 case 'u':
171 remove_constraints (XEXP (part, i));
172 break;
173 case 'E':
174 if (XVEC (part, i) != NULL)
175 for (j = 0; j < XVECLEN (part, i); j++)
176 remove_constraints (XVECEXP (part, i, j));
177 break;
178 }
179 }
180
181 /* Process an include file assuming that it lives in gcc/config/{target}/
182 if the include looks line (include "file"). */
183
184 static void
185 process_include (desc, lineno)
186 rtx desc;
187 int lineno;
188 {
189 const char *filename = XSTR (desc, 0);
190 const char *old_filename;
191 int old_lineno;
192 char *pathname;
193 FILE *input_file;
194
195 /* If specified file name is absolute, skip the include stack. */
196 if (! IS_ABSOLUTE_PATHNAME (filename))
197 {
198 struct file_name_list *stackp;
199
200 /* Search directory path, trying to open the file. */
201 for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
202 {
203 static const char sep[2] = { DIR_SEPARATOR, '\0' };
204
205 pathname = concat (stackp->fname, sep, filename, NULL);
206 input_file = fopen (pathname, "r");
207 if (input_file != NULL)
208 goto success;
209 free (pathname);
210 }
211 }
212
213 if (base_dir)
214 pathname = concat (base_dir, filename, NULL);
215 else
216 pathname = xstrdup (filename);
217 input_file = fopen (pathname, "r");
218 if (input_file == NULL)
219 {
220 free (pathname);
221 message_with_line (lineno, "include file `%s' not found", filename);
222 errors = 1;
223 return;
224 }
225 success:
226
227 /* Save old cursor; setup new for the new file. Note that "lineno" the
228 argument to this function is the beginning of the include statement,
229 while read_rtx_lineno has already been advanced. */
230 old_filename = read_rtx_filename;
231 old_lineno = read_rtx_lineno;
232 read_rtx_filename = pathname;
233 read_rtx_lineno = 1;
234
235 /* Read the entire file. */
236 while (1)
237 {
238 rtx desc;
239 int c;
240
241 c = read_skip_spaces (input_file);
242 if (c == EOF)
243 break;
244
245 ungetc (c, input_file);
246 lineno = read_rtx_lineno;
247 desc = read_rtx (input_file);
248 process_rtx (desc, lineno);
249 }
250
251 read_rtx_filename = old_filename;
252 read_rtx_lineno = old_lineno;
253
254 fclose (input_file);
255 free (pathname);
256 }
257
258 /* Process a top level rtx in some way, queueing as appropriate. */
259
260 static void
261 process_rtx (desc, lineno)
262 rtx desc;
263 int lineno;
264 {
265 switch (GET_CODE (desc))
266 {
267 case DEFINE_INSN:
268 queue_pattern (desc, &define_insn_tail, lineno);
269 break;
270
271 case DEFINE_COND_EXEC:
272 queue_pattern (desc, &define_cond_exec_tail, lineno);
273 break;
274
275 case DEFINE_ATTR:
276 queue_pattern (desc, &define_attr_tail, lineno);
277 break;
278
279 case INCLUDE:
280 process_include (desc, lineno);
281 break;
282
283 case DEFINE_INSN_AND_SPLIT:
284 {
285 const char *split_cond;
286 rtx split;
287 rtvec attr;
288 int i;
289
290 /* Create a split with values from the insn_and_split. */
291 split = rtx_alloc (DEFINE_SPLIT);
292
293 i = XVECLEN (desc, 1);
294 XVEC (split, 0) = rtvec_alloc (i);
295 while (--i >= 0)
296 {
297 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
298 remove_constraints (XVECEXP (split, 0, i));
299 }
300
301 /* If the split condition starts with "&&", append it to the
302 insn condition to create the new split condition. */
303 split_cond = XSTR (desc, 4);
304 if (split_cond[0] == '&' && split_cond[1] == '&')
305 {
306 const char *insn_cond = XSTR (desc, 2);
307 size_t insn_cond_len = strlen (insn_cond);
308 size_t split_cond_len = strlen (split_cond);
309 char *combined;
310
311 combined = (char *) xmalloc (insn_cond_len + split_cond_len + 1);
312 memcpy (combined, insn_cond, insn_cond_len);
313 memcpy (combined + insn_cond_len, split_cond, split_cond_len + 1);
314
315 split_cond = combined;
316 }
317 XSTR (split, 1) = split_cond;
318 XVEC (split, 2) = XVEC (desc, 5);
319 XSTR (split, 3) = XSTR (desc, 6);
320
321 /* Fix up the DEFINE_INSN. */
322 attr = XVEC (desc, 7);
323 PUT_CODE (desc, DEFINE_INSN);
324 XVEC (desc, 4) = attr;
325
326 /* Queue them. */
327 queue_pattern (desc, &define_insn_tail, lineno);
328 queue_pattern (split, &other_tail, lineno);
329 break;
330 }
331
332 default:
333 queue_pattern (desc, &other_tail, lineno);
334 break;
335 }
336 }
337 \f
338 /* Return true if attribute PREDICABLE is true for ELEM, which holds
339 a DEFINE_INSN. */
340
341 static int
342 is_predicable (elem)
343 struct queue_elem *elem;
344 {
345 rtvec vec = XVEC (elem->data, 4);
346 const char *value;
347 int i;
348
349 if (! vec)
350 return predicable_default;
351
352 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
353 {
354 rtx sub = RTVEC_ELT (vec, i);
355 switch (GET_CODE (sub))
356 {
357 case SET_ATTR:
358 if (strcmp (XSTR (sub, 0), "predicable") == 0)
359 {
360 value = XSTR (sub, 1);
361 goto found;
362 }
363 break;
364
365 case SET_ATTR_ALTERNATIVE:
366 if (strcmp (XSTR (sub, 0), "predicable") == 0)
367 {
368 message_with_line (elem->lineno,
369 "multiple alternatives for `predicable'");
370 errors = 1;
371 return 0;
372 }
373 break;
374
375 case SET:
376 if (GET_CODE (SET_DEST (sub)) != ATTR
377 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
378 break;
379 sub = SET_SRC (sub);
380 if (GET_CODE (sub) == CONST_STRING)
381 {
382 value = XSTR (sub, 0);
383 goto found;
384 }
385
386 /* ??? It would be possible to handle this if we really tried.
387 It's not easy though, and I'm not going to bother until it
388 really proves necessary. */
389 message_with_line (elem->lineno,
390 "non-constant value for `predicable'");
391 errors = 1;
392 return 0;
393
394 default:
395 abort ();
396 }
397 }
398
399 return predicable_default;
400
401 found:
402 /* Verify that predicability does not vary on the alternative. */
403 /* ??? It should be possible to handle this by simply eliminating
404 the non-predicable alternatives from the insn. FRV would like
405 to do this. Delay this until we've got the basics solid. */
406 if (strchr (value, ',') != NULL)
407 {
408 message_with_line (elem->lineno,
409 "multiple alternatives for `predicable'");
410 errors = 1;
411 return 0;
412 }
413
414 /* Find out which value we're looking at. */
415 if (strcmp (value, predicable_true) == 0)
416 return 1;
417 if (strcmp (value, predicable_false) == 0)
418 return 0;
419
420 message_with_line (elem->lineno,
421 "unknown value `%s' for `predicable' attribute",
422 value);
423 errors = 1;
424 return 0;
425 }
426
427 /* Examine the attribute "predicable"; discover its boolean values
428 and its default. */
429
430 static void
431 identify_predicable_attribute ()
432 {
433 struct queue_elem *elem;
434 char *p_true, *p_false;
435 const char *value;
436 size_t len;
437
438 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
439 for (elem = define_attr_queue; elem ; elem = elem->next)
440 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
441 goto found;
442
443 message_with_line (define_cond_exec_queue->lineno,
444 "attribute `predicable' not defined");
445 errors = 1;
446 return;
447
448 found:
449 value = XSTR (elem->data, 1);
450 len = strlen (value);
451 p_false = (char *) xmalloc (len + 1);
452 memcpy (p_false, value, len + 1);
453
454 p_true = strchr (p_false, ',');
455 if (p_true == NULL || strchr (++p_true, ',') != NULL)
456 {
457 message_with_line (elem->lineno,
458 "attribute `predicable' is not a boolean");
459 errors = 1;
460 return;
461 }
462 p_true[-1] = '\0';
463
464 predicable_true = p_true;
465 predicable_false = p_false;
466
467 switch (GET_CODE (XEXP (elem->data, 2)))
468 {
469 case CONST_STRING:
470 value = XSTR (XEXP (elem->data, 2), 0);
471 break;
472
473 case CONST:
474 message_with_line (elem->lineno,
475 "attribute `predicable' cannot be const");
476 errors = 1;
477 return;
478
479 default:
480 message_with_line (elem->lineno,
481 "attribute `predicable' must have a constant default");
482 errors = 1;
483 return;
484 }
485
486 if (strcmp (value, p_true) == 0)
487 predicable_default = 1;
488 else if (strcmp (value, p_false) == 0)
489 predicable_default = 0;
490 else
491 {
492 message_with_line (elem->lineno,
493 "unknown value `%s' for `predicable' attribute",
494 value);
495 errors = 1;
496 }
497 }
498
499 /* Return the number of alternatives in constraint S. */
500
501 static int
502 n_alternatives (s)
503 const char *s;
504 {
505 int n = 1;
506
507 if (s)
508 while (*s)
509 n += (*s++ == ',');
510
511 return n;
512 }
513
514 /* Determine how many alternatives there are in INSN, and how many
515 operands. */
516
517 static void
518 collect_insn_data (pattern, palt, pmax)
519 rtx pattern;
520 int *palt, *pmax;
521 {
522 const char *fmt;
523 enum rtx_code code;
524 int i, j, len;
525
526 code = GET_CODE (pattern);
527 switch (code)
528 {
529 case MATCH_OPERAND:
530 i = n_alternatives (XSTR (pattern, 2));
531 *palt = (i > *palt ? i : *palt);
532 /* FALLTHRU */
533
534 case MATCH_OPERATOR:
535 case MATCH_SCRATCH:
536 case MATCH_PARALLEL:
537 case MATCH_INSN:
538 i = XINT (pattern, 0);
539 if (i > *pmax)
540 *pmax = i;
541 break;
542
543 default:
544 break;
545 }
546
547 fmt = GET_RTX_FORMAT (code);
548 len = GET_RTX_LENGTH (code);
549 for (i = 0; i < len; i++)
550 {
551 switch (fmt[i])
552 {
553 case 'e': case 'u':
554 collect_insn_data (XEXP (pattern, i), palt, pmax);
555 break;
556
557 case 'V':
558 if (XVEC (pattern, i) == NULL)
559 break;
560 /* FALLTHRU */
561 case 'E':
562 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
563 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
564 break;
565
566 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
567 break;
568
569 default:
570 abort ();
571 }
572 }
573 }
574
575 static rtx
576 alter_predicate_for_insn (pattern, alt, max_op, lineno)
577 rtx pattern;
578 int alt, max_op, lineno;
579 {
580 const char *fmt;
581 enum rtx_code code;
582 int i, j, len;
583
584 code = GET_CODE (pattern);
585 switch (code)
586 {
587 case MATCH_OPERAND:
588 {
589 const char *c = XSTR (pattern, 2);
590
591 if (n_alternatives (c) != 1)
592 {
593 message_with_line (lineno,
594 "too many alternatives for operand %d",
595 XINT (pattern, 0));
596 errors = 1;
597 return NULL;
598 }
599
600 /* Replicate C as needed to fill out ALT alternatives. */
601 if (c && *c && alt > 1)
602 {
603 size_t c_len = strlen (c);
604 size_t len = alt * (c_len + 1);
605 char *new_c = (char *) xmalloc (len);
606
607 memcpy (new_c, c, c_len);
608 for (i = 1; i < alt; ++i)
609 {
610 new_c[i * (c_len + 1) - 1] = ',';
611 memcpy (&new_c[i * (c_len + 1)], c, c_len);
612 }
613 new_c[len - 1] = '\0';
614 XSTR (pattern, 2) = new_c;
615 }
616 }
617 /* FALLTHRU */
618
619 case MATCH_OPERATOR:
620 case MATCH_SCRATCH:
621 case MATCH_PARALLEL:
622 case MATCH_INSN:
623 XINT (pattern, 0) += max_op;
624 break;
625
626 default:
627 break;
628 }
629
630 fmt = GET_RTX_FORMAT (code);
631 len = GET_RTX_LENGTH (code);
632 for (i = 0; i < len; i++)
633 {
634 rtx r;
635
636 switch (fmt[i])
637 {
638 case 'e': case 'u':
639 r = alter_predicate_for_insn (XEXP (pattern, i), alt,
640 max_op, lineno);
641 if (r == NULL)
642 return r;
643 break;
644
645 case 'E':
646 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
647 {
648 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
649 alt, max_op, lineno);
650 if (r == NULL)
651 return r;
652 }
653 break;
654
655 case 'i': case 'w': case '0': case 's':
656 break;
657
658 default:
659 abort ();
660 }
661 }
662
663 return pattern;
664 }
665
666 static const char *
667 alter_test_for_insn (ce_elem, insn_elem)
668 struct queue_elem *ce_elem, *insn_elem;
669 {
670 const char *ce_test, *insn_test;
671 char *new_test;
672 size_t len, ce_len, insn_len;
673
674 ce_test = XSTR (ce_elem->data, 1);
675 insn_test = XSTR (insn_elem->data, 2);
676 if (!ce_test || *ce_test == '\0')
677 return insn_test;
678 if (!insn_test || *insn_test == '\0')
679 return ce_test;
680
681 ce_len = strlen (ce_test);
682 insn_len = strlen (insn_test);
683 len = 1 + ce_len + 1 + 4 + 1 + insn_len + 1 + 1;
684 new_test = (char *) xmalloc (len);
685
686 sprintf (new_test, "(%s) && (%s)", ce_test, insn_test);
687
688 return new_test;
689 }
690
691 /* Adjust all of the operand numbers in OLD to match the shift they'll
692 get from an operand displacement of DISP. Return a pointer after the
693 adjusted string. */
694
695 static char *
696 shift_output_template (new, old, disp)
697 char *new;
698 const char *old;
699 int disp;
700 {
701 while (*old)
702 {
703 char c = *old++;
704 *new++ = c;
705 if (c == '%')
706 {
707 c = *old++;
708 if (ISDIGIT ((unsigned char) c))
709 c += disp;
710 else if (ISALPHA (c))
711 {
712 *new++ = c;
713 c = *old++ + disp;
714 }
715 *new++ = c;
716 }
717 }
718
719 return new;
720 }
721
722 static const char *
723 alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
724 struct queue_elem *ce_elem, *insn_elem;
725 int alt, max_op;
726 {
727 const char *ce_out, *insn_out;
728 char *new, *p;
729 size_t len, ce_len, insn_len;
730
731 /* ??? Could coordinate with genoutput to not duplicate code here. */
732
733 ce_out = XSTR (ce_elem->data, 2);
734 insn_out = XTMPL (insn_elem->data, 3);
735 if (!ce_out || *ce_out == '\0')
736 return insn_out;
737
738 ce_len = strlen (ce_out);
739 insn_len = strlen (insn_out);
740
741 if (*insn_out == '*')
742 /* You must take care of the predicate yourself. */
743 return insn_out;
744
745 if (*insn_out == '@')
746 {
747 len = (ce_len + 1) * alt + insn_len + 1;
748 p = new = xmalloc (len);
749
750 do
751 {
752 do
753 *p++ = *insn_out++;
754 while (ISSPACE ((unsigned char) *insn_out));
755
756 if (*insn_out != '#')
757 {
758 p = shift_output_template (p, ce_out, max_op);
759 *p++ = ' ';
760 }
761
762 do
763 *p++ = *insn_out++;
764 while (*insn_out && *insn_out != '\n');
765 }
766 while (*insn_out);
767 *p = '\0';
768 }
769 else
770 {
771 len = ce_len + 1 + insn_len + 1;
772 new = xmalloc (len);
773
774 p = shift_output_template (new, ce_out, max_op);
775 *p++ = ' ';
776 memcpy (p, insn_out, insn_len + 1);
777 }
778
779 return new;
780 }
781
782 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
783
784 static void
785 process_one_cond_exec (ce_elem)
786 struct queue_elem *ce_elem;
787 {
788 struct queue_elem *insn_elem;
789 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
790 {
791 int alternatives, max_operand;
792 rtx pred, insn, pattern;
793
794 if (! is_predicable (insn_elem))
795 continue;
796
797 alternatives = 1;
798 max_operand = -1;
799 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
800 max_operand += 1;
801
802 if (XVECLEN (ce_elem->data, 0) != 1)
803 {
804 message_with_line (ce_elem->lineno,
805 "too many patterns in predicate");
806 errors = 1;
807 return;
808 }
809
810 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
811 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
812 ce_elem->lineno);
813 if (pred == NULL)
814 return;
815
816 /* Construct a new pattern for the new insn. */
817 insn = copy_rtx (insn_elem->data);
818 XSTR (insn, 0) = "";
819 pattern = rtx_alloc (COND_EXEC);
820 XEXP (pattern, 0) = pred;
821 if (XVECLEN (insn, 1) == 1)
822 {
823 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
824 XVECEXP (insn, 1, 0) = pattern;
825 PUT_NUM_ELEM (XVEC (insn, 1), 1);
826 }
827 else
828 {
829 XEXP (pattern, 1) = rtx_alloc (PARALLEL);
830 XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
831 XVEC (insn, 1) = rtvec_alloc (1);
832 XVECEXP (insn, 1, 0) = pattern;
833 }
834
835 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
836 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
837 alternatives, max_operand);
838
839 /* ??? Set `predicable' to false. Not crucial since it's really
840 only used here, and we won't reprocess this new pattern. */
841
842 /* Put the new pattern on the `other' list so that it
843 (a) is not reprocessed by other define_cond_exec patterns
844 (b) appears after all normal define_insn patterns.
845
846 ??? B is debatable. If one has normal insns that match
847 cond_exec patterns, they will be preferred over these
848 generated patterns. Whether this matters in practice, or if
849 it's a good thing, or whether we should thread these new
850 patterns into the define_insn chain just after their generator
851 is something we'll have to experiment with. */
852
853 queue_pattern (insn, &other_tail, insn_elem->lineno);
854 }
855 }
856
857 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
858 patterns appropriately. */
859
860 static void
861 process_define_cond_exec ()
862 {
863 struct queue_elem *elem;
864
865 identify_predicable_attribute ();
866 if (errors)
867 return;
868
869 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
870 process_one_cond_exec (elem);
871 }
872
873 static char *
874 save_string (s, len)
875 const char *s;
876 int len;
877 {
878 register char *result = xmalloc (len + 1);
879
880 memcpy (result, s, len);
881 result[len] = 0;
882 return result;
883 }
884
885 \f
886 /* The entry point for initializing the reader. */
887
888 int
889 init_md_reader_args (argc, argv)
890 int argc;
891 char **argv;
892 {
893 int i;
894 const char *in_fname;
895
896 max_include_len = 0;
897 in_fname = NULL;
898 for (i = 1; i < argc; i++)
899 {
900 if (argv[i][0] != '-')
901 {
902 if (in_fname == NULL)
903 in_fname = argv[i];
904 }
905 else
906 {
907 int c = argv[i][1];
908 switch (c)
909 {
910 case 'I': /* Add directory to path for includes. */
911 {
912 struct file_name_list *dirtmp;
913
914 dirtmp = (struct file_name_list *)
915 xmalloc (sizeof (struct file_name_list));
916 dirtmp->next = 0; /* New one goes on the end */
917 if (first_dir_md_include == 0)
918 first_dir_md_include = dirtmp;
919 else
920 last_dir_md_include->next = dirtmp;
921 last_dir_md_include = dirtmp; /* Tail follows the last one */
922 if (argv[i][1] == 'I' && argv[i][2] != 0)
923 dirtmp->fname = argv[i] + 2;
924 else if (i + 1 == argc)
925 fatal ("directory name missing after -I option");
926 else
927 dirtmp->fname = argv[++i];
928 if (strlen (dirtmp->fname) > max_include_len)
929 max_include_len = strlen (dirtmp->fname);
930 }
931 break;
932 default:
933 fatal ("invalid option `%s'", argv[i]);
934
935 }
936 }
937 }
938 return init_md_reader (in_fname);
939 }
940 \f
941 /* The entry point for initializing the reader. */
942
943 int
944 init_md_reader (filename)
945 const char *filename;
946 {
947 FILE *input_file;
948 int c;
949 char *lastsl;
950
951 lastsl = strrchr (filename, '/');
952 if (lastsl != NULL)
953 base_dir = save_string (filename, lastsl - filename + 1 );
954
955 read_rtx_filename = filename;
956 input_file = fopen (filename, "r");
957 if (input_file == 0)
958 {
959 perror (filename);
960 return FATAL_EXIT_CODE;
961 }
962
963 obstack_init (rtl_obstack);
964 errors = 0;
965 sequence_num = 0;
966
967 /* Read the entire file. */
968 while (1)
969 {
970 rtx desc;
971 int lineno;
972
973 c = read_skip_spaces (input_file);
974 if (c == EOF)
975 break;
976
977 ungetc (c, input_file);
978 lineno = read_rtx_lineno;
979 desc = read_rtx (input_file);
980 process_rtx (desc, lineno);
981 }
982 fclose (input_file);
983
984 /* Process define_cond_exec patterns. */
985 if (define_cond_exec_queue != NULL)
986 process_define_cond_exec ();
987
988 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
989 }
990
991 /* The entry point for reading a single rtx from an md file. */
992
993 rtx
994 read_md_rtx (lineno, seqnr)
995 int *lineno;
996 int *seqnr;
997 {
998 struct queue_elem **queue, *elem;
999 rtx desc;
1000
1001 /* Read all patterns from a given queue before moving on to the next. */
1002 if (define_attr_queue != NULL)
1003 queue = &define_attr_queue;
1004 else if (define_insn_queue != NULL)
1005 queue = &define_insn_queue;
1006 else if (other_queue != NULL)
1007 queue = &other_queue;
1008 else
1009 return NULL_RTX;
1010
1011 elem = *queue;
1012 *queue = elem->next;
1013 desc = elem->data;
1014 *lineno = elem->lineno;
1015 *seqnr = sequence_num;
1016
1017 free (elem);
1018
1019 switch (GET_CODE (desc))
1020 {
1021 case DEFINE_INSN:
1022 case DEFINE_EXPAND:
1023 case DEFINE_SPLIT:
1024 case DEFINE_PEEPHOLE:
1025 case DEFINE_PEEPHOLE2:
1026 sequence_num++;
1027 break;
1028
1029 default:
1030 break;
1031 }
1032
1033 return desc;
1034 }
1035
1036 /* Given a string, return the number of comma-separated elements in it.
1037 Return 0 for the null string. */
1038 int
1039 n_comma_elts (s)
1040 const char *s;
1041 {
1042 int n;
1043
1044 if (*s == '\0')
1045 return 0;
1046
1047 for (n = 1; *s; s++)
1048 if (*s == ',')
1049 n++;
1050
1051 return n;
1052 }
1053
1054 /* Given a pointer to a (char *), return a pointer to the beginning of the
1055 next comma-separated element in the string. Advance the pointer given
1056 to the end of that element. Return NULL if at end of string. Caller
1057 is responsible for copying the string if necessary. White space between
1058 a comma and an element is ignored. */
1059
1060 const char *
1061 scan_comma_elt (pstr)
1062 const char **pstr;
1063 {
1064 const char *start;
1065 const char *p = *pstr;
1066
1067 if (*p == ',')
1068 p++;
1069 while (ISSPACE(*p))
1070 p++;
1071
1072 if (*p == '\0')
1073 return NULL;
1074
1075 start = p;
1076
1077 while (*p != ',' && *p != '\0')
1078 p++;
1079
1080 *pstr = p;
1081 return start;
1082 }