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