OSDN Git Service

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