OSDN Git Service

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