OSDN Git Service

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