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