]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/gensupport.c
Merge basic-improvements-branch to trunk
[thirdparty/gcc.git] / gcc / gensupport.c
1 /* Support routines for the various generation passes.
2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
14 License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING. If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 #include "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"
30
31
32 /* In case some macros used by files we include need it, define this here. */
33 int target_flags;
34
35 int insn_elision = 1;
36
37 static struct obstack obstack;
38 struct obstack *rtl_obstack = &obstack;
39
40 static int sequence_num;
41 static int errors;
42
43 static int predicable_default;
44 static const char *predicable_true;
45 static const char *predicable_false;
46
47 static htab_t condition_table;
48
49 static char *base_dir = NULL;
50
51 /* We initially queue all patterns, process the define_insn and
52 define_cond_exec patterns, then return them one at a time. */
53
54 struct queue_elem
55 {
56 rtx data;
57 const char *filename;
58 int lineno;
59 struct queue_elem *next;
60 };
61
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;
70
71 static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
72 const char *, int));
73
74 /* Current maximum length of directory names in the search path
75 for include files. (Altered as we get more of them.) */
76
77 size_t max_include_len;
78
79 struct file_name_list
80 {
81 struct file_name_list *next;
82 const char *fname;
83 };
84
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 */
89
90 static void remove_constraints PARAMS ((rtx));
91 static void process_rtx PARAMS ((rtx, int));
92
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));
108 \f
109 void
110 message_with_line VPARAMS ((int lineno, const char *msg, ...))
111 {
112 VA_OPEN (ap, msg);
113 VA_FIXEDARG (ap, int, lineno);
114 VA_FIXEDARG (ap, const char *, msg);
115
116 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
117 vfprintf (stderr, msg, ap);
118 fputc ('\n', stderr);
119
120 VA_CLOSE (ap);
121 }
122
123 /* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
124 the gensupport programs. */
125
126 rtx
127 gen_rtx_CONST_INT (mode, arg)
128 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 (pattern, list_tail, filename, lineno)
141 rtx pattern;
142 struct queue_elem ***list_tail;
143 const char *filename;
144 int lineno;
145 {
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;
153 }
154
155 /* Recursively remove constraints from an rtx. */
156
157 static void
158 remove_constraints (part)
159 rtx part;
160 {
161 int i, j;
162 const char *format_ptr;
163
164 if (part == 0)
165 return;
166
167 if (GET_CODE (part) == MATCH_OPERAND)
168 XSTR (part, 2) = "";
169 else if (GET_CODE (part) == MATCH_SCRATCH)
170 XSTR (part, 1) = "";
171
172 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
173
174 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
175 switch (*format_ptr++)
176 {
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;
186 }
187 }
188
189 /* Process an include file assuming that it lives in gcc/config/{target}/
190 if the include looks like (include "file"). */
191
192 static void
193 process_include (desc, lineno)
194 rtx desc;
195 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_PATHNAME (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, queueing as appropriate. */
269
270 static void
271 process_rtx (desc, lineno)
272 rtx desc;
273 int lineno;
274 {
275 switch (GET_CODE (desc))
276 {
277 case DEFINE_INSN:
278 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
279 break;
280
281 case DEFINE_COND_EXEC:
282 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
283 break;
284
285 case DEFINE_ATTR:
286 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
287 break;
288
289 case INCLUDE:
290 process_include (desc, lineno);
291 break;
292
293 case DEFINE_INSN_AND_SPLIT:
294 {
295 const char *split_cond;
296 rtx split;
297 rtvec attr;
298 int i;
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 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
327 queue_pattern (split, &other_tail, read_rtx_filename, lineno);
328 break;
329 }
330
331 default:
332 queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
333 break;
334 }
335 }
336 \f
337 /* Return true if attribute PREDICABLE is true for ELEM, which holds
338 a DEFINE_INSN. */
339
340 static int
341 is_predicable (elem)
342 struct queue_elem *elem;
343 {
344 rtvec vec = XVEC (elem->data, 4);
345 const char *value;
346 int i;
347
348 if (! vec)
349 return predicable_default;
350
351 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
352 {
353 rtx sub = RTVEC_ELT (vec, i);
354 switch (GET_CODE (sub))
355 {
356 case SET_ATTR:
357 if (strcmp (XSTR (sub, 0), "predicable") == 0)
358 {
359 value = XSTR (sub, 1);
360 goto found;
361 }
362 break;
363
364 case SET_ATTR_ALTERNATIVE:
365 if (strcmp (XSTR (sub, 0), "predicable") == 0)
366 {
367 message_with_line (elem->lineno,
368 "multiple alternatives for `predicable'");
369 errors = 1;
370 return 0;
371 }
372 break;
373
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)
380 {
381 value = XSTR (sub, 0);
382 goto found;
383 }
384
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;
392
393 default:
394 abort ();
395 }
396 }
397
398 return predicable_default;
399
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)
406 {
407 message_with_line (elem->lineno,
408 "multiple alternatives for `predicable'");
409 errors = 1;
410 return 0;
411 }
412
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;
418
419 message_with_line (elem->lineno,
420 "unknown value `%s' for `predicable' attribute",
421 value);
422 errors = 1;
423 return 0;
424 }
425
426 /* Examine the attribute "predicable"; discover its boolean values
427 and its default. */
428
429 static void
430 identify_predicable_attribute ()
431 {
432 struct queue_elem *elem;
433 char *p_true, *p_false;
434 const char *value;
435
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;
440
441 message_with_line (define_cond_exec_queue->lineno,
442 "attribute `predicable' not defined");
443 errors = 1;
444 return;
445
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)
451 {
452 message_with_line (elem->lineno,
453 "attribute `predicable' is not a boolean");
454 errors = 1;
455 return;
456 }
457 p_true[-1] = '\0';
458
459 predicable_true = p_true;
460 predicable_false = p_false;
461
462 switch (GET_CODE (XEXP (elem->data, 2)))
463 {
464 case CONST_STRING:
465 value = XSTR (XEXP (elem->data, 2), 0);
466 break;
467
468 case CONST:
469 message_with_line (elem->lineno,
470 "attribute `predicable' cannot be const");
471 errors = 1;
472 return;
473
474 default:
475 message_with_line (elem->lineno,
476 "attribute `predicable' must have a constant default");
477 errors = 1;
478 return;
479 }
480
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
486 {
487 message_with_line (elem->lineno,
488 "unknown value `%s' for `predicable' attribute",
489 value);
490 errors = 1;
491 }
492 }
493
494 /* Return the number of alternatives in constraint S. */
495
496 static int
497 n_alternatives (s)
498 const char *s;
499 {
500 int n = 1;
501
502 if (s)
503 while (*s)
504 n += (*s++ == ',');
505
506 return n;
507 }
508
509 /* Determine how many alternatives there are in INSN, and how many
510 operands. */
511
512 static void
513 collect_insn_data (pattern, palt, pmax)
514 rtx pattern;
515 int *palt, *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 /* FALLTHRU */
528
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;
537
538 default:
539 break;
540 }
541
542 fmt = GET_RTX_FORMAT (code);
543 len = GET_RTX_LENGTH (code);
544 for (i = 0; i < len; i++)
545 {
546 switch (fmt[i])
547 {
548 case 'e': case 'u':
549 collect_insn_data (XEXP (pattern, i), palt, pmax);
550 break;
551
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;
560
561 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
562 break;
563
564 default:
565 abort ();
566 }
567 }
568 }
569
570 static rtx
571 alter_predicate_for_insn (pattern, alt, max_op, lineno)
572 rtx pattern;
573 int alt, max_op, lineno;
574 {
575 const char *fmt;
576 enum rtx_code code;
577 int i, j, len;
578
579 code = GET_CODE (pattern);
580 switch (code)
581 {
582 case MATCH_OPERAND:
583 {
584 const char *c = XSTR (pattern, 2);
585
586 if (n_alternatives (c) != 1)
587 {
588 message_with_line (lineno,
589 "too many alternatives for operand %d",
590 XINT (pattern, 0));
591 errors = 1;
592 return NULL;
593 }
594
595 /* Replicate C as needed to fill out ALT alternatives. */
596 if (c && *c && alt > 1)
597 {
598 size_t c_len = strlen (c);
599 size_t len = alt * (c_len + 1);
600 char *new_c = (char *) xmalloc (len);
601
602 memcpy (new_c, c, c_len);
603 for (i = 1; i < alt; ++i)
604 {
605 new_c[i * (c_len + 1) - 1] = ',';
606 memcpy (&new_c[i * (c_len + 1)], c, c_len);
607 }
608 new_c[len - 1] = '\0';
609 XSTR (pattern, 2) = new_c;
610 }
611 }
612 /* FALLTHRU */
613
614 case MATCH_OPERATOR:
615 case MATCH_SCRATCH:
616 case MATCH_PARALLEL:
617 case MATCH_INSN:
618 XINT (pattern, 0) += max_op;
619 break;
620
621 default:
622 break;
623 }
624
625 fmt = GET_RTX_FORMAT (code);
626 len = GET_RTX_LENGTH (code);
627 for (i = 0; i < len; i++)
628 {
629 rtx r;
630
631 switch (fmt[i])
632 {
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;
639
640 case 'E':
641 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
642 {
643 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
644 alt, max_op, lineno);
645 if (r == NULL)
646 return r;
647 }
648 break;
649
650 case 'i': case 'w': case '0': case 's':
651 break;
652
653 default:
654 abort ();
655 }
656 }
657
658 return pattern;
659 }
660
661 static const char *
662 alter_test_for_insn (ce_elem, insn_elem)
663 struct queue_elem *ce_elem, *insn_elem;
664 {
665 const char *ce_test, *insn_test;
666
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;
673
674 return concat ("(", ce_test, ") && (", insn_test, ")", NULL);
675 }
676
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. */
680
681 static char *
682 shift_output_template (new, old, disp)
683 char *new;
684 const char *old;
685 int disp;
686 {
687 while (*old)
688 {
689 char c = *old++;
690 *new++ = c;
691 if (c == '%')
692 {
693 c = *old++;
694 if (ISDIGIT ((unsigned char) c))
695 c += disp;
696 else if (ISALPHA (c))
697 {
698 *new++ = c;
699 c = *old++ + disp;
700 }
701 *new++ = c;
702 }
703 }
704
705 return new;
706 }
707
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;
712 {
713 const char *ce_out, *insn_out;
714 char *new, *p;
715 size_t len, ce_len, insn_len;
716
717 /* ??? Could coordinate with genoutput to not duplicate code here. */
718
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;
723
724 ce_len = strlen (ce_out);
725 insn_len = strlen (insn_out);
726
727 if (*insn_out == '*')
728 /* You must take care of the predicate yourself. */
729 return insn_out;
730
731 if (*insn_out == '@')
732 {
733 len = (ce_len + 1) * alt + insn_len + 1;
734 p = new = xmalloc (len);
735
736 do
737 {
738 do
739 *p++ = *insn_out++;
740 while (ISSPACE ((unsigned char) *insn_out));
741
742 if (*insn_out != '#')
743 {
744 p = shift_output_template (p, ce_out, max_op);
745 *p++ = ' ';
746 }
747
748 do
749 *p++ = *insn_out++;
750 while (*insn_out && *insn_out != '\n');
751 }
752 while (*insn_out);
753 *p = '\0';
754 }
755 else
756 {
757 len = ce_len + 1 + insn_len + 1;
758 new = xmalloc (len);
759
760 p = shift_output_template (new, ce_out, max_op);
761 *p++ = ' ';
762 memcpy (p, insn_out, insn_len + 1);
763 }
764
765 return new;
766 }
767
768 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
769
770 static void
771 process_one_cond_exec (ce_elem)
772 struct queue_elem *ce_elem;
773 {
774 struct queue_elem *insn_elem;
775 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
776 {
777 int alternatives, max_operand;
778 rtx pred, insn, pattern;
779
780 if (! is_predicable (insn_elem))
781 continue;
782
783 alternatives = 1;
784 max_operand = -1;
785 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
786 max_operand += 1;
787
788 if (XVECLEN (ce_elem->data, 0) != 1)
789 {
790 message_with_line (ce_elem->lineno,
791 "too many patterns in predicate");
792 errors = 1;
793 return;
794 }
795
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;
801
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)
808 {
809 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
810 XVECEXP (insn, 1, 0) = pattern;
811 PUT_NUM_ELEM (XVEC (insn, 1), 1);
812 }
813 else
814 {
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;
819 }
820
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);
824
825 /* ??? Set `predicable' to false. Not crucial since it's really
826 only used here, and we won't reprocess this new pattern. */
827
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.
831
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. */
838
839 queue_pattern (insn, &other_tail, insn_elem->filename,
840 insn_elem->lineno);
841 }
842 }
843
844 /* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
845 patterns appropriately. */
846
847 static void
848 process_define_cond_exec ()
849 {
850 struct queue_elem *elem;
851
852 identify_predicable_attribute ();
853 if (errors)
854 return;
855
856 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
857 process_one_cond_exec (elem);
858 }
859
860 static char *
861 save_string (s, len)
862 const char *s;
863 int len;
864 {
865 register char *result = xmalloc (len + 1);
866
867 memcpy (result, s, len);
868 result[len] = 0;
869 return result;
870 }
871
872 \f
873 /* The entry point for initializing the reader. */
874
875 int
876 init_md_reader_args (argc, argv)
877 int argc;
878 char **argv;
879 {
880 int i;
881 const char *in_fname;
882
883 max_include_len = 0;
884 in_fname = NULL;
885 for (i = 1; i < argc; i++)
886 {
887 if (argv[i][0] != '-')
888 {
889 if (in_fname == NULL)
890 in_fname = argv[i];
891 }
892 else
893 {
894 int c = argv[i][1];
895 switch (c)
896 {
897 case 'I': /* Add directory to path for includes. */
898 {
899 struct file_name_list *dirtmp;
900
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);
917 }
918 break;
919 default:
920 fatal ("invalid option `%s'", argv[i]);
921
922 }
923 }
924 }
925 return init_md_reader (in_fname);
926 }
927 \f
928 /* The entry point for initializing the reader. */
929
930 int
931 init_md_reader (filename)
932 const char *filename;
933 {
934 FILE *input_file;
935 int c;
936 size_t i;
937 char *lastsl;
938
939 lastsl = strrchr (filename, '/');
940 if (lastsl != NULL)
941 base_dir = save_string (filename, lastsl - filename + 1 );
942
943 read_rtx_filename = filename;
944 input_file = fopen (filename, "r");
945 if (input_file == 0)
946 {
947 perror (filename);
948 return FATAL_EXIT_CODE;
949 }
950
951 /* Initialize the table of insn conditions. */
952 condition_table = htab_create (n_insn_conditions,
953 hash_c_test, cmp_c_test, NULL);
954
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];
958
959 obstack_init (rtl_obstack);
960 errors = 0;
961 sequence_num = 0;
962
963 /* Read the entire file. */
964 while (1)
965 {
966 rtx desc;
967 int lineno;
968
969 c = read_skip_spaces (input_file);
970 if (c == EOF)
971 break;
972
973 ungetc (c, input_file);
974 lineno = read_rtx_lineno;
975 desc = read_rtx (input_file);
976 process_rtx (desc, lineno);
977 }
978 fclose (input_file);
979
980 /* Process define_cond_exec patterns. */
981 if (define_cond_exec_queue != NULL)
982 process_define_cond_exec ();
983
984 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
985 }
986
987 /* The entry point for reading a single rtx from an md file. */
988
989 rtx
990 read_md_rtx (lineno, seqnr)
991 int *lineno;
992 int *seqnr;
993 {
994 struct queue_elem **queue, *elem;
995 rtx desc;
996
997 discard:
998
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;
1008
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;
1015
1016 free (elem);
1017
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))
1025 {
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;
1033
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;
1042
1043 default:
1044 break;
1045 }
1046
1047 return desc;
1048 }
1049
1050 /* Helper functions for insn elision. */
1051
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;
1057 {
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;
1063
1064 base = s;
1065 hash = 0;
1066
1067 while ((c = *s++) != '\0')
1068 {
1069 hash += c + (c << 17);
1070 hash ^= hash >> 2;
1071 }
1072
1073 len = s - base;
1074 hash += len + (len << 17);
1075 hash ^= hash >> 2;
1076
1077 return hash;
1078 }
1079
1080 /* Compare two c_test expression structures. */
1081 int
1082 cmp_c_test (x, y)
1083 const PTR x;
1084 const PTR y;
1085 {
1086 const struct c_test *a = (const struct c_test *) x;
1087 const struct c_test *b = (const struct c_test *) y;
1088
1089 return !strcmp (a->expr, b->expr);
1090 }
1091
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. */
1096 int
1097 maybe_eval_c_test (expr)
1098 const char *expr;
1099 {
1100 const struct c_test *test;
1101 struct c_test dummy;
1102
1103 if (expr[0] == 0)
1104 return 1;
1105
1106 if (insn_elision_unavailable)
1107 return -1;
1108
1109 dummy.expr = expr;
1110 test = (const struct c_test *) htab_find (condition_table, &dummy);
1111 if (!test)
1112 abort ();
1113
1114 return test->value;
1115 }
1116
1117 /* Given a string, return the number of comma-separated elements in it.
1118 Return 0 for the null string. */
1119 int
1120 n_comma_elts (s)
1121 const char *s;
1122 {
1123 int n;
1124
1125 if (*s == '\0')
1126 return 0;
1127
1128 for (n = 1; *s; s++)
1129 if (*s == ',')
1130 n++;
1131
1132 return n;
1133 }
1134
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. */
1140
1141 const char *
1142 scan_comma_elt (pstr)
1143 const char **pstr;
1144 {
1145 const char *start;
1146 const char *p = *pstr;
1147
1148 if (*p == ',')
1149 p++;
1150 while (ISSPACE(*p))
1151 p++;
1152
1153 if (*p == '\0')
1154 return NULL;
1155
1156 start = p;
1157
1158 while (*p != ',' && *p != '\0')
1159 p++;
1160
1161 *pstr = p;
1162 return start;
1163 }