]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gensupport.c
ste.c (ffeste_R838): Handle ERROR_MARK.
[thirdparty/gcc.git] / gcc / gensupport.c
CommitLineData
3916d6d8 1/* Support routines for the various generation passes.
9a5834ae 2 Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
c88c0d42 3
1322177d 4 This file is part of GCC.
c88c0d42 5
1322177d
LB
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
c88c0d42
CP
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
1322177d
LB
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.
c88c0d42
CP
15
16 You should have received a copy of the GNU General Public License
1322177d
LB
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. */
c88c0d42 20
4977bab6 21#include "bconfig.h"
c88c0d42 22#include "system.h"
4977bab6
ZW
23#include "coretypes.h"
24#include "tm.h"
c88c0d42 25#include "rtl.h"
3916d6d8 26#include "obstack.h"
c88c0d42 27#include "errors.h"
2199e5fa 28#include "hashtab.h"
c88c0d42
CP
29#include "gensupport.h"
30
3916d6d8 31
c8cf201f
RK
32/* In case some macros used by files we include need it, define this here. */
33int target_flags;
34
2199e5fa
ZW
35int insn_elision = 1;
36
3916d6d8
RH
37static struct obstack obstack;
38struct obstack *rtl_obstack = &obstack;
39
c88c0d42 40static int sequence_num;
3262c1f5
RH
41static int errors;
42
43static int predicable_default;
44static const char *predicable_true;
45static const char *predicable_false;
46
2199e5fa
ZW
47static htab_t condition_table;
48
04d8aa70
AM
49static char *base_dir = NULL;
50
3262c1f5
RH
51/* We initially queue all patterns, process the define_insn and
52 define_cond_exec patterns, then return them one at a time. */
c88c0d42 53
3262c1f5
RH
54struct queue_elem
55{
56 rtx data;
821e35ba 57 const char *filename;
3262c1f5
RH
58 int lineno;
59 struct queue_elem *next;
c88c0d42
CP
60};
61
3262c1f5
RH
62static struct queue_elem *define_attr_queue;
63static struct queue_elem **define_attr_tail = &define_attr_queue;
64static struct queue_elem *define_insn_queue;
65static struct queue_elem **define_insn_tail = &define_insn_queue;
66static struct queue_elem *define_cond_exec_queue;
67static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
68static struct queue_elem *other_queue;
69static struct queue_elem **other_tail = &other_queue;
c88c0d42 70
821e35ba
RH
71static void queue_pattern PARAMS ((rtx, struct queue_elem ***,
72 const char *, int));
04d8aa70
AM
73
74/* Current maximum length of directory names in the search path
75 for include files. (Altered as we get more of them.) */
76
77size_t max_include_len;
78
79struct file_name_list
80 {
81 struct file_name_list *next;
82 const char *fname;
83 };
84
4ec59de2 85struct file_name_list *first_dir_md_include = 0; /* First dir to search */
04d8aa70
AM
86 /* First dir to search for <file> */
87struct file_name_list *first_bracket_include = 0;
4ec59de2 88struct file_name_list *last_dir_md_include = 0; /* Last in chain */
04d8aa70 89
36244024 90static void remove_constraints PARAMS ((rtx));
3262c1f5
RH
91static void process_rtx PARAMS ((rtx, int));
92
93static int is_predicable PARAMS ((struct queue_elem *));
94static void identify_predicable_attribute PARAMS ((void));
95static int n_alternatives PARAMS ((const char *));
96static void collect_insn_data PARAMS ((rtx, int *, int *));
97static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
98static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
99 struct queue_elem *));
100static char *shift_output_template PARAMS ((char *, const char *, int));
101static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
102 struct queue_elem *,
103 int, int));
104static void process_one_cond_exec PARAMS ((struct queue_elem *));
105static void process_define_cond_exec PARAMS ((void));
174cc7d1 106static void process_include PARAMS ((rtx, int));
04d8aa70 107static char *save_string PARAMS ((const char *, int));
3916d6d8
RH
108\f
109void
e34d07f2 110message_with_line (int lineno, const char *msg, ...)
3916d6d8 111{
e34d07f2
KG
112 va_list ap;
113
114 va_start (ap, msg);
36244024 115
3916d6d8
RH
116 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
117 vfprintf (stderr, msg, ap);
118 fputc ('\n', stderr);
119
e34d07f2 120 va_end (ap);
3916d6d8 121}
10b76d73
RK
122
123/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
124 the gensupport programs. */
125
126rtx
127gen_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}
3916d6d8 136\f
3262c1f5
RH
137/* Queue PATTERN on LIST_TAIL. */
138
139static void
821e35ba 140queue_pattern (pattern, list_tail, filename, lineno)
3262c1f5
RH
141 rtx pattern;
142 struct queue_elem ***list_tail;
821e35ba 143 const char *filename;
3262c1f5
RH
144 int lineno;
145{
146 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
147 e->data = pattern;
821e35ba 148 e->filename = filename;
3262c1f5
RH
149 e->lineno = lineno;
150 e->next = NULL;
151 **list_tail = e;
152 *list_tail = &e->next;
153}
154
c88c0d42
CP
155/* Recursively remove constraints from an rtx. */
156
157static void
158remove_constraints (part)
159 rtx part;
160{
b3694847
SS
161 int i, j;
162 const char *format_ptr;
c88c0d42
CP
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
04d8aa70 189/* Process an include file assuming that it lives in gcc/config/{target}/
80815706 190 if the include looks like (include "file"). */
174cc7d1
RH
191
192static void
04d8aa70
AM
193process_include (desc, lineno)
194 rtx desc;
195 int lineno;
196{
197 const char *filename = XSTR (desc, 0);
174cc7d1
RH
198 const char *old_filename;
199 int old_lineno;
200 char *pathname;
04d8aa70 201 FILE *input_file;
04d8aa70 202
174cc7d1
RH
203 /* If specified file name is absolute, skip the include stack. */
204 if (! IS_ABSOLUTE_PATHNAME (filename))
04d8aa70 205 {
174cc7d1
RH
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)
04d8aa70 210 {
174cc7d1
RH
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);
04d8aa70
AM
218 }
219 }
04d8aa70 220
174cc7d1
RH
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:
04d8aa70 234
174cc7d1
RH
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;
04d8aa70 242
174cc7d1
RH
243 /* Read the entire file. */
244 while (1)
245 {
246 rtx desc;
247 int c;
04d8aa70 248
174cc7d1
RH
249 c = read_skip_spaces (input_file);
250 if (c == EOF)
251 break;
04d8aa70 252
174cc7d1
RH
253 ungetc (c, input_file);
254 lineno = read_rtx_lineno;
255 desc = read_rtx (input_file);
256 process_rtx (desc, lineno);
04d8aa70
AM
257 }
258
821e35ba
RH
259 /* Do not free pathname. It is attached to the various rtx queue
260 elements. */
261
174cc7d1
RH
262 read_rtx_filename = old_filename;
263 read_rtx_lineno = old_lineno;
04d8aa70 264
174cc7d1 265 fclose (input_file);
04d8aa70
AM
266}
267
3262c1f5 268/* Process a top level rtx in some way, queueing as appropriate. */
c88c0d42
CP
269
270static void
3262c1f5
RH
271process_rtx (desc, lineno)
272 rtx desc;
273 int lineno;
274{
275 switch (GET_CODE (desc))
276 {
277 case DEFINE_INSN:
821e35ba 278 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
3262c1f5
RH
279 break;
280
281 case DEFINE_COND_EXEC:
821e35ba 282 queue_pattern (desc, &define_cond_exec_tail, read_rtx_filename, lineno);
3262c1f5
RH
283 break;
284
285 case DEFINE_ATTR:
821e35ba 286 queue_pattern (desc, &define_attr_tail, read_rtx_filename, lineno);
3262c1f5
RH
287 break;
288
04d8aa70 289 case INCLUDE:
174cc7d1 290 process_include (desc, lineno);
04d8aa70
AM
291 break;
292
3262c1f5
RH
293 case DEFINE_INSN_AND_SPLIT:
294 {
295 const char *split_cond;
20217ac1
KG
296 rtx split;
297 rtvec attr;
de4bfbcb 298 int i;
3262c1f5 299
dc297297 300 /* Create a split with values from the insn_and_split. */
3262c1f5 301 split = rtx_alloc (DEFINE_SPLIT);
de4bfbcb
RH
302
303 i = XVECLEN (desc, 1);
fbd40359 304 XVEC (split, 0) = rtvec_alloc (i);
de4bfbcb
RH
305 while (--i >= 0)
306 {
307 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
308 remove_constraints (XVECEXP (split, 0, i));
309 }
3262c1f5
RH
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] == '&')
1dcd444b 315 split_cond = concat (XSTR (desc, 2), split_cond, NULL);
3262c1f5
RH
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. */
ee138cf8 321 attr = XVEC (desc, 7);
3262c1f5 322 PUT_CODE (desc, DEFINE_INSN);
ee138cf8 323 XVEC (desc, 4) = attr;
3262c1f5
RH
324
325 /* Queue them. */
821e35ba
RH
326 queue_pattern (desc, &define_insn_tail, read_rtx_filename, lineno);
327 queue_pattern (split, &other_tail, read_rtx_filename, lineno);
3262c1f5
RH
328 break;
329 }
330
331 default:
821e35ba 332 queue_pattern (desc, &other_tail, read_rtx_filename, lineno);
3262c1f5 333 break;
c88c0d42
CP
334 }
335}
3916d6d8 336\f
3262c1f5
RH
337/* Return true if attribute PREDICABLE is true for ELEM, which holds
338 a DEFINE_INSN. */
339
340static int
341is_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,
1f978f5f 420 "unknown value `%s' for `predicable' attribute",
3262c1f5
RH
421 value);
422 errors = 1;
423 return 0;
424}
425
426/* Examine the attribute "predicable"; discover its boolean values
427 and its default. */
428
429static void
430identify_predicable_attribute ()
431{
432 struct queue_elem *elem;
d6edb99e 433 char *p_true, *p_false;
3262c1f5 434 const char *value;
3262c1f5
RH
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,
1f978f5f 442 "attribute `predicable' not defined");
3262c1f5
RH
443 errors = 1;
444 return;
445
446 found:
447 value = XSTR (elem->data, 1);
1dcd444b 448 p_false = xstrdup (value);
d6edb99e
ZW
449 p_true = strchr (p_false, ',');
450 if (p_true == NULL || strchr (++p_true, ',') != NULL)
3262c1f5
RH
451 {
452 message_with_line (elem->lineno,
1f978f5f 453 "attribute `predicable' is not a boolean");
3262c1f5
RH
454 errors = 1;
455 return;
456 }
d6edb99e 457 p_true[-1] = '\0';
3262c1f5 458
d6edb99e
ZW
459 predicable_true = p_true;
460 predicable_false = p_false;
3262c1f5
RH
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,
1f978f5f 470 "attribute `predicable' cannot be const");
3262c1f5
RH
471 errors = 1;
472 return;
473
474 default:
475 message_with_line (elem->lineno,
1f978f5f 476 "attribute `predicable' must have a constant default");
3262c1f5
RH
477 errors = 1;
478 return;
479 }
480
d6edb99e 481 if (strcmp (value, p_true) == 0)
3262c1f5 482 predicable_default = 1;
d6edb99e 483 else if (strcmp (value, p_false) == 0)
3262c1f5
RH
484 predicable_default = 0;
485 else
486 {
487 message_with_line (elem->lineno,
1f978f5f 488 "unknown value `%s' for `predicable' attribute",
3262c1f5
RH
489 value);
490 errors = 1;
491 }
492}
493
494/* Return the number of alternatives in constraint S. */
495
496static int
497n_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
512static void
513collect_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:
892ecf92
RH
525 i = n_alternatives (XSTR (pattern, 2));
526 *palt = (i > *palt ? i : *palt);
3262c1f5
RH
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
3b324340 561 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
3262c1f5
RH
562 break;
563
564 default:
565 abort ();
566 }
567 }
568}
569
570static rtx
571alter_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,
1f978f5f 589 "too many alternatives for operand %d",
3262c1f5
RH
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
661static const char *
662alter_test_for_insn (ce_elem, insn_elem)
663 struct queue_elem *ce_elem, *insn_elem;
664{
665 const char *ce_test, *insn_test;
3262c1f5
RH
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
1dcd444b 674 return concat ("(", ce_test, ") && (", insn_test, ")", NULL);
3262c1f5
RH
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
681static char *
682shift_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;
0df6c2c7 696 else if (ISALPHA (c))
3262c1f5
RH
697 {
698 *new++ = c;
699 c = *old++ + disp;
700 }
701 *new++ = c;
702 }
703 }
704
705 return new;
706}
707
708static const char *
709alter_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);
66621f9e 720 insn_out = XTMPL (insn_elem->data, 3);
3262c1f5
RH
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
770static void
771process_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);
66621f9e 822 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
3262c1f5
RH
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
821e35ba
RH
839 queue_pattern (insn, &other_tail, insn_elem->filename,
840 insn_elem->lineno);
3262c1f5
RH
841 }
842}
843
844/* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
845 patterns appropriately. */
846
847static void
848process_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}
04d8aa70
AM
859
860static char *
861save_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
875int
876init_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 */
4ec59de2
MH
904 if (first_dir_md_include == 0)
905 first_dir_md_include = dirtmp;
04d8aa70 906 else
4ec59de2
MH
907 last_dir_md_include->next = dirtmp;
908 last_dir_md_include = dirtmp; /* Tail follows the last one */
04d8aa70
AM
909 if (argv[i][1] == 'I' && argv[i][2] != 0)
910 dirtmp->fname = argv[i] + 2;
911 else if (i + 1 == argc)
1f978f5f 912 fatal ("directory name missing after -I option");
04d8aa70
AM
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:
1f978f5f 920 fatal ("invalid option `%s'", argv[i]);
04d8aa70
AM
921
922 }
923 }
924 }
925 return init_md_reader (in_fname);
926}
3262c1f5 927\f
c88c0d42
CP
928/* The entry point for initializing the reader. */
929
3262c1f5 930int
c88c0d42 931init_md_reader (filename)
3262c1f5 932 const char *filename;
c88c0d42 933{
3262c1f5
RH
934 FILE *input_file;
935 int c;
2199e5fa 936 size_t i;
04d8aa70
AM
937 char *lastsl;
938
4ec59de2
MH
939 lastsl = strrchr (filename, '/');
940 if (lastsl != NULL)
941 base_dir = save_string (filename, lastsl - filename + 1 );
3262c1f5 942
3916d6d8 943 read_rtx_filename = filename;
c88c0d42 944 input_file = fopen (filename, "r");
c88c0d42
CP
945 if (input_file == 0)
946 {
947 perror (filename);
948 return FATAL_EXIT_CODE;
949 }
950
2199e5fa
ZW
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
3916d6d8 959 obstack_init (rtl_obstack);
3262c1f5 960 errors = 0;
c88c0d42 961 sequence_num = 0;
c88c0d42 962
3262c1f5
RH
963 /* Read the entire file. */
964 while (1)
c88c0d42 965 {
3262c1f5
RH
966 rtx desc;
967 int lineno;
968
c88c0d42
CP
969 c = read_skip_spaces (input_file);
970 if (c == EOF)
04d8aa70 971 break;
c88c0d42
CP
972
973 ungetc (c, input_file);
3262c1f5 974 lineno = read_rtx_lineno;
c88c0d42 975 desc = read_rtx (input_file);
3262c1f5 976 process_rtx (desc, lineno);
c88c0d42 977 }
3262c1f5
RH
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
989rtx
990read_md_rtx (lineno, seqnr)
991 int *lineno;
992 int *seqnr;
993{
994 struct queue_elem **queue, *elem;
995 rtx desc;
996
2199e5fa
ZW
997 discard:
998
3262c1f5
RH
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;
821e35ba 1012 read_rtx_filename = elem->filename;
3262c1f5 1013 *lineno = elem->lineno;
c88c0d42 1014 *seqnr = sequence_num;
3262c1f5
RH
1015
1016 free (elem);
1017
2199e5fa
ZW
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. */
c88c0d42
CP
1024 switch (GET_CODE (desc))
1025 {
3262c1f5
RH
1026 case DEFINE_INSN:
1027 case DEFINE_EXPAND:
2199e5fa
ZW
1028 if (maybe_eval_c_test (XSTR (desc, 2)) != 0)
1029 sequence_num++;
1030 else if (insn_elision)
1031 goto discard;
1032 break;
1033
3262c1f5
RH
1034 case DEFINE_SPLIT:
1035 case DEFINE_PEEPHOLE:
1036 case DEFINE_PEEPHOLE2:
2199e5fa
ZW
1037 if (maybe_eval_c_test (XSTR (desc, 1)) != 0)
1038 sequence_num++;
1039 else if (insn_elision)
1040 goto discard;
3262c1f5
RH
1041 break;
1042
1043 default:
1044 break;
c88c0d42
CP
1045 }
1046
1047 return desc;
1048}
9a5834ae 1049
2199e5fa
ZW
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. */
1054hashval_t
1055hash_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. */
1081int
1082cmp_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. */
1096int
1097maybe_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
9a5834ae
ZW
1117/* Given a string, return the number of comma-separated elements in it.
1118 Return 0 for the null string. */
1119int
1120n_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
1141const char *
1142scan_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}