* arm.md (stack_tie): New insn. Use an idiom that the alias code
[official-gcc.git] / gcc / gensupport.c
blob7cfa31ba127b7b345d65d6703b67e861eb3b6405
1 /* Support routines for the various generation passes.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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. */
21 #include "hconfig.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "obstack.h"
25 #include "errors.h"
26 #include "gensupport.h"
29 /* In case some macros used by files we include need it, define this here. */
30 int target_flags;
32 static struct obstack obstack;
33 struct obstack *rtl_obstack = &obstack;
35 #define obstack_chunk_alloc xmalloc
36 #define obstack_chunk_free free
38 static int sequence_num;
39 static int errors;
41 static int predicable_default;
42 static const char *predicable_true;
43 static const char *predicable_false;
45 static char *base_dir = NULL;
47 /* We initially queue all patterns, process the define_insn and
48 define_cond_exec patterns, then return them one at a time. */
50 struct queue_elem
52 rtx data;
53 const char *filename;
54 int lineno;
55 struct queue_elem *next;
58 static struct queue_elem *define_attr_queue;
59 static struct queue_elem **define_attr_tail = &define_attr_queue;
60 static struct queue_elem *define_insn_queue;
61 static struct queue_elem **define_insn_tail = &define_insn_queue;
62 static struct queue_elem *define_cond_exec_queue;
63 static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
64 static struct queue_elem *other_queue;
65 static struct queue_elem **other_tail = &other_queue;
67 static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
68 const char *, int));
70 /* Current maximum length of directory names in the search path
71 for include files. (Altered as we get more of them.) */
73 size_t max_include_len;
75 struct file_name_list
77 struct file_name_list *next;
78 const char *fname;
81 struct file_name_list *first_dir_md_include = 0; /* First dir to search */
82 /* First dir to search for <file> */
83 struct file_name_list *first_bracket_include = 0;
84 struct file_name_list *last_dir_md_include = 0; /* Last in chain */
86 static void remove_constraints PARAMS ((rtx));
87 static void process_rtx PARAMS ((rtx, int));
89 static int is_predicable PARAMS ((struct queue_elem *));
90 static void identify_predicable_attribute PARAMS ((void));
91 static int n_alternatives PARAMS ((const char *));
92 static void collect_insn_data PARAMS ((rtx, int *, int *));
93 static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
94 static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
95 struct queue_elem *));
96 static char *shift_output_template PARAMS ((char *, const char *, int));
97 static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
98 struct queue_elem *,
99 int, int));
100 static void process_one_cond_exec PARAMS ((struct queue_elem *));
101 static void process_define_cond_exec PARAMS ((void));
102 static void process_include PARAMS ((rtx, int));
103 static char *save_string PARAMS ((const char *, int));
105 void
106 message_with_line VPARAMS ((int lineno, const char *msg, ...))
108 VA_OPEN (ap, msg);
109 VA_FIXEDARG (ap, int, lineno);
110 VA_FIXEDARG (ap, const char *, msg);
112 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
113 vfprintf (stderr, msg, ap);
114 fputc ('\n', stderr);
116 VA_CLOSE (ap);
119 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
120 the gensupport programs. */
123 gen_rtx_CONST_INT (mode, arg)
124 enum machine_mode mode ATTRIBUTE_UNUSED;
125 HOST_WIDE_INT arg;
127 rtx rt = rtx_alloc (CONST_INT);
129 XWINT (rt, 0) = arg;
130 return rt;
133 /* Queue PATTERN on LIST_TAIL. */
135 static void
136 queue_pattern (pattern, list_tail, filename, lineno)
137 rtx pattern;
138 struct queue_elem ***list_tail;
139 const char *filename;
140 int lineno;
142 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
143 e->data = pattern;
144 e->filename = filename;
145 e->lineno = lineno;
146 e->next = NULL;
147 **list_tail = e;
148 *list_tail = &e->next;
151 /* Recursively remove constraints from an rtx. */
153 static void
154 remove_constraints (part)
155 rtx part;
157 int i, j;
158 const char *format_ptr;
160 if (part == 0)
161 return;
163 if (GET_CODE (part) == MATCH_OPERAND)
164 XSTR (part, 2) = "";
165 else if (GET_CODE (part) == MATCH_SCRATCH)
166 XSTR (part, 1) = "";
168 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
170 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
171 switch (*format_ptr++)
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;
185 /* Process an include file assuming that it lives in gcc/config/{target}/
186 if the include looks like (include "file"). */
188 static void
189 process_include (desc, lineno)
190 rtx desc;
191 int lineno;
193 const char *filename = XSTR (desc, 0);
194 const char *old_filename;
195 int old_lineno;
196 char *pathname;
197 FILE *input_file;
199 /* If specified file name is absolute, skip the include stack. */
200 if (! IS_ABSOLUTE_PATHNAME (filename))
202 struct file_name_list *stackp;
204 /* Search directory path, trying to open the file. */
205 for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
207 static const char sep[2] = { DIR_SEPARATOR, '\0' };
209 pathname = concat (stackp->fname, sep, filename, NULL);
210 input_file = fopen (pathname, "r");
211 if (input_file != NULL)
212 goto success;
213 free (pathname);
217 if (base_dir)
218 pathname = concat (base_dir, filename, NULL);
219 else
220 pathname = xstrdup (filename);
221 input_file = fopen (pathname, "r");
222 if (input_file == NULL)
224 free (pathname);
225 message_with_line (lineno, "include file `%s' not found", filename);
226 errors = 1;
227 return;
229 success:
231 /* Save old cursor; setup new for the new file. Note that "lineno" the
232 argument to this function is the beginning of the include statement,
233 while read_rtx_lineno has already been advanced. */
234 old_filename = read_rtx_filename;
235 old_lineno = read_rtx_lineno;
236 read_rtx_filename = pathname;
237 read_rtx_lineno = 1;
239 /* Read the entire file. */
240 while (1)
242 rtx desc;
243 int c;
245 c = read_skip_spaces (input_file);
246 if (c == EOF)
247 break;
249 ungetc (c, input_file);
250 lineno = read_rtx_lineno;
251 desc = read_rtx (input_file);
252 process_rtx (desc, lineno);
255 /* Do not free pathname. It is attached to the various rtx queue
256 elements. */
258 read_rtx_filename = old_filename;
259 read_rtx_lineno = old_lineno;
261 fclose (input_file);
264 /* Process a top level rtx in some way, queueing as appropriate. */
266 static void
267 process_rtx (desc, lineno)
268 rtx desc;
269 int lineno;
271 switch (GET_CODE (desc))
273 case DEFINE_INSN:
274 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
275 break;
277 case DEFINE_COND_EXEC:
278 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
279 break;
281 case DEFINE_ATTR:
282 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
283 break;
285 case INCLUDE:
286 process_include (desc, lineno);
287 break;
289 case DEFINE_INSN_AND_SPLIT:
291 const char *split_cond;
292 rtx split;
293 rtvec attr;
294 int i;
296 /* Create a split with values from the insn_and_split. */
297 split = rtx_alloc (DEFINE_SPLIT);
299 i = XVECLEN (desc, 1);
300 XVEC (split, 0) = rtvec_alloc (i);
301 while (--i >= 0)
303 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
304 remove_constraints (XVECEXP (split, 0, i));
307 /* If the split condition starts with "&&", append it to the
308 insn condition to create the new split condition. */
309 split_cond = XSTR (desc, 4);
310 if (split_cond[0] == '&' && split_cond[1] == '&')
312 const char *insn_cond = XSTR (desc, 2);
313 size_t insn_cond_len = strlen (insn_cond);
314 size_t split_cond_len = strlen (split_cond);
315 char *combined;
317 combined = (char *) xmalloc (insn_cond_len + split_cond_len + 1);
318 memcpy (combined, insn_cond, insn_cond_len);
319 memcpy (combined + insn_cond_len, split_cond, split_cond_len + 1);
321 split_cond = combined;
323 XSTR (split, 1) = split_cond;
324 XVEC (split, 2) = XVEC (desc, 5);
325 XSTR (split, 3) = XSTR (desc, 6);
327 /* Fix up the DEFINE_INSN. */
328 attr = XVEC (desc, 7);
329 PUT_CODE (desc, DEFINE_INSN);
330 XVEC (desc, 4) = attr;
332 /* Queue them. */
333 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
334 queue_pattern (split, &other_tail, read_rtx_filename, lineno);
335 break;
338 default:
339 queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
340 break;
344 /* Return true if attribute PREDICABLE is true for ELEM, which holds
345 a DEFINE_INSN. */
347 static int
348 is_predicable (elem)
349 struct queue_elem *elem;
351 rtvec vec = XVEC (elem->data, 4);
352 const char *value;
353 int i;
355 if (! vec)
356 return predicable_default;
358 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
360 rtx sub = RTVEC_ELT (vec, i);
361 switch (GET_CODE (sub))
363 case SET_ATTR:
364 if (strcmp (XSTR (sub, 0), "predicable") == 0)
366 value = XSTR (sub, 1);
367 goto found;
369 break;
371 case SET_ATTR_ALTERNATIVE:
372 if (strcmp (XSTR (sub, 0), "predicable") == 0)
374 message_with_line (elem->lineno,
375 "multiple alternatives for `predicable'");
376 errors = 1;
377 return 0;
379 break;
381 case SET:
382 if (GET_CODE (SET_DEST (sub)) != ATTR
383 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
384 break;
385 sub = SET_SRC (sub);
386 if (GET_CODE (sub) == CONST_STRING)
388 value = XSTR (sub, 0);
389 goto found;
392 /* ??? It would be possible to handle this if we really tried.
393 It's not easy though, and I'm not going to bother until it
394 really proves necessary. */
395 message_with_line (elem->lineno,
396 "non-constant value for `predicable'");
397 errors = 1;
398 return 0;
400 default:
401 abort ();
405 return predicable_default;
407 found:
408 /* Verify that predicability does not vary on the alternative. */
409 /* ??? It should be possible to handle this by simply eliminating
410 the non-predicable alternatives from the insn. FRV would like
411 to do this. Delay this until we've got the basics solid. */
412 if (strchr (value, ',') != NULL)
414 message_with_line (elem->lineno,
415 "multiple alternatives for `predicable'");
416 errors = 1;
417 return 0;
420 /* Find out which value we're looking at. */
421 if (strcmp (value, predicable_true) == 0)
422 return 1;
423 if (strcmp (value, predicable_false) == 0)
424 return 0;
426 message_with_line (elem->lineno,
427 "unknown value `%s' for `predicable' attribute",
428 value);
429 errors = 1;
430 return 0;
433 /* Examine the attribute "predicable"; discover its boolean values
434 and its default. */
436 static void
437 identify_predicable_attribute ()
439 struct queue_elem *elem;
440 char *p_true, *p_false;
441 const char *value;
442 size_t len;
444 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
445 for (elem = define_attr_queue; elem ; elem = elem->next)
446 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
447 goto found;
449 message_with_line (define_cond_exec_queue->lineno,
450 "attribute `predicable' not defined");
451 errors = 1;
452 return;
454 found:
455 value = XSTR (elem->data, 1);
456 len = strlen (value);
457 p_false = (char *) xmalloc (len + 1);
458 memcpy (p_false, value, len + 1);
460 p_true = strchr (p_false, ',');
461 if (p_true == NULL || strchr (++p_true, ',') != NULL)
463 message_with_line (elem->lineno,
464 "attribute `predicable' is not a boolean");
465 errors = 1;
466 return;
468 p_true[-1] = '\0';
470 predicable_true = p_true;
471 predicable_false = p_false;
473 switch (GET_CODE (XEXP (elem->data, 2)))
475 case CONST_STRING:
476 value = XSTR (XEXP (elem->data, 2), 0);
477 break;
479 case CONST:
480 message_with_line (elem->lineno,
481 "attribute `predicable' cannot be const");
482 errors = 1;
483 return;
485 default:
486 message_with_line (elem->lineno,
487 "attribute `predicable' must have a constant default");
488 errors = 1;
489 return;
492 if (strcmp (value, p_true) == 0)
493 predicable_default = 1;
494 else if (strcmp (value, p_false) == 0)
495 predicable_default = 0;
496 else
498 message_with_line (elem->lineno,
499 "unknown value `%s' for `predicable' attribute",
500 value);
501 errors = 1;
505 /* Return the number of alternatives in constraint S. */
507 static int
508 n_alternatives (s)
509 const char *s;
511 int n = 1;
513 if (s)
514 while (*s)
515 n += (*s++ == ',');
517 return n;
520 /* Determine how many alternatives there are in INSN, and how many
521 operands. */
523 static void
524 collect_insn_data (pattern, palt, pmax)
525 rtx pattern;
526 int *palt, *pmax;
528 const char *fmt;
529 enum rtx_code code;
530 int i, j, len;
532 code = GET_CODE (pattern);
533 switch (code)
535 case MATCH_OPERAND:
536 i = n_alternatives (XSTR (pattern, 2));
537 *palt = (i > *palt ? i : *palt);
538 /* FALLTHRU */
540 case MATCH_OPERATOR:
541 case MATCH_SCRATCH:
542 case MATCH_PARALLEL:
543 case MATCH_INSN:
544 i = XINT (pattern, 0);
545 if (i > *pmax)
546 *pmax = i;
547 break;
549 default:
550 break;
553 fmt = GET_RTX_FORMAT (code);
554 len = GET_RTX_LENGTH (code);
555 for (i = 0; i < len; i++)
557 switch (fmt[i])
559 case 'e': case 'u':
560 collect_insn_data (XEXP (pattern, i), palt, pmax);
561 break;
563 case 'V':
564 if (XVEC (pattern, i) == NULL)
565 break;
566 /* FALLTHRU */
567 case 'E':
568 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
569 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
570 break;
572 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
573 break;
575 default:
576 abort ();
581 static rtx
582 alter_predicate_for_insn (pattern, alt, max_op, lineno)
583 rtx pattern;
584 int alt, max_op, lineno;
586 const char *fmt;
587 enum rtx_code code;
588 int i, j, len;
590 code = GET_CODE (pattern);
591 switch (code)
593 case MATCH_OPERAND:
595 const char *c = XSTR (pattern, 2);
597 if (n_alternatives (c) != 1)
599 message_with_line (lineno,
600 "too many alternatives for operand %d",
601 XINT (pattern, 0));
602 errors = 1;
603 return NULL;
606 /* Replicate C as needed to fill out ALT alternatives. */
607 if (c && *c && alt > 1)
609 size_t c_len = strlen (c);
610 size_t len = alt * (c_len + 1);
611 char *new_c = (char *) xmalloc (len);
613 memcpy (new_c, c, c_len);
614 for (i = 1; i < alt; ++i)
616 new_c[i * (c_len + 1) - 1] = ',';
617 memcpy (&new_c[i * (c_len + 1)], c, c_len);
619 new_c[len - 1] = '\0';
620 XSTR (pattern, 2) = new_c;
623 /* FALLTHRU */
625 case MATCH_OPERATOR:
626 case MATCH_SCRATCH:
627 case MATCH_PARALLEL:
628 case MATCH_INSN:
629 XINT (pattern, 0) += max_op;
630 break;
632 default:
633 break;
636 fmt = GET_RTX_FORMAT (code);
637 len = GET_RTX_LENGTH (code);
638 for (i = 0; i < len; i++)
640 rtx r;
642 switch (fmt[i])
644 case 'e': case 'u':
645 r = alter_predicate_for_insn (XEXP (pattern, i), alt,
646 max_op, lineno);
647 if (r == NULL)
648 return r;
649 break;
651 case 'E':
652 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
654 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
655 alt, max_op, lineno);
656 if (r == NULL)
657 return r;
659 break;
661 case 'i': case 'w': case '0': case 's':
662 break;
664 default:
665 abort ();
669 return pattern;
672 static const char *
673 alter_test_for_insn (ce_elem, insn_elem)
674 struct queue_elem *ce_elem, *insn_elem;
676 const char *ce_test, *insn_test;
677 char *new_test;
678 size_t len, ce_len, insn_len;
680 ce_test = XSTR (ce_elem->data, 1);
681 insn_test = XSTR (insn_elem->data, 2);
682 if (!ce_test || *ce_test == '\0')
683 return insn_test;
684 if (!insn_test || *insn_test == '\0')
685 return ce_test;
687 ce_len = strlen (ce_test);
688 insn_len = strlen (insn_test);
689 len = 1 + ce_len + 1 + 4 + 1 + insn_len + 1 + 1;
690 new_test = (char *) xmalloc (len);
692 sprintf (new_test, "(%s) && (%s)", ce_test, insn_test);
694 return new_test;
697 /* Adjust all of the operand numbers in OLD to match the shift they'll
698 get from an operand displacement of DISP. Return a pointer after the
699 adjusted string. */
701 static char *
702 shift_output_template (new, old, disp)
703 char *new;
704 const char *old;
705 int disp;
707 while (*old)
709 char c = *old++;
710 *new++ = c;
711 if (c == '%')
713 c = *old++;
714 if (ISDIGIT ((unsigned char) c))
715 c += disp;
716 else if (ISALPHA (c))
718 *new++ = c;
719 c = *old++ + disp;
721 *new++ = c;
725 return new;
728 static const char *
729 alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
730 struct queue_elem *ce_elem, *insn_elem;
731 int alt, max_op;
733 const char *ce_out, *insn_out;
734 char *new, *p;
735 size_t len, ce_len, insn_len;
737 /* ??? Could coordinate with genoutput to not duplicate code here. */
739 ce_out = XSTR (ce_elem->data, 2);
740 insn_out = XTMPL (insn_elem->data, 3);
741 if (!ce_out || *ce_out == '\0')
742 return insn_out;
744 ce_len = strlen (ce_out);
745 insn_len = strlen (insn_out);
747 if (*insn_out == '*')
748 /* You must take care of the predicate yourself. */
749 return insn_out;
751 if (*insn_out == '@')
753 len = (ce_len + 1) * alt + insn_len + 1;
754 p = new = xmalloc (len);
759 *p++ = *insn_out++;
760 while (ISSPACE ((unsigned char) *insn_out));
762 if (*insn_out != '#')
764 p = shift_output_template (p, ce_out, max_op);
765 *p++ = ' ';
769 *p++ = *insn_out++;
770 while (*insn_out && *insn_out != '\n');
772 while (*insn_out);
773 *p = '\0';
775 else
777 len = ce_len + 1 + insn_len + 1;
778 new = xmalloc (len);
780 p = shift_output_template (new, ce_out, max_op);
781 *p++ = ' ';
782 memcpy (p, insn_out, insn_len + 1);
785 return new;
788 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
790 static void
791 process_one_cond_exec (ce_elem)
792 struct queue_elem *ce_elem;
794 struct queue_elem *insn_elem;
795 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
797 int alternatives, max_operand;
798 rtx pred, insn, pattern;
800 if (! is_predicable (insn_elem))
801 continue;
803 alternatives = 1;
804 max_operand = -1;
805 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
806 max_operand += 1;
808 if (XVECLEN (ce_elem->data, 0) != 1)
810 message_with_line (ce_elem->lineno,
811 "too many patterns in predicate");
812 errors = 1;
813 return;
816 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
817 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
818 ce_elem->lineno);
819 if (pred == NULL)
820 return;
822 /* Construct a new pattern for the new insn. */
823 insn = copy_rtx (insn_elem->data);
824 XSTR (insn, 0) = "";
825 pattern = rtx_alloc (COND_EXEC);
826 XEXP (pattern, 0) = pred;
827 if (XVECLEN (insn, 1) == 1)
829 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
830 XVECEXP (insn, 1, 0) = pattern;
831 PUT_NUM_ELEM (XVEC (insn, 1), 1);
833 else
835 XEXP (pattern, 1) = rtx_alloc (PARALLEL);
836 XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
837 XVEC (insn, 1) = rtvec_alloc (1);
838 XVECEXP (insn, 1, 0) = pattern;
841 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
842 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
843 alternatives, max_operand);
845 /* ??? Set `predicable' to false. Not crucial since it's really
846 only used here, and we won't reprocess this new pattern. */
848 /* Put the new pattern on the `other' list so that it
849 (a) is not reprocessed by other define_cond_exec patterns
850 (b) appears after all normal define_insn patterns.
852 ??? B is debatable. If one has normal insns that match
853 cond_exec patterns, they will be preferred over these
854 generated patterns. Whether this matters in practice, or if
855 it's a good thing, or whether we should thread these new
856 patterns into the define_insn chain just after their generator
857 is something we'll have to experiment with. */
859 queue_pattern (insn, &other_tail, insn_elem->filename,
860 insn_elem->lineno);
864 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
865 patterns appropriately. */
867 static void
868 process_define_cond_exec ()
870 struct queue_elem *elem;
872 identify_predicable_attribute ();
873 if (errors)
874 return;
876 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
877 process_one_cond_exec (elem);
880 static char *
881 save_string (s, len)
882 const char *s;
883 int len;
885 register char *result = xmalloc (len + 1);
887 memcpy (result, s, len);
888 result[len] = 0;
889 return result;
893 /* The entry point for initializing the reader. */
896 init_md_reader_args (argc, argv)
897 int argc;
898 char **argv;
900 int i;
901 const char *in_fname;
903 max_include_len = 0;
904 in_fname = NULL;
905 for (i = 1; i < argc; i++)
907 if (argv[i][0] != '-')
909 if (in_fname == NULL)
910 in_fname = argv[i];
912 else
914 int c = argv[i][1];
915 switch (c)
917 case 'I': /* Add directory to path for includes. */
919 struct file_name_list *dirtmp;
921 dirtmp = (struct file_name_list *)
922 xmalloc (sizeof (struct file_name_list));
923 dirtmp->next = 0; /* New one goes on the end */
924 if (first_dir_md_include == 0)
925 first_dir_md_include = dirtmp;
926 else
927 last_dir_md_include->next = dirtmp;
928 last_dir_md_include = dirtmp; /* Tail follows the last one */
929 if (argv[i][1] == 'I' && argv[i][2] != 0)
930 dirtmp->fname = argv[i] + 2;
931 else if (i + 1 == argc)
932 fatal ("directory name missing after -I option");
933 else
934 dirtmp->fname = argv[++i];
935 if (strlen (dirtmp->fname) > max_include_len)
936 max_include_len = strlen (dirtmp->fname);
938 break;
939 default:
940 fatal ("invalid option `%s'", argv[i]);
945 return init_md_reader (in_fname);
948 /* The entry point for initializing the reader. */
951 init_md_reader (filename)
952 const char *filename;
954 FILE *input_file;
955 int c;
956 char *lastsl;
958 lastsl = strrchr (filename, '/');
959 if (lastsl != NULL)
960 base_dir = save_string (filename, lastsl - filename + 1 );
962 read_rtx_filename = filename;
963 input_file = fopen (filename, "r");
964 if (input_file == 0)
966 perror (filename);
967 return FATAL_EXIT_CODE;
970 obstack_init (rtl_obstack);
971 errors = 0;
972 sequence_num = 0;
974 /* Read the entire file. */
975 while (1)
977 rtx desc;
978 int lineno;
980 c = read_skip_spaces (input_file);
981 if (c == EOF)
982 break;
984 ungetc (c, input_file);
985 lineno = read_rtx_lineno;
986 desc = read_rtx (input_file);
987 process_rtx (desc, lineno);
989 fclose (input_file);
991 /* Process define_cond_exec patterns. */
992 if (define_cond_exec_queue != NULL)
993 process_define_cond_exec ();
995 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
998 /* The entry point for reading a single rtx from an md file. */
1001 read_md_rtx (lineno, seqnr)
1002 int *lineno;
1003 int *seqnr;
1005 struct queue_elem **queue, *elem;
1006 rtx desc;
1008 /* Read all patterns from a given queue before moving on to the next. */
1009 if (define_attr_queue != NULL)
1010 queue = &define_attr_queue;
1011 else if (define_insn_queue != NULL)
1012 queue = &define_insn_queue;
1013 else if (other_queue != NULL)
1014 queue = &other_queue;
1015 else
1016 return NULL_RTX;
1018 elem = *queue;
1019 *queue = elem->next;
1020 desc = elem->data;
1021 read_rtx_filename = elem->filename;
1022 *lineno = elem->lineno;
1023 *seqnr = sequence_num;
1025 free (elem);
1027 switch (GET_CODE (desc))
1029 case DEFINE_INSN:
1030 case DEFINE_EXPAND:
1031 case DEFINE_SPLIT:
1032 case DEFINE_PEEPHOLE:
1033 case DEFINE_PEEPHOLE2:
1034 sequence_num++;
1035 break;
1037 default:
1038 break;
1041 return desc;
1044 /* Given a string, return the number of comma-separated elements in it.
1045 Return 0 for the null string. */
1047 n_comma_elts (s)
1048 const char *s;
1050 int n;
1052 if (*s == '\0')
1053 return 0;
1055 for (n = 1; *s; s++)
1056 if (*s == ',')
1057 n++;
1059 return n;
1062 /* Given a pointer to a (char *), return a pointer to the beginning of the
1063 next comma-separated element in the string. Advance the pointer given
1064 to the end of that element. Return NULL if at end of string. Caller
1065 is responsible for copying the string if necessary. White space between
1066 a comma and an element is ignored. */
1068 const char *
1069 scan_comma_elt (pstr)
1070 const char **pstr;
1072 const char *start;
1073 const char *p = *pstr;
1075 if (*p == ',')
1076 p++;
1077 while (ISSPACE(*p))
1078 p++;
1080 if (*p == '\0')
1081 return NULL;
1083 start = p;
1085 while (*p != ',' && *p != '\0')
1086 p++;
1088 *pstr = p;
1089 return start;