Warning fixes:
[platform/upstream/gcc.git] / gcc / genextract.c
1 /* Generate code from machine description to extract operands from insn as rtl.
2    Copyright (C) 1987, 91, 92, 93, 97, 1998 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
22 #include "hconfig.h"
23 #ifdef __STDC__
24 #include <stdarg.h>
25 #else
26 #include <varargs.h>
27 #endif
28 #include "system.h"
29 #include "rtl.h"
30 #include "obstack.h"
31 #include "insn-config.h"
32
33 static struct obstack obstack;
34 struct obstack *rtl_obstack = &obstack;
35
36 #define obstack_chunk_alloc xmalloc
37 #define obstack_chunk_free free
38
39 /* Names for patterns.  Need to allow linking with print-rtl.  */
40 char **insn_name_ptr;
41
42 /* This structure contains all the information needed to describe one
43    set of extractions methods.  Each method may be used by more than 
44    one pattern if the operands are in the same place.
45
46    The string for each operand describes that path to the operand and
47    contains `0' through `9' when going into an expression and `a' through
48    `z' when going into a vector.  We assume here that only the first operand
49    of an rtl expression is a vector.  genrecog.c makes the same assumption
50    (and uses the same representation) and it is currently true.  */
51
52 struct extraction
53 {
54   int op_count;
55   char *oplocs[MAX_RECOG_OPERANDS];
56   int dup_count;
57   char *duplocs[MAX_DUP_OPERANDS];
58   int dupnums[MAX_DUP_OPERANDS];
59   struct code_ptr *insns;
60   struct extraction *next;
61 };
62
63 /* Holds a single insn code that use an extraction method.  */
64
65 struct code_ptr
66 {
67   int insn_code;
68   struct code_ptr *next;
69 };
70
71 static struct extraction *extractions;
72
73 /* Number instruction patterns handled, starting at 0 for first one.  */
74
75 static int insn_code_number;
76
77 /* Records the large operand number in this insn.  */
78
79 static int op_count;
80
81 /* Records the location of any operands using the string format described
82    above.  */
83
84 static char *oplocs[MAX_RECOG_OPERANDS];
85
86 /* Number the occurrences of MATCH_DUP in each instruction,
87    starting at 0 for the first occurrence.  */
88
89 static int dup_count;
90
91 /* Records the location of any MATCH_DUP operands.  */
92
93 static char *duplocs[MAX_DUP_OPERANDS];
94
95 /* Record the operand number of any MATCH_DUPs.  */
96
97 static int dupnums[MAX_DUP_OPERANDS];
98
99 /* Record the list of insn_codes for peepholes.  */
100
101 static struct code_ptr *peepholes;
102
103 static void gen_insn PROTO ((rtx));
104 static void walk_rtx PROTO ((rtx, char *));
105 static void print_path PROTO ((char *));
106 char *xmalloc PROTO ((unsigned));
107 char *xrealloc PROTO ((char *, unsigned));
108 static void fatal PVPROTO ((char *, ...)) ATTRIBUTE_PRINTF_1;
109 static char *copystr PROTO ((char *));
110 static void mybzero ();
111 void fancy_abort PROTO ((void));
112 \f
113 static void
114 gen_insn (insn)
115      rtx insn;
116 {
117   register int i;
118   register struct extraction *p;
119   register struct code_ptr *link;
120
121   op_count = 0;
122   dup_count = 0;
123
124   /* No operands seen so far in this pattern.  */
125   mybzero (oplocs, sizeof oplocs);
126
127   /* Walk the insn's pattern, remembering at all times the path
128      down to the walking point.  */
129
130   if (XVECLEN (insn, 1) == 1)
131     walk_rtx (XVECEXP (insn, 1, 0), "");
132   else
133     for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
134       {
135         char *path = (char *) alloca (2);
136
137         path[0] = 'a' + i;
138         path[1] = 0;
139
140         walk_rtx (XVECEXP (insn, 1, i), path);
141       }
142
143   link = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
144   link->insn_code = insn_code_number;
145
146   /* See if we find something that already had this extraction method.  */
147
148   for (p = extractions; p; p = p->next)
149     {
150       if (p->op_count != op_count || p->dup_count != dup_count)
151         continue;
152
153       for (i = 0; i < op_count; i++)
154         if (p->oplocs[i] != oplocs[i]
155             && ! (p->oplocs[i] != 0 && oplocs[i] != 0
156                   && ! strcmp (p->oplocs[i], oplocs[i])))
157           break;
158
159       if (i != op_count)
160         continue;
161
162       for (i = 0; i < dup_count; i++)
163         if (p->dupnums[i] != dupnums[i]
164             || strcmp (p->duplocs[i], duplocs[i]))
165           break;
166
167       if (i != dup_count)
168         continue;
169
170       /* This extraction is the same as ours.  Just link us in.  */
171       link->next = p->insns;
172       p->insns = link;
173       return;
174     }
175
176   /* Otherwise, make a new extraction method.  */
177
178   p = (struct extraction *) xmalloc (sizeof (struct extraction));
179   p->op_count = op_count;
180   p->dup_count = dup_count;
181   p->next = extractions;
182   extractions = p;
183   p->insns = link;
184   link->next = 0;
185
186   for (i = 0; i < op_count; i++)
187     p->oplocs[i] = oplocs[i];
188
189   for (i = 0; i < dup_count; i++)
190     p->dupnums[i] = dupnums[i], p->duplocs[i] = duplocs[i];
191 }
192 \f
193 static void
194 walk_rtx (x, path)
195      rtx x;
196      char *path;
197 {
198   register RTX_CODE code;
199   register int i;
200   register int len;
201   register char *fmt;
202   int depth = strlen (path);
203   char *newpath;
204
205   if (x == 0)
206     return;
207
208   code = GET_CODE (x);
209
210   switch (code)
211     {
212     case PC:
213     case CC0:
214     case CONST_INT:
215     case SYMBOL_REF:
216       return;
217
218     case MATCH_OPERAND:
219     case MATCH_SCRATCH:
220       oplocs[XINT (x, 0)] = copystr (path);
221       op_count = MAX (op_count, XINT (x, 0) + 1);
222       break;
223
224     case MATCH_DUP:
225     case MATCH_PAR_DUP:
226       duplocs[dup_count] = copystr (path);
227       dupnums[dup_count] = XINT (x, 0);
228       dup_count++;
229       break;
230
231     case MATCH_OP_DUP:
232       duplocs[dup_count] = copystr (path);
233       dupnums[dup_count] = XINT (x, 0);
234       dup_count++;
235       
236       newpath = (char *) alloca (depth + 2);
237       strcpy (newpath, path);
238       newpath[depth + 1] = 0;
239       
240       for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
241         {
242           newpath[depth] = '0' + i;
243           walk_rtx (XVECEXP (x, 1, i), newpath);
244         }
245       return;
246       
247     case MATCH_OPERATOR:
248       oplocs[XINT (x, 0)] = copystr (path);
249       op_count = MAX (op_count, XINT (x, 0) + 1);
250
251       newpath = (char *) alloca (depth + 2);
252       strcpy (newpath, path);
253       newpath[depth + 1] = 0;
254
255       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
256         {
257           newpath[depth] = '0' + i;
258           walk_rtx (XVECEXP (x, 2, i), newpath);
259         }
260       return;
261
262     case MATCH_PARALLEL:
263       oplocs[XINT (x, 0)] = copystr (path);
264       op_count = MAX (op_count, XINT (x, 0) + 1);
265
266       newpath = (char *) alloca (depth + 2);
267       strcpy (newpath, path);
268       newpath[depth + 1] = 0;
269
270       for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
271         {
272           newpath[depth] = 'a' + i;
273           walk_rtx (XVECEXP (x, 2, i), newpath);
274         }
275       return;
276
277     case ADDRESS:
278       walk_rtx (XEXP (x, 0), path);
279       return;
280
281     default:
282       break;
283     }
284
285   newpath = (char *) alloca (depth + 2);
286   strcpy (newpath, path);
287   newpath[depth + 1] = 0;
288
289   fmt = GET_RTX_FORMAT (code);
290   len = GET_RTX_LENGTH (code);
291   for (i = 0; i < len; i++)
292     {
293       if (fmt[i] == 'e' || fmt[i] == 'u')
294         {
295           newpath[depth] = '0' + i;
296           walk_rtx (XEXP (x, i), newpath);
297         }
298       else if (fmt[i] == 'E')
299         {
300           int j;
301           for (j = XVECLEN (x, i) - 1; j >= 0; j--)
302             {
303               newpath[depth] = 'a' + j;
304               walk_rtx (XVECEXP (x, i, j), newpath);
305             }
306         }
307     }
308 }
309
310 /* Given a PATH, representing a path down the instruction's
311    pattern from the root to a certain point, output code to
312    evaluate to the rtx at that point.  */
313
314 static void
315 print_path (path)
316      char *path;
317 {
318   register int len = strlen (path);
319   register int i;
320
321   /* We first write out the operations (XEXP or XVECEXP) in reverse
322      order, then write "insn", then the indices in forward order.  */
323
324   for (i = len - 1; i >=0 ; i--)
325     {
326       if (path[i] >= 'a' && path[i] <= 'z')
327         printf ("XVECEXP (");
328       else if (path[i] >= '0' && path[i] <= '9')
329         printf ("XEXP (");
330       else
331         abort ();
332     }
333   
334   printf ("pat");
335
336   for (i = 0; i < len; i++)
337     {
338       if (path[i] >= 'a' && path[i] <= 'z')
339         printf (", 0, %d)", path[i] - 'a');
340       else if (path[i] >= '0' && path[i] <= '9')
341         printf (", %d)", path[i] - '0');
342       else
343         abort ();
344     }
345 }
346 \f
347 char *
348 xmalloc (size)
349      unsigned size;
350 {
351   register char *val = (char *) malloc (size);
352
353   if (val == 0)
354     fatal ("virtual memory exhausted");
355   return val;
356 }
357
358 char *
359 xrealloc (ptr, size)
360      char *ptr;
361      unsigned size;
362 {
363   char *result = (char *) realloc (ptr, size);
364   if (!result)
365     fatal ("virtual memory exhausted");
366   return result;
367 }
368
369 static void
370 fatal VPROTO ((char *format, ...))
371 {
372 #ifndef __STDC__
373   char *format;
374 #endif
375   va_list ap;
376
377   VA_START (ap, format);
378
379 #ifndef __STDC__
380   format = va_arg (ap, char *);
381 #endif
382
383   fprintf (stderr, "genextract: ");
384   vfprintf (stderr, format, ap);
385   va_end (ap);
386   fprintf (stderr, "\n");
387   exit (FATAL_EXIT_CODE);
388 }
389
390 /* More 'friendly' abort that prints the line and file.
391    config.h can #define abort fancy_abort if you like that sort of thing.  */
392
393 void
394 fancy_abort ()
395 {
396   fatal ("Internal gcc abort.");
397 }
398
399 static char *
400 copystr (s1)
401      char *s1;
402 {
403   register char *tem;
404
405   if (s1 == 0)
406     return 0;
407
408   tem = (char *) xmalloc (strlen (s1) + 1);
409   strcpy (tem, s1);
410
411   return tem;
412 }
413
414 static void
415 mybzero (b, length)
416      register char *b;
417      register unsigned length;
418 {
419   while (length-- > 0)
420     *b++ = 0;
421 }
422 \f
423 int
424 main (argc, argv)
425      int argc;
426      char **argv;
427 {
428   rtx desc;
429   FILE *infile;
430   register int c, i;
431   struct extraction *p;
432   struct code_ptr *link;
433
434   obstack_init (rtl_obstack);
435
436   if (argc <= 1)
437     fatal ("No input file name.");
438
439   infile = fopen (argv[1], "r");
440   if (infile == 0)
441     {
442       perror (argv[1]);
443       exit (FATAL_EXIT_CODE);
444     }
445
446   init_rtl ();
447
448   /* Assign sequential codes to all entries in the machine description
449      in parallel with the tables in insn-output.c.  */
450
451   insn_code_number = 0;
452
453   printf ("/* Generated automatically by the program `genextract'\n\
454 from the machine description file `md'.  */\n\n");
455
456   printf ("#include \"config.h\"\n");
457   printf ("#include \"system.h\"\n");
458   printf ("#include \"rtl.h\"\n\n");
459
460   /* This variable exists only so it can be the "location"
461      of any missing operand whose numbers are skipped by a given pattern.  */
462   printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
463
464   printf ("extern rtx recog_operand[];\n");
465   printf ("extern rtx *recog_operand_loc[];\n");
466   printf ("extern rtx *recog_dup_loc[];\n");
467   printf ("extern char recog_dup_num[];\n");
468
469   printf ("void\ninsn_extract (insn)\n");
470   printf ("     rtx insn;\n");
471   printf ("{\n");
472   printf ("  register rtx *ro = recog_operand;\n");
473   printf ("  register rtx **ro_loc = recog_operand_loc;\n");
474   printf ("  rtx pat = PATTERN (insn);\n");
475   printf ("  int i;\n\n");
476   printf ("  switch (INSN_CODE (insn))\n");
477   printf ("    {\n");
478   printf ("    case -1:\n");
479   printf ("      fatal_insn_not_found (insn);\n\n");
480
481   /* Read the machine description.  */
482
483   while (1)
484     {
485       c = read_skip_spaces (infile);
486       if (c == EOF)
487         break;
488       ungetc (c, infile);
489
490       desc = read_rtx (infile);
491       if (GET_CODE (desc) == DEFINE_INSN)
492         {
493           gen_insn (desc);
494           ++insn_code_number;
495         }
496
497       else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
498         {
499           struct code_ptr *link
500             = (struct code_ptr *) xmalloc (sizeof (struct code_ptr));
501
502           link->insn_code = insn_code_number;
503           link->next = peepholes;
504           peepholes = link;
505           ++insn_code_number;
506         }
507
508       else if (GET_CODE (desc) == DEFINE_EXPAND
509                || GET_CODE (desc) == DEFINE_SPLIT)
510         ++insn_code_number;
511     }
512
513   /* Write out code to handle peepholes and the insn_codes that it should
514      be called for.  */
515   if (peepholes)
516     {
517       for (link = peepholes; link; link = link->next)
518         printf ("    case %d:\n", link->insn_code);
519
520       /* The vector in the insn says how many operands it has.
521          And all it contains are operands.  In fact, the vector was
522          created just for the sake of this function.  */
523       printf ("      for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
524       printf ("          ro[i] = XVECEXP (pat, 0, i);\n");
525       printf ("      break;\n\n");
526     }
527
528   /* Write out all the ways to extract insn operands.  */
529   for (p = extractions; p; p = p->next)
530     {
531       for (link = p->insns; link; link = link->next)
532         printf ("    case %d:\n", link->insn_code);
533
534       for (i = 0; i < p->op_count; i++)
535         {
536           if (p->oplocs[i] == 0)
537             {
538               printf ("      ro[%d] = const0_rtx;\n", i);
539               printf ("      ro_loc[%d] = &junk;\n", i);
540             }
541           else
542             {
543               printf ("      ro[%d] = *(ro_loc[%d] = &", i, i);
544               print_path (p->oplocs[i]);
545               printf (");\n");
546             }
547         }
548
549       for (i = 0; i < p->dup_count; i++)
550         {
551           printf ("      recog_dup_loc[%d] = &", i);
552           print_path (p->duplocs[i]);
553           printf (";\n");
554           printf ("      recog_dup_num[%d] = %d;\n", i, p->dupnums[i]);
555         }
556
557       printf ("      break;\n\n");
558     }
559
560   /* This should never be reached.  Note that we would also reach this abort
561    if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
562    DEFINE_SPLIT, but that is correct.  */
563   printf ("    default:\n      abort ();\n");
564
565   printf ("    }\n}\n");
566
567   fflush (stdout);
568   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
569   /* NOTREACHED */
570   return 0;
571 }