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