xref: /openbsd-src/gnu/usr.bin/gcc/gcc/gensupport.c (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
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