OSDN Git Service

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