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