OSDN Git Service

3660378d7cf4ba3e5e87e79a2df96deddc1f4480
[pf3gnuchains/gcc-fork.git] / gcc / gensupport.c
1 /* Support routines for the various generation passes.
2    Copyright (C) 2000, 2001 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 *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_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;
227   struct file_name_list *stackp;
228   int flen;
229
230   stackp = 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 *) alloca (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   return SUCCESS_EXIT_CODE;
316 }
317
318 /* Process a top level rtx in some way, queueing as appropriate.  */
319
320 static void
321 process_rtx (desc, lineno)
322      rtx desc;
323      int lineno;
324 {
325   const char *filename = XSTR (desc, 0);
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         message_with_line (lineno, "include file at  %s not found\n", filename);
344       break;
345
346     case DEFINE_INSN_AND_SPLIT:
347       {
348         const char *split_cond;
349         rtx split;
350         rtvec attr;
351         int i;
352
353         /* Create a split with values from the insn_and_split.  */
354         split = rtx_alloc (DEFINE_SPLIT);
355
356         i = XVECLEN (desc, 1);
357         XVEC (split, 0) = rtvec_alloc (i);
358         while (--i >= 0)
359           {
360             XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
361             remove_constraints (XVECEXP (split, 0, i));
362           }
363
364         /* If the split condition starts with "&&", append it to the
365            insn condition to create the new split condition.  */
366         split_cond = XSTR (desc, 4);
367         if (split_cond[0] == '&' && split_cond[1] == '&')
368           {
369             const char *insn_cond = XSTR (desc, 2);
370             size_t insn_cond_len = strlen (insn_cond);
371             size_t split_cond_len = strlen (split_cond);
372             char *combined;
373
374             combined = (char *) xmalloc (insn_cond_len + split_cond_len + 1);
375             memcpy (combined, insn_cond, insn_cond_len);
376             memcpy (combined + insn_cond_len, split_cond, split_cond_len + 1);
377
378             split_cond = combined;
379           }
380         XSTR (split, 1) = split_cond;
381         XVEC (split, 2) = XVEC (desc, 5);
382         XSTR (split, 3) = XSTR (desc, 6);
383
384         /* Fix up the DEFINE_INSN.  */
385         attr = XVEC (desc, 7);
386         PUT_CODE (desc, DEFINE_INSN);
387         XVEC (desc, 4) = attr;
388
389         /* Queue them.  */
390         queue_pattern (desc, &define_insn_tail, lineno);
391         queue_pattern (split, &other_tail, lineno);
392         break;
393       }
394
395     default:
396       queue_pattern (desc, &other_tail, lineno);
397       break;
398     }
399 }
400 \f
401 /* Return true if attribute PREDICABLE is true for ELEM, which holds
402    a DEFINE_INSN.  */
403
404 static int
405 is_predicable (elem)
406      struct queue_elem *elem;
407 {
408   rtvec vec = XVEC (elem->data, 4);
409   const char *value;
410   int i;
411
412   if (! vec)
413     return predicable_default;
414
415   for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
416     {
417       rtx sub = RTVEC_ELT (vec, i);
418       switch (GET_CODE (sub))
419         {
420         case SET_ATTR:
421           if (strcmp (XSTR (sub, 0), "predicable") == 0)
422             {
423               value = XSTR (sub, 1);
424               goto found;
425             }
426           break;
427
428         case SET_ATTR_ALTERNATIVE:
429           if (strcmp (XSTR (sub, 0), "predicable") == 0)
430             {
431               message_with_line (elem->lineno,
432                                  "multiple alternatives for `predicable'");
433               errors = 1;
434               return 0;
435             }
436           break;
437
438         case SET:
439           if (GET_CODE (SET_DEST (sub)) != ATTR
440               || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
441             break;
442           sub = SET_SRC (sub);
443           if (GET_CODE (sub) == CONST_STRING)
444             {
445               value = XSTR (sub, 0);
446               goto found;
447             }
448
449           /* ??? It would be possible to handle this if we really tried.
450              It's not easy though, and I'm not going to bother until it
451              really proves necessary.  */
452           message_with_line (elem->lineno,
453                              "non-constant value for `predicable'");
454           errors = 1;
455           return 0;
456
457         default:
458           abort ();
459         }
460     }
461
462   return predicable_default;
463
464  found:
465   /* Verify that predicability does not vary on the alternative.  */
466   /* ??? It should be possible to handle this by simply eliminating
467      the non-predicable alternatives from the insn.  FRV would like
468      to do this.  Delay this until we've got the basics solid.  */
469   if (strchr (value, ',') != NULL)
470     {
471       message_with_line (elem->lineno,
472                          "multiple alternatives for `predicable'");
473       errors = 1;
474       return 0;
475     }
476
477   /* Find out which value we're looking at.  */
478   if (strcmp (value, predicable_true) == 0)
479     return 1;
480   if (strcmp (value, predicable_false) == 0)
481     return 0;
482
483   message_with_line (elem->lineno,
484                      "Unknown value `%s' for `predicable' attribute",
485                      value);
486   errors = 1;
487   return 0;
488 }
489
490 /* Examine the attribute "predicable"; discover its boolean values
491    and its default.  */
492
493 static void
494 identify_predicable_attribute ()
495 {
496   struct queue_elem *elem;
497   char *p_true, *p_false;
498   const char *value;
499   size_t len;
500
501   /* Look for the DEFINE_ATTR for `predicable', which must exist.  */
502   for (elem = define_attr_queue; elem ; elem = elem->next)
503     if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
504       goto found;
505
506   message_with_line (define_cond_exec_queue->lineno,
507                      "Attribute `predicable' not defined");
508   errors = 1;
509   return;
510
511  found:
512   value = XSTR (elem->data, 1);
513   len = strlen (value);
514   p_false = (char *) xmalloc (len + 1);
515   memcpy (p_false, value, len + 1);
516
517   p_true = strchr (p_false, ',');
518   if (p_true == NULL || strchr (++p_true, ',') != NULL)
519     {
520       message_with_line (elem->lineno,
521                          "Attribute `predicable' is not a boolean");
522       errors = 1;
523       return;
524     }
525   p_true[-1] = '\0';
526
527   predicable_true = p_true;
528   predicable_false = p_false;
529
530   switch (GET_CODE (XEXP (elem->data, 2)))
531     {
532     case CONST_STRING:
533       value = XSTR (XEXP (elem->data, 2), 0);
534       break;
535
536     case CONST:
537       message_with_line (elem->lineno,
538                          "Attribute `predicable' cannot be const");
539       errors = 1;
540       return;
541
542     default:
543       message_with_line (elem->lineno,
544                          "Attribute `predicable' must have a constant default");
545       errors = 1;
546       return;
547     }
548
549   if (strcmp (value, p_true) == 0)
550     predicable_default = 1;
551   else if (strcmp (value, p_false) == 0)
552     predicable_default = 0;
553   else
554     {
555       message_with_line (elem->lineno,
556                          "Unknown value `%s' for `predicable' attribute",
557                          value);
558       errors = 1;
559     }
560 }
561
562 /* Return the number of alternatives in constraint S.  */
563
564 static int
565 n_alternatives (s)
566      const char *s;
567 {
568   int n = 1;
569
570   if (s)
571     while (*s)
572       n += (*s++ == ',');
573
574   return n;
575 }
576
577 /* Determine how many alternatives there are in INSN, and how many
578    operands.  */
579
580 static void
581 collect_insn_data (pattern, palt, pmax)
582      rtx pattern;
583      int *palt, *pmax;
584 {
585   const char *fmt;
586   enum rtx_code code;
587   int i, j, len;
588
589   code = GET_CODE (pattern);
590   switch (code)
591     {
592     case MATCH_OPERAND:
593       i = n_alternatives (XSTR (pattern, 2));
594       *palt = (i > *palt ? i : *palt);
595       /* FALLTHRU */
596
597     case MATCH_OPERATOR:
598     case MATCH_SCRATCH:
599     case MATCH_PARALLEL:
600     case MATCH_INSN:
601       i = XINT (pattern, 0);
602       if (i > *pmax)
603         *pmax = i;
604       break;
605
606     default:
607       break;
608     }
609
610   fmt = GET_RTX_FORMAT (code);
611   len = GET_RTX_LENGTH (code);
612   for (i = 0; i < len; i++)
613     {
614       switch (fmt[i])
615         {
616         case 'e': case 'u':
617           collect_insn_data (XEXP (pattern, i), palt, pmax);
618           break;
619
620         case 'V':
621           if (XVEC (pattern, i) == NULL)
622             break;
623           /* FALLTHRU */
624         case 'E':
625           for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
626             collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
627           break;
628
629         case 'i': case 'w': case '0': case 's': case 'S': case 'T':
630           break;
631
632         default:
633           abort ();
634         }
635     }
636 }
637
638 static rtx
639 alter_predicate_for_insn (pattern, alt, max_op, lineno)
640      rtx pattern;
641      int alt, max_op, lineno;
642 {
643   const char *fmt;
644   enum rtx_code code;
645   int i, j, len;
646
647   code = GET_CODE (pattern);
648   switch (code)
649     {
650     case MATCH_OPERAND:
651       {
652         const char *c = XSTR (pattern, 2);
653
654         if (n_alternatives (c) != 1)
655           {
656             message_with_line (lineno,
657                                "Too many alternatives for operand %d",
658                                XINT (pattern, 0));
659             errors = 1;
660             return NULL;
661           }
662
663         /* Replicate C as needed to fill out ALT alternatives.  */
664         if (c && *c && alt > 1)
665           {
666             size_t c_len = strlen (c);
667             size_t len = alt * (c_len + 1);
668             char *new_c = (char *) xmalloc (len);
669
670             memcpy (new_c, c, c_len);
671             for (i = 1; i < alt; ++i)
672               {
673                 new_c[i * (c_len + 1) - 1] = ',';
674                 memcpy (&new_c[i * (c_len + 1)], c, c_len);
675               }
676             new_c[len - 1] = '\0';
677             XSTR (pattern, 2) = new_c;
678           }
679       }
680       /* FALLTHRU */
681
682     case MATCH_OPERATOR:
683     case MATCH_SCRATCH:
684     case MATCH_PARALLEL:
685     case MATCH_INSN:
686       XINT (pattern, 0) += max_op;
687       break;
688
689     default:
690       break;
691     }
692
693   fmt = GET_RTX_FORMAT (code);
694   len = GET_RTX_LENGTH (code);
695   for (i = 0; i < len; i++)
696     {
697       rtx r;
698
699       switch (fmt[i])
700         {
701         case 'e': case 'u':
702           r = alter_predicate_for_insn (XEXP (pattern, i), alt,
703                                         max_op, lineno);
704           if (r == NULL)
705             return r;
706           break;
707
708         case 'E':
709           for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
710             {
711               r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
712                                             alt, max_op, lineno);
713               if (r == NULL)
714                 return r;
715             }
716           break;
717
718         case 'i': case 'w': case '0': case 's':
719           break;
720
721         default:
722           abort ();
723         }
724     }
725
726   return pattern;
727 }
728
729 static const char *
730 alter_test_for_insn (ce_elem, insn_elem)
731      struct queue_elem *ce_elem, *insn_elem;
732 {
733   const char *ce_test, *insn_test;
734   char *new_test;
735   size_t len, ce_len, insn_len;
736
737   ce_test = XSTR (ce_elem->data, 1);
738   insn_test = XSTR (insn_elem->data, 2);
739   if (!ce_test || *ce_test == '\0')
740     return insn_test;
741   if (!insn_test || *insn_test == '\0')
742     return ce_test;
743
744   ce_len = strlen (ce_test);
745   insn_len = strlen (insn_test);
746   len = 1 + ce_len + 1 + 4 + 1 + insn_len + 1 + 1;
747   new_test = (char *) xmalloc (len);
748
749   sprintf (new_test, "(%s) && (%s)", ce_test, insn_test);
750
751   return new_test;
752 }
753
754 /* Adjust all of the operand numbers in OLD to match the shift they'll
755    get from an operand displacement of DISP.  Return a pointer after the
756    adjusted string.  */
757
758 static char *
759 shift_output_template (new, old, disp)
760      char *new;
761      const char *old;
762      int disp;
763 {
764   while (*old)
765     {
766       char c = *old++;
767       *new++ = c;
768       if (c == '%')
769         {
770           c = *old++;
771           if (ISDIGIT ((unsigned char) c))
772             c += disp;
773           else if (ISALPHA (c))
774             {
775               *new++ = c;
776               c = *old++ + disp;
777             }
778           *new++ = c;
779         }
780     }
781
782   return new;
783 }
784
785 static const char *
786 alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
787      struct queue_elem *ce_elem, *insn_elem;
788      int alt, max_op;
789 {
790   const char *ce_out, *insn_out;
791   char *new, *p;
792   size_t len, ce_len, insn_len;
793
794   /* ??? Could coordinate with genoutput to not duplicate code here.  */
795
796   ce_out = XSTR (ce_elem->data, 2);
797   insn_out = XTMPL (insn_elem->data, 3);
798   if (!ce_out || *ce_out == '\0')
799     return insn_out;
800
801   ce_len = strlen (ce_out);
802   insn_len = strlen (insn_out);
803
804   if (*insn_out == '*')
805     /* You must take care of the predicate yourself.  */
806     return insn_out;
807
808   if (*insn_out == '@')
809     {
810       len = (ce_len + 1) * alt + insn_len + 1;
811       p = new = xmalloc (len);
812
813       do
814         {
815           do
816             *p++ = *insn_out++;
817           while (ISSPACE ((unsigned char) *insn_out));
818
819           if (*insn_out != '#')
820             {
821               p = shift_output_template (p, ce_out, max_op);
822               *p++ = ' ';
823             }
824
825           do
826             *p++ = *insn_out++;
827           while (*insn_out && *insn_out != '\n');
828         }
829       while (*insn_out);
830       *p = '\0';
831     }
832   else
833     {
834       len = ce_len + 1 + insn_len + 1;
835       new = xmalloc (len);
836
837       p = shift_output_template (new, ce_out, max_op);
838       *p++ = ' ';
839       memcpy (p, insn_out, insn_len + 1);
840     }
841
842   return new;
843 }
844
845 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC.  */
846
847 static void
848 process_one_cond_exec (ce_elem)
849      struct queue_elem *ce_elem;
850 {
851   struct queue_elem *insn_elem;
852   for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
853     {
854       int alternatives, max_operand;
855       rtx pred, insn, pattern;
856
857       if (! is_predicable (insn_elem))
858         continue;
859
860       alternatives = 1;
861       max_operand = -1;
862       collect_insn_data (insn_elem->data, &alternatives, &max_operand);
863       max_operand += 1;
864
865       if (XVECLEN (ce_elem->data, 0) != 1)
866         {
867           message_with_line (ce_elem->lineno,
868                              "too many patterns in predicate");
869           errors = 1;
870           return;
871         }
872
873       pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
874       pred = alter_predicate_for_insn (pred, alternatives, max_operand,
875                                        ce_elem->lineno);
876       if (pred == NULL)
877         return;
878
879       /* Construct a new pattern for the new insn.  */
880       insn = copy_rtx (insn_elem->data);
881       XSTR (insn, 0) = "";
882       pattern = rtx_alloc (COND_EXEC);
883       XEXP (pattern, 0) = pred;
884       if (XVECLEN (insn, 1) == 1)
885         {
886           XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
887           XVECEXP (insn, 1, 0) = pattern;
888           PUT_NUM_ELEM (XVEC (insn, 1), 1);
889         }
890       else
891         {
892           XEXP (pattern, 1) = rtx_alloc (PARALLEL);
893           XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
894           XVEC (insn, 1) = rtvec_alloc (1);
895           XVECEXP (insn, 1, 0) = pattern;
896         }
897
898       XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
899       XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
900                                               alternatives, max_operand);
901
902       /* ??? Set `predicable' to false.  Not crucial since it's really
903          only used here, and we won't reprocess this new pattern.  */
904
905       /* Put the new pattern on the `other' list so that it
906          (a) is not reprocessed by other define_cond_exec patterns
907          (b) appears after all normal define_insn patterns.
908
909          ??? B is debatable.  If one has normal insns that match
910          cond_exec patterns, they will be preferred over these
911          generated patterns.  Whether this matters in practice, or if
912          it's a good thing, or whether we should thread these new
913          patterns into the define_insn chain just after their generator
914          is something we'll have to experiment with.  */
915
916       queue_pattern (insn, &other_tail, insn_elem->lineno);
917     }
918 }
919
920 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
921    patterns appropriately.  */
922
923 static void
924 process_define_cond_exec ()
925 {
926   struct queue_elem *elem;
927
928   identify_predicable_attribute ();
929   if (errors)
930     return;
931
932   for (elem = define_cond_exec_queue; elem ; elem = elem->next)
933     process_one_cond_exec (elem);
934 }
935
936 static char *
937 save_string (s, len)
938      const char *s;
939      int len;
940 {
941   register char *result = xmalloc (len + 1);
942
943   memcpy (result, s, len);
944   result[len] = 0;
945   return result;
946 }
947
948 \f
949 /* The entry point for initializing the reader.  */
950
951 int
952 init_md_reader_args (argc, argv)
953      int argc;
954      char **argv;
955 {
956   int i;
957   const char *in_fname;
958
959   max_include_len = 0;
960   in_fname = NULL;
961   for (i = 1; i < argc; i++)
962     {
963       if (argv[i][0] != '-')
964         {
965           if (in_fname == NULL)
966             in_fname = argv[i];
967         }
968       else
969         {
970           int c = argv[i][1];
971           switch (c)
972             {
973             case 'I':           /* Add directory to path for includes.  */
974               {
975                 struct file_name_list *dirtmp;
976
977                 dirtmp = (struct file_name_list *)
978                   xmalloc (sizeof (struct file_name_list));
979                 dirtmp->next = 0;       /* New one goes on the end */
980                 if (include == 0)
981                   include = dirtmp;
982                 else
983                   last_include->next = dirtmp;
984                 last_include = dirtmp;  /* Tail follows the last one */
985                 if (argv[i][1] == 'I' && argv[i][2] != 0)
986                   dirtmp->fname = argv[i] + 2;
987                 else if (i + 1 == argc)
988                   fatal ("Directory name missing after -I option");
989                 else
990                   dirtmp->fname = argv[++i];
991                 if (strlen (dirtmp->fname) > max_include_len)
992                   max_include_len = strlen (dirtmp->fname);
993               }
994               break;
995             default:
996               fatal ("Invalid option `%s'", argv[i]);
997
998             }
999         }
1000     }
1001     return init_md_reader (in_fname);
1002 }
1003 \f
1004 /* The entry point for initializing the reader.  */
1005
1006 int
1007 init_md_reader (filename)
1008      const char *filename;
1009 {
1010   FILE *input_file;
1011   int c;
1012   char *lastsl;
1013
1014   if (!IS_ABSOLUTE_PATHNAME (filename))
1015     {
1016       lastsl = strrchr (filename, '/');
1017       if (lastsl != NULL) 
1018         base_dir = save_string (filename, lastsl - filename + 1 );
1019     }
1020
1021   read_rtx_filename = filename;
1022   input_file = fopen (filename, "r");
1023   if (input_file == 0)
1024     {
1025       perror (filename);
1026       return FATAL_EXIT_CODE;
1027     }
1028
1029   obstack_init (rtl_obstack);
1030   errors = 0;
1031   sequence_num = 0;
1032
1033   /* Read the entire file.  */
1034   while (1)
1035     {
1036       rtx desc;
1037       int lineno;
1038
1039       c = read_skip_spaces (input_file);
1040       if (c == EOF)
1041         break;
1042
1043       ungetc (c, input_file);
1044       lineno = read_rtx_lineno;
1045       desc = read_rtx (input_file);
1046       process_rtx (desc, lineno);
1047     }
1048   fclose (input_file);
1049
1050   /* Process define_cond_exec patterns.  */
1051   if (define_cond_exec_queue != NULL)
1052     process_define_cond_exec ();
1053
1054   return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
1055 }
1056
1057 /* The entry point for reading a single rtx from an md file.  */
1058
1059 rtx
1060 read_md_rtx (lineno, seqnr)
1061      int *lineno;
1062      int *seqnr;
1063 {
1064   struct queue_elem **queue, *elem;
1065   rtx desc;
1066
1067   /* Read all patterns from a given queue before moving on to the next.  */
1068   if (define_attr_queue != NULL)
1069     queue = &define_attr_queue;
1070   else if (define_insn_queue != NULL)
1071     queue = &define_insn_queue;
1072   else if (other_queue != NULL)
1073     queue = &other_queue;
1074   else
1075     return NULL_RTX;
1076
1077   elem = *queue;
1078   *queue = elem->next;
1079   desc = elem->data;
1080   *lineno = elem->lineno;
1081   *seqnr = sequence_num;
1082
1083   free (elem);
1084
1085   switch (GET_CODE (desc))
1086     {
1087     case DEFINE_INSN:
1088     case DEFINE_EXPAND:
1089     case DEFINE_SPLIT:
1090     case DEFINE_PEEPHOLE:
1091     case DEFINE_PEEPHOLE2:
1092       sequence_num++;
1093       break;
1094
1095     default:
1096       break;
1097     }
1098
1099   return desc;
1100 }
1101
1102 /* Until we can use the versions in libiberty.  */
1103 char *
1104 xstrdup (input)
1105   const char *input;
1106 {
1107   size_t len = strlen (input) + 1;
1108   char *output = xmalloc (len);
1109   memcpy (output, input, len);
1110   return output;
1111 }
1112
1113 PTR
1114 xcalloc (nelem, elsize)
1115   size_t nelem, elsize;
1116 {
1117   PTR newmem;
1118
1119   if (nelem == 0 || elsize == 0)
1120     nelem = elsize = 1;
1121
1122   newmem = really_call_calloc (nelem, elsize);
1123   if (!newmem)
1124     fatal ("virtual memory exhausted");
1125   return (newmem);
1126 }
1127
1128 PTR
1129 xrealloc (old, size)
1130   PTR old;
1131   size_t size;
1132 {
1133   PTR ptr;
1134   if (old)
1135     ptr = (PTR) really_call_realloc (old, size);
1136   else
1137     ptr = (PTR) really_call_malloc (size);
1138   if (!ptr)
1139     fatal ("virtual memory exhausted");
1140   return ptr;
1141 }
1142
1143 PTR
1144 xmalloc (size)
1145   size_t size;
1146 {
1147   PTR val = (PTR) really_call_malloc (size);
1148
1149   if (val == 0)
1150     fatal ("virtual memory exhausted");
1151   return val;
1152 }