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