2003-05-05 Aldy Hernandez <aldyh@redhat.com>
[official-gcc.git] / gcc / gensupport.c
blobbc07c90317cc632a228eb77ef11869469591a12d
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 "bconfig.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "obstack.h"
27 #include "errors.h"
28 #include "hashtab.h"
29 #include "gensupport.h"
32 /* In case some macros used by files we include need it, define this here. */
33 int target_flags;
35 int insn_elision = 1;
37 static struct obstack obstack;
38 struct obstack *rtl_obstack = &obstack;
40 static int sequence_num;
41 static int errors;
43 static int predicable_default;
44 static const char *predicable_true;
45 static const char *predicable_false;
47 static htab_t condition_table;
49 static char *base_dir = NULL;
51 /* We initially queue all patterns, process the define_insn and
52 define_cond_exec patterns, then return them one at a time. */
54 struct queue_elem
56 rtx data;
57 const char *filename;
58 int lineno;
59 struct queue_elem *next;
62 static struct queue_elem *define_attr_queue;
63 static struct queue_elem **define_attr_tail = &define_attr_queue;
64 static struct queue_elem *define_insn_queue;
65 static struct queue_elem **define_insn_tail = &define_insn_queue;
66 static struct queue_elem *define_cond_exec_queue;
67 static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
68 static struct queue_elem *other_queue;
69 static struct queue_elem **other_tail = &other_queue;
71 static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
72 const char *, int));
74 /* Current maximum length of directory names in the search path
75 for include files. (Altered as we get more of them.) */
77 size_t max_include_len;
79 struct file_name_list
81 struct file_name_list *next;
82 const char *fname;
85 struct file_name_list *first_dir_md_include = 0; /* First dir to search */
86 /* First dir to search for <file> */
87 struct file_name_list *first_bracket_include = 0;
88 struct file_name_list *last_dir_md_include = 0; /* Last in chain */
90 static void remove_constraints PARAMS ((rtx));
91 static void process_rtx PARAMS ((rtx, int));
93 static int is_predicable PARAMS ((struct queue_elem *));
94 static void identify_predicable_attribute PARAMS ((void));
95 static int n_alternatives PARAMS ((const char *));
96 static void collect_insn_data PARAMS ((rtx, int *, int *));
97 static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
98 static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
99 struct queue_elem *));
100 static char *shift_output_template PARAMS ((char *, const char *, int));
101 static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
102 struct queue_elem *,
103 int, int));
104 static void process_one_cond_exec PARAMS ((struct queue_elem *));
105 static void process_define_cond_exec PARAMS ((void));
106 static void process_include PARAMS ((rtx, int));
107 static char *save_string PARAMS ((const char *, int));
109 void
110 message_with_line VPARAMS ((int lineno, const char *msg, ...))
112 VA_OPEN (ap, msg);
113 VA_FIXEDARG (ap, int, lineno);
114 VA_FIXEDARG (ap, const char *, msg);
116 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
117 vfprintf (stderr, msg, ap);
118 fputc ('\n', stderr);
120 VA_CLOSE (ap);
123 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
124 the gensupport programs. */
127 gen_rtx_CONST_INT (mode, arg)
128 enum machine_mode mode ATTRIBUTE_UNUSED;
129 HOST_WIDE_INT arg;
131 rtx rt = rtx_alloc (CONST_INT);
133 XWINT (rt, 0) = arg;
134 return rt;
137 /* Queue PATTERN on LIST_TAIL. */
139 static void
140 queue_pattern (pattern, list_tail, filename, lineno)
141 rtx pattern;
142 struct queue_elem ***list_tail;
143 const char *filename;
144 int lineno;
146 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
147 e->data = pattern;
148 e->filename = filename;
149 e->lineno = lineno;
150 e->next = NULL;
151 **list_tail = e;
152 *list_tail = &e->next;
155 /* Recursively remove constraints from an rtx. */
157 static void
158 remove_constraints (part)
159 rtx part;
161 int i, j;
162 const char *format_ptr;
164 if (part == 0)
165 return;
167 if (GET_CODE (part) == MATCH_OPERAND)
168 XSTR (part, 2) = "";
169 else if (GET_CODE (part) == MATCH_SCRATCH)
170 XSTR (part, 1) = "";
172 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
174 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
175 switch (*format_ptr++)
177 case 'e':
178 case 'u':
179 remove_constraints (XEXP (part, i));
180 break;
181 case 'E':
182 if (XVEC (part, i) != NULL)
183 for (j = 0; j < XVECLEN (part, i); j++)
184 remove_constraints (XVECEXP (part, i, j));
185 break;
189 /* Process an include file assuming that it lives in gcc/config/{target}/
190 if the include looks like (include "file"). */
192 static void
193 process_include (desc, lineno)
194 rtx desc;
195 int lineno;
197 const char *filename = XSTR (desc, 0);
198 const char *old_filename;
199 int old_lineno;
200 char *pathname;
201 FILE *input_file;
203 /* If specified file name is absolute, skip the include stack. */
204 if (! IS_ABSOLUTE_PATHNAME (filename))
206 struct file_name_list *stackp;
208 /* Search directory path, trying to open the file. */
209 for (stackp = first_dir_md_include; stackp; stackp = stackp->next)
211 static const char sep[2] = { DIR_SEPARATOR, '\0' };
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);
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)
228 free (pathname);
229 message_with_line (lineno, "include file `%s' not found", filename);
230 errors = 1;
231 return;
233 success:
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;
243 /* Read the entire file. */
244 while (1)
246 rtx desc;
247 int c;
249 c = read_skip_spaces (input_file);
250 if (c == EOF)
251 break;
253 ungetc (c, input_file);
254 lineno = read_rtx_lineno;
255 desc = read_rtx (input_file);
256 process_rtx (desc, lineno);
259 /* Do not free pathname. It is attached to the various rtx queue
260 elements. */
262 read_rtx_filename = old_filename;
263 read_rtx_lineno = old_lineno;
265 fclose (input_file);
268 /* Process a top level rtx in some way, queueing as appropriate. */
270 static void
271 process_rtx (desc, lineno)
272 rtx desc;
273 int lineno;
275 switch (GET_CODE (desc))
277 case DEFINE_INSN:
278 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
279 break;
281 case DEFINE_COND_EXEC:
282 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
283 break;
285 case DEFINE_ATTR:
286 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
287 break;
289 case INCLUDE:
290 process_include (desc, lineno);
291 break;
293 case DEFINE_INSN_AND_SPLIT:
295 const char *split_cond;
296 rtx split;
297 rtvec attr;
298 int i;
300 /* Create a split with values from the insn_and_split. */
301 split = rtx_alloc (DEFINE_SPLIT);
303 i = XVECLEN (desc, 1);
304 XVEC (split, 0) = rtvec_alloc (i);
305 while (--i >= 0)
307 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
308 remove_constraints (XVECEXP (split, 0, i));
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);
320 /* Fix up the DEFINE_INSN. */
321 attr = XVEC (desc, 7);
322 PUT_CODE (desc, DEFINE_INSN);
323 XVEC (desc, 4) = attr;
325 /* Queue them. */
326 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
327 queue_pattern (split, &other_tail, read_rtx_filename, lineno);
328 break;
331 default:
332 queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
333 break;
337 /* Return true if attribute PREDICABLE is true for ELEM, which holds
338 a DEFINE_INSN. */
340 static int
341 is_predicable (elem)
342 struct queue_elem *elem;
344 rtvec vec = XVEC (elem->data, 4);
345 const char *value;
346 int i;
348 if (! vec)
349 return predicable_default;
351 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
353 rtx sub = RTVEC_ELT (vec, i);
354 switch (GET_CODE (sub))
356 case SET_ATTR:
357 if (strcmp (XSTR (sub, 0), "predicable") == 0)
359 value = XSTR (sub, 1);
360 goto found;
362 break;
364 case SET_ATTR_ALTERNATIVE:
365 if (strcmp (XSTR (sub, 0), "predicable") == 0)
367 message_with_line (elem->lineno,
368 "multiple alternatives for `predicable'");
369 errors = 1;
370 return 0;
372 break;
374 case SET:
375 if (GET_CODE (SET_DEST (sub)) != ATTR
376 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
377 break;
378 sub = SET_SRC (sub);
379 if (GET_CODE (sub) == CONST_STRING)
381 value = XSTR (sub, 0);
382 goto found;
385 /* ??? It would be possible to handle this if we really tried.
386 It's not easy though, and I'm not going to bother until it
387 really proves necessary. */
388 message_with_line (elem->lineno,
389 "non-constant value for `predicable'");
390 errors = 1;
391 return 0;
393 default:
394 abort ();
398 return predicable_default;
400 found:
401 /* Verify that predicability does not vary on the alternative. */
402 /* ??? It should be possible to handle this by simply eliminating
403 the non-predicable alternatives from the insn. FRV would like
404 to do this. Delay this until we've got the basics solid. */
405 if (strchr (value, ',') != NULL)
407 message_with_line (elem->lineno,
408 "multiple alternatives for `predicable'");
409 errors = 1;
410 return 0;
413 /* Find out which value we're looking at. */
414 if (strcmp (value, predicable_true) == 0)
415 return 1;
416 if (strcmp (value, predicable_false) == 0)
417 return 0;
419 message_with_line (elem->lineno,
420 "unknown value `%s' for `predicable' attribute",
421 value);
422 errors = 1;
423 return 0;
426 /* Examine the attribute "predicable"; discover its boolean values
427 and its default. */
429 static void
430 identify_predicable_attribute ()
432 struct queue_elem *elem;
433 char *p_true, *p_false;
434 const char *value;
436 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
437 for (elem = define_attr_queue; elem ; elem = elem->next)
438 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
439 goto found;
441 message_with_line (define_cond_exec_queue->lineno,
442 "attribute `predicable' not defined");
443 errors = 1;
444 return;
446 found:
447 value = XSTR (elem->data, 1);
448 p_false = xstrdup (value);
449 p_true = strchr (p_false, ',');
450 if (p_true == NULL || strchr (++p_true, ',') != NULL)
452 message_with_line (elem->lineno,
453 "attribute `predicable' is not a boolean");
454 errors = 1;
455 return;
457 p_true[-1] = '\0';
459 predicable_true = p_true;
460 predicable_false = p_false;
462 switch (GET_CODE (XEXP (elem->data, 2)))
464 case CONST_STRING:
465 value = XSTR (XEXP (elem->data, 2), 0);
466 break;
468 case CONST:
469 message_with_line (elem->lineno,
470 "attribute `predicable' cannot be const");
471 errors = 1;
472 return;
474 default:
475 message_with_line (elem->lineno,
476 "attribute `predicable' must have a constant default");
477 errors = 1;
478 return;
481 if (strcmp (value, p_true) == 0)
482 predicable_default = 1;
483 else if (strcmp (value, p_false) == 0)
484 predicable_default = 0;
485 else
487 message_with_line (elem->lineno,
488 "unknown value `%s' for `predicable' attribute",
489 value);
490 errors = 1;
494 /* Return the number of alternatives in constraint S. */
496 static int
497 n_alternatives (s)
498 const char *s;
500 int n = 1;
502 if (s)
503 while (*s)
504 n += (*s++ == ',');
506 return n;
509 /* Determine how many alternatives there are in INSN, and how many
510 operands. */
512 static void
513 collect_insn_data (pattern, palt, pmax)
514 rtx pattern;
515 int *palt, *pmax;
517 const char *fmt;
518 enum rtx_code code;
519 int i, j, len;
521 code = GET_CODE (pattern);
522 switch (code)
524 case MATCH_OPERAND:
525 i = n_alternatives (XSTR (pattern, 2));
526 *palt = (i > *palt ? i : *palt);
527 /* FALLTHRU */
529 case MATCH_OPERATOR:
530 case MATCH_SCRATCH:
531 case MATCH_PARALLEL:
532 case MATCH_INSN:
533 i = XINT (pattern, 0);
534 if (i > *pmax)
535 *pmax = i;
536 break;
538 default:
539 break;
542 fmt = GET_RTX_FORMAT (code);
543 len = GET_RTX_LENGTH (code);
544 for (i = 0; i < len; i++)
546 switch (fmt[i])
548 case 'e': case 'u':
549 collect_insn_data (XEXP (pattern, i), palt, pmax);
550 break;
552 case 'V':
553 if (XVEC (pattern, i) == NULL)
554 break;
555 /* FALLTHRU */
556 case 'E':
557 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
558 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
559 break;
561 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
562 break;
564 default:
565 abort ();
570 static rtx
571 alter_predicate_for_insn (pattern, alt, max_op, lineno)
572 rtx pattern;
573 int alt, max_op, lineno;
575 const char *fmt;
576 enum rtx_code code;
577 int i, j, len;
579 code = GET_CODE (pattern);
580 switch (code)
582 case MATCH_OPERAND:
584 const char *c = XSTR (pattern, 2);
586 if (n_alternatives (c) != 1)
588 message_with_line (lineno,
589 "too many alternatives for operand %d",
590 XINT (pattern, 0));
591 errors = 1;
592 return NULL;
595 /* Replicate C as needed to fill out ALT alternatives. */
596 if (c && *c && alt > 1)
598 size_t c_len = strlen (c);
599 size_t len = alt * (c_len + 1);
600 char *new_c = (char *) xmalloc (len);
602 memcpy (new_c, c, c_len);
603 for (i = 1; i < alt; ++i)
605 new_c[i * (c_len + 1) - 1] = ',';
606 memcpy (&new_c[i * (c_len + 1)], c, c_len);
608 new_c[len - 1] = '\0';
609 XSTR (pattern, 2) = new_c;
612 /* FALLTHRU */
614 case MATCH_OPERATOR:
615 case MATCH_SCRATCH:
616 case MATCH_PARALLEL:
617 case MATCH_INSN:
618 XINT (pattern, 0) += max_op;
619 break;
621 default:
622 break;
625 fmt = GET_RTX_FORMAT (code);
626 len = GET_RTX_LENGTH (code);
627 for (i = 0; i < len; i++)
629 rtx r;
631 switch (fmt[i])
633 case 'e': case 'u':
634 r = alter_predicate_for_insn (XEXP (pattern, i), alt,
635 max_op, lineno);
636 if (r == NULL)
637 return r;
638 break;
640 case 'E':
641 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
643 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
644 alt, max_op, lineno);
645 if (r == NULL)
646 return r;
648 break;
650 case 'i': case 'w': case '0': case 's':
651 break;
653 default:
654 abort ();
658 return pattern;
661 static const char *
662 alter_test_for_insn (ce_elem, insn_elem)
663 struct queue_elem *ce_elem, *insn_elem;
665 const char *ce_test, *insn_test;
667 ce_test = XSTR (ce_elem->data, 1);
668 insn_test = XSTR (insn_elem->data, 2);
669 if (!ce_test || *ce_test == '\0')
670 return insn_test;
671 if (!insn_test || *insn_test == '\0')
672 return ce_test;
674 return concat ("(", ce_test, ") && (", insn_test, ")", NULL);
677 /* Adjust all of the operand numbers in OLD to match the shift they'll
678 get from an operand displacement of DISP. Return a pointer after the
679 adjusted string. */
681 static char *
682 shift_output_template (new, old, disp)
683 char *new;
684 const char *old;
685 int disp;
687 while (*old)
689 char c = *old++;
690 *new++ = c;
691 if (c == '%')
693 c = *old++;
694 if (ISDIGIT ((unsigned char) c))
695 c += disp;
696 else if (ISALPHA (c))
698 *new++ = c;
699 c = *old++ + disp;
701 *new++ = c;
705 return new;
708 static const char *
709 alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
710 struct queue_elem *ce_elem, *insn_elem;
711 int alt, max_op;
713 const char *ce_out, *insn_out;
714 char *new, *p;
715 size_t len, ce_len, insn_len;
717 /* ??? Could coordinate with genoutput to not duplicate code here. */
719 ce_out = XSTR (ce_elem->data, 2);
720 insn_out = XTMPL (insn_elem->data, 3);
721 if (!ce_out || *ce_out == '\0')
722 return insn_out;
724 ce_len = strlen (ce_out);
725 insn_len = strlen (insn_out);
727 if (*insn_out == '*')
728 /* You must take care of the predicate yourself. */
729 return insn_out;
731 if (*insn_out == '@')
733 len = (ce_len + 1) * alt + insn_len + 1;
734 p = new = xmalloc (len);
739 *p++ = *insn_out++;
740 while (ISSPACE ((unsigned char) *insn_out));
742 if (*insn_out != '#')
744 p = shift_output_template (p, ce_out, max_op);
745 *p++ = ' ';
749 *p++ = *insn_out++;
750 while (*insn_out && *insn_out != '\n');
752 while (*insn_out);
753 *p = '\0';
755 else
757 len = ce_len + 1 + insn_len + 1;
758 new = xmalloc (len);
760 p = shift_output_template (new, ce_out, max_op);
761 *p++ = ' ';
762 memcpy (p, insn_out, insn_len + 1);
765 return new;
768 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
770 static void
771 process_one_cond_exec (ce_elem)
772 struct queue_elem *ce_elem;
774 struct queue_elem *insn_elem;
775 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
777 int alternatives, max_operand;
778 rtx pred, insn, pattern;
780 if (! is_predicable (insn_elem))
781 continue;
783 alternatives = 1;
784 max_operand = -1;
785 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
786 max_operand += 1;
788 if (XVECLEN (ce_elem->data, 0) != 1)
790 message_with_line (ce_elem->lineno,
791 "too many patterns in predicate");
792 errors = 1;
793 return;
796 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
797 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
798 ce_elem->lineno);
799 if (pred == NULL)
800 return;
802 /* Construct a new pattern for the new insn. */
803 insn = copy_rtx (insn_elem->data);
804 XSTR (insn, 0) = "";
805 pattern = rtx_alloc (COND_EXEC);
806 XEXP (pattern, 0) = pred;
807 if (XVECLEN (insn, 1) == 1)
809 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
810 XVECEXP (insn, 1, 0) = pattern;
811 PUT_NUM_ELEM (XVEC (insn, 1), 1);
813 else
815 XEXP (pattern, 1) = rtx_alloc (PARALLEL);
816 XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
817 XVEC (insn, 1) = rtvec_alloc (1);
818 XVECEXP (insn, 1, 0) = pattern;
821 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
822 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
823 alternatives, max_operand);
825 /* ??? Set `predicable' to false. Not crucial since it's really
826 only used here, and we won't reprocess this new pattern. */
828 /* Put the new pattern on the `other' list so that it
829 (a) is not reprocessed by other define_cond_exec patterns
830 (b) appears after all normal define_insn patterns.
832 ??? B is debatable. If one has normal insns that match
833 cond_exec patterns, they will be preferred over these
834 generated patterns. Whether this matters in practice, or if
835 it's a good thing, or whether we should thread these new
836 patterns into the define_insn chain just after their generator
837 is something we'll have to experiment with. */
839 queue_pattern (insn, &other_tail, insn_elem->filename,
840 insn_elem->lineno);
844 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
845 patterns appropriately. */
847 static void
848 process_define_cond_exec ()
850 struct queue_elem *elem;
852 identify_predicable_attribute ();
853 if (errors)
854 return;
856 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
857 process_one_cond_exec (elem);
860 static char *
861 save_string (s, len)
862 const char *s;
863 int len;
865 register char *result = xmalloc (len + 1);
867 memcpy (result, s, len);
868 result[len] = 0;
869 return result;
873 /* The entry point for initializing the reader. */
876 init_md_reader_args (argc, argv)
877 int argc;
878 char **argv;
880 int i;
881 const char *in_fname;
883 max_include_len = 0;
884 in_fname = NULL;
885 for (i = 1; i < argc; i++)
887 if (argv[i][0] != '-')
889 if (in_fname == NULL)
890 in_fname = argv[i];
892 else
894 int c = argv[i][1];
895 switch (c)
897 case 'I': /* Add directory to path for includes. */
899 struct file_name_list *dirtmp;
901 dirtmp = (struct file_name_list *)
902 xmalloc (sizeof (struct file_name_list));
903 dirtmp->next = 0; /* New one goes on the end */
904 if (first_dir_md_include == 0)
905 first_dir_md_include = dirtmp;
906 else
907 last_dir_md_include->next = dirtmp;
908 last_dir_md_include = dirtmp; /* Tail follows the last one */
909 if (argv[i][1] == 'I' && argv[i][2] != 0)
910 dirtmp->fname = argv[i] + 2;
911 else if (i + 1 == argc)
912 fatal ("directory name missing after -I option");
913 else
914 dirtmp->fname = argv[++i];
915 if (strlen (dirtmp->fname) > max_include_len)
916 max_include_len = strlen (dirtmp->fname);
918 break;
919 default:
920 fatal ("invalid option `%s'", argv[i]);
925 return init_md_reader (in_fname);
928 /* The entry point for initializing the reader. */
931 init_md_reader (filename)
932 const char *filename;
934 FILE *input_file;
935 int c;
936 size_t i;
937 char *lastsl;
939 lastsl = strrchr (filename, '/');
940 if (lastsl != NULL)
941 base_dir = save_string (filename, lastsl - filename + 1 );
943 read_rtx_filename = filename;
944 input_file = fopen (filename, "r");
945 if (input_file == 0)
947 perror (filename);
948 return FATAL_EXIT_CODE;
951 /* Initialize the table of insn conditions. */
952 condition_table = htab_create (n_insn_conditions,
953 hash_c_test, cmp_c_test, NULL);
955 for (i = 0; i < n_insn_conditions; i++)
956 *(htab_find_slot (condition_table, (PTR) &insn_conditions[i], INSERT))
957 = (PTR) &insn_conditions[i];
959 obstack_init (rtl_obstack);
960 errors = 0;
961 sequence_num = 0;
963 /* Read the entire file. */
964 while (1)
966 rtx desc;
967 int lineno;
969 c = read_skip_spaces (input_file);
970 if (c == EOF)
971 break;
973 ungetc (c, input_file);
974 lineno = read_rtx_lineno;
975 desc = read_rtx (input_file);
976 process_rtx (desc, lineno);
978 fclose (input_file);
980 /* Process define_cond_exec patterns. */
981 if (define_cond_exec_queue != NULL)
982 process_define_cond_exec ();
984 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
987 /* The entry point for reading a single rtx from an md file. */
990 read_md_rtx (lineno, seqnr)
991 int *lineno;
992 int *seqnr;
994 struct queue_elem **queue, *elem;
995 rtx desc;
997 discard:
999 /* Read all patterns from a given queue before moving on to the next. */
1000 if (define_attr_queue != NULL)
1001 queue = &define_attr_queue;
1002 else if (define_insn_queue != NULL)
1003 queue = &define_insn_queue;
1004 else if (other_queue != NULL)
1005 queue = &other_queue;
1006 else
1007 return NULL_RTX;
1009 elem = *queue;
1010 *queue = elem->next;
1011 desc = elem->data;
1012 read_rtx_filename = elem->filename;
1013 *lineno = elem->lineno;
1014 *seqnr = sequence_num;
1016 free (elem);
1018 /* Discard insn patterns which we know can never match (because
1019 their C test is provably always false). If insn_elision is
1020 false, our caller needs to see all the patterns. Note that the
1021 elided patterns are never counted by the sequence numbering; it
1022 it is the caller's responsibility, when insn_elision is false, not
1023 to use elided pattern numbers for anything. */
1024 switch (GET_CODE (desc))
1026 case DEFINE_INSN:
1027 case DEFINE_EXPAND:
1028 if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
1029 sequence_num++;
1030 else if (insn_elision)
1031 goto discard;
1032 break;
1034 case DEFINE_SPLIT:
1035 case DEFINE_PEEPHOLE:
1036 case DEFINE_PEEPHOLE2:
1037 if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
1038 sequence_num++;
1039 else if (insn_elision)
1040 goto discard;
1041 break;
1043 default:
1044 break;
1047 return desc;
1050 /* Helper functions for insn elision. */
1052 /* Compute a hash function of a c_test structure, which is keyed
1053 by its ->expr field. */
1054 hashval_t
1055 hash_c_test (x)
1056 const PTR x;
1058 const struct c_test *a = (const struct c_test *) x;
1059 const unsigned char *base, *s = (const unsigned char *) a->expr;
1060 hashval_t hash;
1061 unsigned char c;
1062 unsigned int len;
1064 base = s;
1065 hash = 0;
1067 while ((c = *s++) != '\0')
1069 hash += c + (c << 17);
1070 hash ^= hash >> 2;
1073 len = s - base;
1074 hash += len + (len << 17);
1075 hash ^= hash >> 2;
1077 return hash;
1080 /* Compare two c_test expression structures. */
1082 cmp_c_test (x, y)
1083 const PTR x;
1084 const PTR y;
1086 const struct c_test *a = (const struct c_test *) x;
1087 const struct c_test *b = (const struct c_test *) y;
1089 return !strcmp (a->expr, b->expr);
1092 /* Given a string representing a C test expression, look it up in the
1093 condition_table and report whether or not its value is known
1094 at compile time. Returns a tristate: 1 for known true, 0 for
1095 known false, -1 for unknown. */
1097 maybe_eval_c_test (expr)
1098 const char *expr;
1100 const struct c_test *test;
1101 struct c_test dummy;
1103 if (expr[0] == 0)
1104 return 1;
1106 if (insn_elision_unavailable)
1107 return -1;
1109 dummy.expr = expr;
1110 test = (const struct c_test *) htab_find (condition_table, &dummy);
1111 if (!test)
1112 abort ();
1114 return test->value;
1117 /* Given a string, return the number of comma-separated elements in it.
1118 Return 0 for the null string. */
1120 n_comma_elts (s)
1121 const char *s;
1123 int n;
1125 if (*s == '\0')
1126 return 0;
1128 for (n = 1; *s; s++)
1129 if (*s == ',')
1130 n++;
1132 return n;
1135 /* Given a pointer to a (char *), return a pointer to the beginning of the
1136 next comma-separated element in the string. Advance the pointer given
1137 to the end of that element. Return NULL if at end of string. Caller
1138 is responsible for copying the string if necessary. White space between
1139 a comma and an element is ignored. */
1141 const char *
1142 scan_comma_elt (pstr)
1143 const char **pstr;
1145 const char *start;
1146 const char *p = *pstr;
1148 if (*p == ',')
1149 p++;
1150 while (ISSPACE(*p))
1151 p++;
1153 if (*p == '\0')
1154 return NULL;
1156 start = p;
1158 while (*p != ',' && *p != '\0')
1159 p++;
1161 *pstr = p;
1162 return start;