OSDN Git Service

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