OSDN Git Service

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