]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gensupport.c
* cfglayout.c (fixup_fallthru_exit_predecesor): New static function.
[thirdparty/gcc.git] / gcc / gensupport.c
CommitLineData
96d905e5 1/* Support routines for the various generation passes.
9c811526 2 Copyright (C) 2000, 2001 Free Software Foundation, Inc.
c5ddd6b5 3
f12b58b3 4 This file is part of GCC.
c5ddd6b5 5
f12b58b3 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
c5ddd6b5 8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
f12b58b3 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.
c5ddd6b5 15
16 You should have received a copy of the GNU General Public License
f12b58b3 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. */
c5ddd6b5 20
21#include "hconfig.h"
22#include "system.h"
23#include "rtl.h"
96d905e5 24#include "obstack.h"
c5ddd6b5 25#include "errors.h"
26#include "gensupport.h"
27
96d905e5 28
420f5e4e 29/* In case some macros used by files we include need it, define this here. */
30int target_flags;
31
96d905e5 32static struct obstack obstack;
33struct obstack *rtl_obstack = &obstack;
34
35#define obstack_chunk_alloc xmalloc
36#define obstack_chunk_free free
37
c5ddd6b5 38static int sequence_num;
1df8f1eb 39static int errors;
40
41static int predicable_default;
42static const char *predicable_true;
43static const char *predicable_false;
44
45/* We initially queue all patterns, process the define_insn and
46 define_cond_exec patterns, then return them one at a time. */
c5ddd6b5 47
1df8f1eb 48struct queue_elem
49{
50 rtx data;
51 int lineno;
52 struct queue_elem *next;
c5ddd6b5 53};
54
1df8f1eb 55static struct queue_elem *define_attr_queue;
56static struct queue_elem **define_attr_tail = &define_attr_queue;
57static struct queue_elem *define_insn_queue;
58static struct queue_elem **define_insn_tail = &define_insn_queue;
59static struct queue_elem *define_cond_exec_queue;
60static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
61static struct queue_elem *other_queue;
62static struct queue_elem **other_tail = &other_queue;
c5ddd6b5 63
1df8f1eb 64static void queue_pattern PARAMS ((rtx, struct queue_elem ***, int));
2f5d30d9 65static void remove_constraints PARAMS ((rtx));
1df8f1eb 66static void process_rtx PARAMS ((rtx, int));
67
68static int is_predicable PARAMS ((struct queue_elem *));
69static void identify_predicable_attribute PARAMS ((void));
70static int n_alternatives PARAMS ((const char *));
71static void collect_insn_data PARAMS ((rtx, int *, int *));
72static rtx alter_predicate_for_insn PARAMS ((rtx, int, int, int));
73static const char *alter_test_for_insn PARAMS ((struct queue_elem *,
74 struct queue_elem *));
75static char *shift_output_template PARAMS ((char *, const char *, int));
76static const char *alter_output_for_insn PARAMS ((struct queue_elem *,
77 struct queue_elem *,
78 int, int));
79static void process_one_cond_exec PARAMS ((struct queue_elem *));
80static void process_define_cond_exec PARAMS ((void));
96d905e5 81\f
82void
83message_with_line VPARAMS ((int lineno, const char *msg, ...))
84{
0903457a 85 VA_OPEN (ap, msg);
86 VA_FIXEDARG (ap, int, lineno);
87 VA_FIXEDARG (ap, const char *, msg);
2f5d30d9 88
96d905e5 89 fprintf (stderr, "%s:%d: ", read_rtx_filename, lineno);
90 vfprintf (stderr, msg, ap);
91 fputc ('\n', stderr);
92
0903457a 93 VA_CLOSE (ap);
96d905e5 94}
5cc193e7 95
96/* Make a version of gen_rtx_CONST_INT so that GEN_INT can be used in
97 the gensupport programs. */
98
99rtx
100gen_rtx_CONST_INT (mode, arg)
101 enum machine_mode mode ATTRIBUTE_UNUSED;
102 HOST_WIDE_INT arg;
103{
104 rtx rt = rtx_alloc (CONST_INT);
105
106 XWINT (rt, 0) = arg;
107 return rt;
108}
96d905e5 109\f
1df8f1eb 110/* Queue PATTERN on LIST_TAIL. */
111
112static void
113queue_pattern (pattern, list_tail, lineno)
114 rtx pattern;
115 struct queue_elem ***list_tail;
116 int lineno;
117{
118 struct queue_elem *e = (struct queue_elem *) xmalloc (sizeof (*e));
119 e->data = pattern;
120 e->lineno = lineno;
121 e->next = NULL;
122 **list_tail = e;
123 *list_tail = &e->next;
124}
125
c5ddd6b5 126/* Recursively remove constraints from an rtx. */
127
128static void
129remove_constraints (part)
130 rtx part;
131{
19cb6b50 132 int i, j;
133 const char *format_ptr;
c5ddd6b5 134
135 if (part == 0)
136 return;
137
138 if (GET_CODE (part) == MATCH_OPERAND)
139 XSTR (part, 2) = "";
140 else if (GET_CODE (part) == MATCH_SCRATCH)
141 XSTR (part, 1) = "";
142
143 format_ptr = GET_RTX_FORMAT (GET_CODE (part));
144
145 for (i = 0; i < GET_RTX_LENGTH (GET_CODE (part)); i++)
146 switch (*format_ptr++)
147 {
148 case 'e':
149 case 'u':
150 remove_constraints (XEXP (part, i));
151 break;
152 case 'E':
153 if (XVEC (part, i) != NULL)
154 for (j = 0; j < XVECLEN (part, i); j++)
155 remove_constraints (XVECEXP (part, i, j));
156 break;
157 }
158}
159
1df8f1eb 160/* Process a top level rtx in some way, queueing as appropriate. */
c5ddd6b5 161
162static void
1df8f1eb 163process_rtx (desc, lineno)
164 rtx desc;
165 int lineno;
166{
167 switch (GET_CODE (desc))
168 {
169 case DEFINE_INSN:
170 queue_pattern (desc, &define_insn_tail, lineno);
171 break;
172
173 case DEFINE_COND_EXEC:
174 queue_pattern (desc, &define_cond_exec_tail, lineno);
175 break;
176
177 case DEFINE_ATTR:
178 queue_pattern (desc, &define_attr_tail, lineno);
179 break;
180
181 case DEFINE_INSN_AND_SPLIT:
182 {
183 const char *split_cond;
5dd13b1d 184 rtx split;
185 rtvec attr;
6ef7f25d 186 int i;
1df8f1eb 187
aa40f561 188 /* Create a split with values from the insn_and_split. */
1df8f1eb 189 split = rtx_alloc (DEFINE_SPLIT);
6ef7f25d 190
191 i = XVECLEN (desc, 1);
2508fdc3 192 XVEC (split, 0) = rtvec_alloc (i);
6ef7f25d 193 while (--i >= 0)
194 {
195 XVECEXP (split, 0, i) = copy_rtx (XVECEXP (desc, 1, i));
196 remove_constraints (XVECEXP (split, 0, i));
197 }
1df8f1eb 198
199 /* If the split condition starts with "&&", append it to the
200 insn condition to create the new split condition. */
201 split_cond = XSTR (desc, 4);
202 if (split_cond[0] == '&' && split_cond[1] == '&')
203 {
204 const char *insn_cond = XSTR (desc, 2);
205 size_t insn_cond_len = strlen (insn_cond);
206 size_t split_cond_len = strlen (split_cond);
207 char *combined;
208
209 combined = (char *) xmalloc (insn_cond_len + split_cond_len + 1);
210 memcpy (combined, insn_cond, insn_cond_len);
211 memcpy (combined + insn_cond_len, split_cond, split_cond_len + 1);
212
213 split_cond = combined;
214 }
215 XSTR (split, 1) = split_cond;
216 XVEC (split, 2) = XVEC (desc, 5);
217 XSTR (split, 3) = XSTR (desc, 6);
218
219 /* Fix up the DEFINE_INSN. */
5a9f7b1b 220 attr = XVEC (desc, 7);
1df8f1eb 221 PUT_CODE (desc, DEFINE_INSN);
5a9f7b1b 222 XVEC (desc, 4) = attr;
1df8f1eb 223
224 /* Queue them. */
225 queue_pattern (desc, &define_insn_tail, lineno);
226 queue_pattern (split, &other_tail, lineno);
227 break;
228 }
229
230 default:
231 queue_pattern (desc, &other_tail, lineno);
232 break;
c5ddd6b5 233 }
234}
96d905e5 235\f
1df8f1eb 236/* Return true if attribute PREDICABLE is true for ELEM, which holds
237 a DEFINE_INSN. */
238
239static int
240is_predicable (elem)
241 struct queue_elem *elem;
242{
243 rtvec vec = XVEC (elem->data, 4);
244 const char *value;
245 int i;
246
247 if (! vec)
248 return predicable_default;
249
250 for (i = GET_NUM_ELEM (vec) - 1; i >= 0; --i)
251 {
252 rtx sub = RTVEC_ELT (vec, i);
253 switch (GET_CODE (sub))
254 {
255 case SET_ATTR:
256 if (strcmp (XSTR (sub, 0), "predicable") == 0)
257 {
258 value = XSTR (sub, 1);
259 goto found;
260 }
261 break;
262
263 case SET_ATTR_ALTERNATIVE:
264 if (strcmp (XSTR (sub, 0), "predicable") == 0)
265 {
266 message_with_line (elem->lineno,
267 "multiple alternatives for `predicable'");
268 errors = 1;
269 return 0;
270 }
271 break;
272
273 case SET:
274 if (GET_CODE (SET_DEST (sub)) != ATTR
275 || strcmp (XSTR (SET_DEST (sub), 0), "predicable") != 0)
276 break;
277 sub = SET_SRC (sub);
278 if (GET_CODE (sub) == CONST_STRING)
279 {
280 value = XSTR (sub, 0);
281 goto found;
282 }
283
284 /* ??? It would be possible to handle this if we really tried.
285 It's not easy though, and I'm not going to bother until it
286 really proves necessary. */
287 message_with_line (elem->lineno,
288 "non-constant value for `predicable'");
289 errors = 1;
290 return 0;
291
292 default:
293 abort ();
294 }
295 }
296
297 return predicable_default;
298
299 found:
300 /* Verify that predicability does not vary on the alternative. */
301 /* ??? It should be possible to handle this by simply eliminating
302 the non-predicable alternatives from the insn. FRV would like
303 to do this. Delay this until we've got the basics solid. */
304 if (strchr (value, ',') != NULL)
305 {
306 message_with_line (elem->lineno,
307 "multiple alternatives for `predicable'");
308 errors = 1;
309 return 0;
310 }
311
312 /* Find out which value we're looking at. */
313 if (strcmp (value, predicable_true) == 0)
314 return 1;
315 if (strcmp (value, predicable_false) == 0)
316 return 0;
317
318 message_with_line (elem->lineno,
319 "Unknown value `%s' for `predicable' attribute",
320 value);
321 errors = 1;
322 return 0;
323}
324
325/* Examine the attribute "predicable"; discover its boolean values
326 and its default. */
327
328static void
329identify_predicable_attribute ()
330{
331 struct queue_elem *elem;
9c811526 332 char *p_true, *p_false;
1df8f1eb 333 const char *value;
334 size_t len;
335
336 /* Look for the DEFINE_ATTR for `predicable', which must exist. */
337 for (elem = define_attr_queue; elem ; elem = elem->next)
338 if (strcmp (XSTR (elem->data, 0), "predicable") == 0)
339 goto found;
340
341 message_with_line (define_cond_exec_queue->lineno,
342 "Attribute `predicable' not defined");
343 errors = 1;
344 return;
345
346 found:
347 value = XSTR (elem->data, 1);
348 len = strlen (value);
9c811526 349 p_false = (char *) xmalloc (len + 1);
350 memcpy (p_false, value, len + 1);
1df8f1eb 351
9c811526 352 p_true = strchr (p_false, ',');
353 if (p_true == NULL || strchr (++p_true, ',') != NULL)
1df8f1eb 354 {
355 message_with_line (elem->lineno,
356 "Attribute `predicable' is not a boolean");
357 errors = 1;
358 return;
359 }
9c811526 360 p_true[-1] = '\0';
1df8f1eb 361
9c811526 362 predicable_true = p_true;
363 predicable_false = p_false;
1df8f1eb 364
365 switch (GET_CODE (XEXP (elem->data, 2)))
366 {
367 case CONST_STRING:
368 value = XSTR (XEXP (elem->data, 2), 0);
369 break;
370
371 case CONST:
372 message_with_line (elem->lineno,
373 "Attribute `predicable' cannot be const");
374 errors = 1;
375 return;
376
377 default:
378 message_with_line (elem->lineno,
379 "Attribute `predicable' must have a constant default");
380 errors = 1;
381 return;
382 }
383
9c811526 384 if (strcmp (value, p_true) == 0)
1df8f1eb 385 predicable_default = 1;
9c811526 386 else if (strcmp (value, p_false) == 0)
1df8f1eb 387 predicable_default = 0;
388 else
389 {
390 message_with_line (elem->lineno,
391 "Unknown value `%s' for `predicable' attribute",
392 value);
393 errors = 1;
394 }
395}
396
397/* Return the number of alternatives in constraint S. */
398
399static int
400n_alternatives (s)
401 const char *s;
402{
403 int n = 1;
404
405 if (s)
406 while (*s)
407 n += (*s++ == ',');
408
409 return n;
410}
411
412/* Determine how many alternatives there are in INSN, and how many
413 operands. */
414
415static void
416collect_insn_data (pattern, palt, pmax)
417 rtx pattern;
418 int *palt, *pmax;
419{
420 const char *fmt;
421 enum rtx_code code;
422 int i, j, len;
423
424 code = GET_CODE (pattern);
425 switch (code)
426 {
427 case MATCH_OPERAND:
f316cb53 428 i = n_alternatives (XSTR (pattern, 2));
429 *palt = (i > *palt ? i : *palt);
1df8f1eb 430 /* FALLTHRU */
431
432 case MATCH_OPERATOR:
433 case MATCH_SCRATCH:
434 case MATCH_PARALLEL:
435 case MATCH_INSN:
436 i = XINT (pattern, 0);
437 if (i > *pmax)
438 *pmax = i;
439 break;
440
441 default:
442 break;
443 }
444
445 fmt = GET_RTX_FORMAT (code);
446 len = GET_RTX_LENGTH (code);
447 for (i = 0; i < len; i++)
448 {
449 switch (fmt[i])
450 {
451 case 'e': case 'u':
452 collect_insn_data (XEXP (pattern, i), palt, pmax);
453 break;
454
455 case 'V':
456 if (XVEC (pattern, i) == NULL)
457 break;
458 /* FALLTHRU */
459 case 'E':
460 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
461 collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
462 break;
463
9abd2cd7 464 case 'i': case 'w': case '0': case 's': case 'S': case 'T':
1df8f1eb 465 break;
466
467 default:
468 abort ();
469 }
470 }
471}
472
473static rtx
474alter_predicate_for_insn (pattern, alt, max_op, lineno)
475 rtx pattern;
476 int alt, max_op, lineno;
477{
478 const char *fmt;
479 enum rtx_code code;
480 int i, j, len;
481
482 code = GET_CODE (pattern);
483 switch (code)
484 {
485 case MATCH_OPERAND:
486 {
487 const char *c = XSTR (pattern, 2);
488
489 if (n_alternatives (c) != 1)
490 {
491 message_with_line (lineno,
492 "Too many alternatives for operand %d",
493 XINT (pattern, 0));
494 errors = 1;
495 return NULL;
496 }
497
498 /* Replicate C as needed to fill out ALT alternatives. */
499 if (c && *c && alt > 1)
500 {
501 size_t c_len = strlen (c);
502 size_t len = alt * (c_len + 1);
503 char *new_c = (char *) xmalloc (len);
504
505 memcpy (new_c, c, c_len);
506 for (i = 1; i < alt; ++i)
507 {
508 new_c[i * (c_len + 1) - 1] = ',';
509 memcpy (&new_c[i * (c_len + 1)], c, c_len);
510 }
511 new_c[len - 1] = '\0';
512 XSTR (pattern, 2) = new_c;
513 }
514 }
515 /* FALLTHRU */
516
517 case MATCH_OPERATOR:
518 case MATCH_SCRATCH:
519 case MATCH_PARALLEL:
520 case MATCH_INSN:
521 XINT (pattern, 0) += max_op;
522 break;
523
524 default:
525 break;
526 }
527
528 fmt = GET_RTX_FORMAT (code);
529 len = GET_RTX_LENGTH (code);
530 for (i = 0; i < len; i++)
531 {
532 rtx r;
533
534 switch (fmt[i])
535 {
536 case 'e': case 'u':
537 r = alter_predicate_for_insn (XEXP (pattern, i), alt,
538 max_op, lineno);
539 if (r == NULL)
540 return r;
541 break;
542
543 case 'E':
544 for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
545 {
546 r = alter_predicate_for_insn (XVECEXP (pattern, i, j),
547 alt, max_op, lineno);
548 if (r == NULL)
549 return r;
550 }
551 break;
552
553 case 'i': case 'w': case '0': case 's':
554 break;
555
556 default:
557 abort ();
558 }
559 }
560
561 return pattern;
562}
563
564static const char *
565alter_test_for_insn (ce_elem, insn_elem)
566 struct queue_elem *ce_elem, *insn_elem;
567{
568 const char *ce_test, *insn_test;
569 char *new_test;
570 size_t len, ce_len, insn_len;
571
572 ce_test = XSTR (ce_elem->data, 1);
573 insn_test = XSTR (insn_elem->data, 2);
574 if (!ce_test || *ce_test == '\0')
575 return insn_test;
576 if (!insn_test || *insn_test == '\0')
577 return ce_test;
578
579 ce_len = strlen (ce_test);
580 insn_len = strlen (insn_test);
581 len = 1 + ce_len + 1 + 4 + 1 + insn_len + 1 + 1;
582 new_test = (char *) xmalloc (len);
583
584 sprintf (new_test, "(%s) && (%s)", ce_test, insn_test);
585
586 return new_test;
587}
588
589/* Adjust all of the operand numbers in OLD to match the shift they'll
590 get from an operand displacement of DISP. Return a pointer after the
591 adjusted string. */
592
593static char *
594shift_output_template (new, old, disp)
595 char *new;
596 const char *old;
597 int disp;
598{
599 while (*old)
600 {
601 char c = *old++;
602 *new++ = c;
603 if (c == '%')
604 {
605 c = *old++;
606 if (ISDIGIT ((unsigned char) c))
607 c += disp;
66a33570 608 else if (ISALPHA (c))
1df8f1eb 609 {
610 *new++ = c;
611 c = *old++ + disp;
612 }
613 *new++ = c;
614 }
615 }
616
617 return new;
618}
619
620static const char *
621alter_output_for_insn (ce_elem, insn_elem, alt, max_op)
622 struct queue_elem *ce_elem, *insn_elem;
623 int alt, max_op;
624{
625 const char *ce_out, *insn_out;
626 char *new, *p;
627 size_t len, ce_len, insn_len;
628
629 /* ??? Could coordinate with genoutput to not duplicate code here. */
630
631 ce_out = XSTR (ce_elem->data, 2);
4a9e3377 632 insn_out = XTMPL (insn_elem->data, 3);
1df8f1eb 633 if (!ce_out || *ce_out == '\0')
634 return insn_out;
635
636 ce_len = strlen (ce_out);
637 insn_len = strlen (insn_out);
638
639 if (*insn_out == '*')
640 /* You must take care of the predicate yourself. */
641 return insn_out;
642
643 if (*insn_out == '@')
644 {
645 len = (ce_len + 1) * alt + insn_len + 1;
646 p = new = xmalloc (len);
647
648 do
649 {
650 do
651 *p++ = *insn_out++;
652 while (ISSPACE ((unsigned char) *insn_out));
653
654 if (*insn_out != '#')
655 {
656 p = shift_output_template (p, ce_out, max_op);
657 *p++ = ' ';
658 }
659
660 do
661 *p++ = *insn_out++;
662 while (*insn_out && *insn_out != '\n');
663 }
664 while (*insn_out);
665 *p = '\0';
666 }
667 else
668 {
669 len = ce_len + 1 + insn_len + 1;
670 new = xmalloc (len);
671
672 p = shift_output_template (new, ce_out, max_op);
673 *p++ = ' ';
674 memcpy (p, insn_out, insn_len + 1);
675 }
676
677 return new;
678}
679
680/* Replicate insns as appropriate for the given DEFINE_COND_EXEC. */
681
682static void
683process_one_cond_exec (ce_elem)
684 struct queue_elem *ce_elem;
685{
686 struct queue_elem *insn_elem;
687 for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
688 {
689 int alternatives, max_operand;
690 rtx pred, insn, pattern;
691
692 if (! is_predicable (insn_elem))
693 continue;
694
695 alternatives = 1;
696 max_operand = -1;
697 collect_insn_data (insn_elem->data, &alternatives, &max_operand);
698 max_operand += 1;
699
700 if (XVECLEN (ce_elem->data, 0) != 1)
701 {
702 message_with_line (ce_elem->lineno,
703 "too many patterns in predicate");
704 errors = 1;
705 return;
706 }
707
708 pred = copy_rtx (XVECEXP (ce_elem->data, 0, 0));
709 pred = alter_predicate_for_insn (pred, alternatives, max_operand,
710 ce_elem->lineno);
711 if (pred == NULL)
712 return;
713
714 /* Construct a new pattern for the new insn. */
715 insn = copy_rtx (insn_elem->data);
716 XSTR (insn, 0) = "";
717 pattern = rtx_alloc (COND_EXEC);
718 XEXP (pattern, 0) = pred;
719 if (XVECLEN (insn, 1) == 1)
720 {
721 XEXP (pattern, 1) = XVECEXP (insn, 1, 0);
722 XVECEXP (insn, 1, 0) = pattern;
723 PUT_NUM_ELEM (XVEC (insn, 1), 1);
724 }
725 else
726 {
727 XEXP (pattern, 1) = rtx_alloc (PARALLEL);
728 XVEC (XEXP (pattern, 1), 0) = XVEC (insn, 1);
729 XVEC (insn, 1) = rtvec_alloc (1);
730 XVECEXP (insn, 1, 0) = pattern;
731 }
732
733 XSTR (insn, 2) = alter_test_for_insn (ce_elem, insn_elem);
4a9e3377 734 XTMPL (insn, 3) = alter_output_for_insn (ce_elem, insn_elem,
1df8f1eb 735 alternatives, max_operand);
736
737 /* ??? Set `predicable' to false. Not crucial since it's really
738 only used here, and we won't reprocess this new pattern. */
739
740 /* Put the new pattern on the `other' list so that it
741 (a) is not reprocessed by other define_cond_exec patterns
742 (b) appears after all normal define_insn patterns.
743
744 ??? B is debatable. If one has normal insns that match
745 cond_exec patterns, they will be preferred over these
746 generated patterns. Whether this matters in practice, or if
747 it's a good thing, or whether we should thread these new
748 patterns into the define_insn chain just after their generator
749 is something we'll have to experiment with. */
750
751 queue_pattern (insn, &other_tail, insn_elem->lineno);
752 }
753}
754
755/* If we have any DEFINE_COND_EXEC patterns, expand the DEFINE_INSN
756 patterns appropriately. */
757
758static void
759process_define_cond_exec ()
760{
761 struct queue_elem *elem;
762
763 identify_predicable_attribute ();
764 if (errors)
765 return;
766
767 for (elem = define_cond_exec_queue; elem ; elem = elem->next)
768 process_one_cond_exec (elem);
769}
770\f
c5ddd6b5 771/* The entry point for initializing the reader. */
772
1df8f1eb 773int
c5ddd6b5 774init_md_reader (filename)
1df8f1eb 775 const char *filename;
c5ddd6b5 776{
1df8f1eb 777 FILE *input_file;
778 int c;
779
96d905e5 780 read_rtx_filename = filename;
c5ddd6b5 781 input_file = fopen (filename, "r");
c5ddd6b5 782 if (input_file == 0)
783 {
784 perror (filename);
785 return FATAL_EXIT_CODE;
786 }
787
96d905e5 788 obstack_init (rtl_obstack);
1df8f1eb 789 errors = 0;
c5ddd6b5 790 sequence_num = 0;
c5ddd6b5 791
1df8f1eb 792 /* Read the entire file. */
793 while (1)
c5ddd6b5 794 {
1df8f1eb 795 rtx desc;
796 int lineno;
797
c5ddd6b5 798 c = read_skip_spaces (input_file);
799 if (c == EOF)
1df8f1eb 800 break;
c5ddd6b5 801
802 ungetc (c, input_file);
1df8f1eb 803 lineno = read_rtx_lineno;
c5ddd6b5 804 desc = read_rtx (input_file);
1df8f1eb 805 process_rtx (desc, lineno);
c5ddd6b5 806 }
1df8f1eb 807 fclose (input_file);
808
809 /* Process define_cond_exec patterns. */
810 if (define_cond_exec_queue != NULL)
811 process_define_cond_exec ();
812
813 return errors ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE;
814}
815
816/* The entry point for reading a single rtx from an md file. */
817
818rtx
819read_md_rtx (lineno, seqnr)
820 int *lineno;
821 int *seqnr;
822{
823 struct queue_elem **queue, *elem;
824 rtx desc;
825
826 /* Read all patterns from a given queue before moving on to the next. */
827 if (define_attr_queue != NULL)
828 queue = &define_attr_queue;
829 else if (define_insn_queue != NULL)
830 queue = &define_insn_queue;
831 else if (other_queue != NULL)
832 queue = &other_queue;
833 else
834 return NULL_RTX;
835
836 elem = *queue;
837 *queue = elem->next;
838 desc = elem->data;
839 *lineno = elem->lineno;
c5ddd6b5 840 *seqnr = sequence_num;
1df8f1eb 841
842 free (elem);
843
c5ddd6b5 844 switch (GET_CODE (desc))
845 {
1df8f1eb 846 case DEFINE_INSN:
847 case DEFINE_EXPAND:
848 case DEFINE_SPLIT:
849 case DEFINE_PEEPHOLE:
850 case DEFINE_PEEPHOLE2:
851 sequence_num++;
852 break;
853
854 default:
855 break;
c5ddd6b5 856 }
857
858 return desc;
859}
f950cdc7 860
861/* Until we can use the versions in libiberty. */
862char *
863xstrdup (input)
864 const char *input;
865{
19cb6b50 866 size_t len = strlen (input) + 1;
867 char *output = xmalloc (len);
f950cdc7 868 memcpy (output, input, len);
869 return output;
870}
871
4333d921 872PTR
873xcalloc (nelem, elsize)
874 size_t nelem, elsize;
875{
876 PTR newmem;
877
878 if (nelem == 0 || elsize == 0)
879 nelem = elsize = 1;
880
d0dad2ed 881 newmem = really_call_calloc (nelem, elsize);
4333d921 882 if (!newmem)
883 fatal ("virtual memory exhausted");
884 return (newmem);
885}
886
f950cdc7 887PTR
888xrealloc (old, size)
889 PTR old;
890 size_t size;
891{
19cb6b50 892 PTR ptr;
f950cdc7 893 if (old)
d0dad2ed 894 ptr = (PTR) really_call_realloc (old, size);
f950cdc7 895 else
d0dad2ed 896 ptr = (PTR) really_call_malloc (size);
f950cdc7 897 if (!ptr)
898 fatal ("virtual memory exhausted");
899 return ptr;
900}
901
902PTR
903xmalloc (size)
904 size_t size;
905{
19cb6b50 906 PTR val = (PTR) really_call_malloc (size);
f950cdc7 907
908 if (val == 0)
909 fatal ("virtual memory exhausted");
910 return val;
911}