]>
gcc.gnu.org Git - gcc.git/blob - gcc/genextract.c
1 /* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987, 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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)
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.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
25 #include "insn-config.h"
27 static struct obstack obstack
;
28 struct obstack
*rtl_obstack
= &obstack
;
30 #define obstack_chunk_alloc xmalloc
31 #define obstack_chunk_free free
34 extern rtx
read_rtx ();
36 /* This structure contains all the information needed to describe one
37 set of extractions methods. Each method may be used by more than
38 one pattern if the operands are in the same place.
40 The string for each operand describes that path to the operand and
41 contains `0' through `9' when going into an expression and `a' through
42 `z' when going into a vector. We assume here that only the first operand
43 of an rtl expression is a vector. genrecog.c makes the same assumption
44 (and uses the same representation) and it is currently true. */
49 char *oplocs
[MAX_RECOG_OPERANDS
];
51 char *duplocs
[MAX_DUP_OPERANDS
];
52 int dupnums
[MAX_DUP_OPERANDS
];
53 struct code_ptr
*insns
;
54 struct extraction
*next
;
57 /* Holds a single insn code that use an extraction method. */
62 struct code_ptr
*next
;
65 static struct extraction
*extractions
;
67 /* Number instruction patterns handled, starting at 0 for first one. */
69 static int insn_code_number
;
71 /* Records the large operand number in this insn. */
75 /* Records the location of any operands using the string format described
78 static char *oplocs
[MAX_RECOG_OPERANDS
];
80 /* Number the occurrences of MATCH_DUP in each instruction,
81 starting at 0 for the first occurrence. */
85 /* Records the location of any MATCH_DUP operands. */
87 static char *duplocs
[MAX_DUP_OPERANDS
];
89 /* Record the operand number of any MATCH_DUPs. */
91 static int dupnums
[MAX_DUP_OPERANDS
];
93 /* Record the list of insn_codes for peepholes. */
95 static struct code_ptr
*peepholes
;
97 static void walk_rtx ();
98 static void print_path ();
101 static void fatal ();
102 static char *copystr ();
103 static void mybzero ();
111 register struct extraction
*p
;
112 register struct code_ptr
*link
;
117 /* No operands seen so far in this pattern. */
118 mybzero (oplocs
, sizeof oplocs
);
120 /* Walk the insn's pattern, remembering at all times the path
121 down to the walking point. */
123 if (XVECLEN (insn
, 1) == 1)
124 walk_rtx (XVECEXP (insn
, 1, 0), "");
126 for (i
= XVECLEN (insn
, 1) - 1; i
>= 0; i
--)
128 char *path
= (char *) alloca (2);
133 walk_rtx (XVECEXP (insn
, 1, i
), path
);
136 link
= (struct code_ptr
*) xmalloc (sizeof (struct code_ptr
));
137 link
->insn_code
= insn_code_number
;
139 /* See if we find something that already had this extraction method. */
141 for (p
= extractions
; p
; p
= p
->next
)
143 if (p
->op_count
!= op_count
|| p
->dup_count
!= dup_count
)
146 for (i
= 0; i
< op_count
; i
++)
147 if (p
->oplocs
[i
] != oplocs
[i
]
148 && ! (p
->oplocs
[i
] != 0 && oplocs
[i
] != 0
149 && ! strcmp (p
->oplocs
[i
], oplocs
[i
])))
155 for (i
= 0; i
< dup_count
; i
++)
156 if (p
->dupnums
[i
] != dupnums
[i
]
157 || strcmp (p
->duplocs
[i
], duplocs
[i
]))
163 /* This extraction is the same as ours. Just link us in. */
164 link
->next
= p
->insns
;
169 /* Otherwise, make a new extraction method. */
171 p
= (struct extraction
*) xmalloc (sizeof (struct extraction
));
172 p
->op_count
= op_count
;
173 p
->dup_count
= dup_count
;
174 p
->next
= extractions
;
179 for (i
= 0; i
< op_count
; i
++)
180 p
->oplocs
[i
] = oplocs
[i
];
182 for (i
= 0; i
< dup_count
; i
++)
183 p
->dupnums
[i
] = dupnums
[i
], p
->duplocs
[i
] = duplocs
[i
];
191 register RTX_CODE code
;
195 register struct code_ptr
*link
;
196 int depth
= strlen (path
);
214 oplocs
[XINT (x
, 0)] = copystr (path
);
215 op_count
= MAX (op_count
, XINT (x
, 0) + 1);
220 duplocs
[dup_count
] = copystr (path
);
221 dupnums
[dup_count
] = XINT (x
, 0);
226 oplocs
[XINT (x
, 0)] = copystr (path
);
227 op_count
= MAX (op_count
, XINT (x
, 0) + 1);
229 newpath
= (char *) alloca (depth
+ 2);
230 strcpy (newpath
, path
);
231 newpath
[depth
+ 1] = 0;
233 for (i
= XVECLEN (x
, 2) - 1; i
>= 0; i
--)
235 newpath
[depth
] = '0' + i
;
236 walk_rtx (XVECEXP (x
, 2, i
), newpath
);
241 oplocs
[XINT (x
, 0)] = copystr (path
);
242 op_count
= MAX (op_count
, XINT (x
, 0) + 1);
244 newpath
= (char *) alloca (depth
+ 2);
245 strcpy (newpath
, path
);
246 newpath
[depth
+ 1] = 0;
248 for (i
= XVECLEN (x
, 2) - 1; i
>= 0; i
--)
250 newpath
[depth
] = 'a' + i
;
251 walk_rtx (XVECEXP (x
, 2, i
), newpath
);
256 walk_rtx (XEXP (x
, 0), path
);
260 newpath
= (char *) alloca (depth
+ 2);
261 strcpy (newpath
, path
);
262 newpath
[depth
+ 1] = 0;
264 fmt
= GET_RTX_FORMAT (code
);
265 len
= GET_RTX_LENGTH (code
);
266 for (i
= 0; i
< len
; i
++)
268 if (fmt
[i
] == 'e' || fmt
[i
] == 'u')
270 newpath
[depth
] = '0' + i
;
271 walk_rtx (XEXP (x
, i
), newpath
);
273 else if (fmt
[i
] == 'E')
276 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
278 newpath
[depth
] = 'a' + j
;
279 walk_rtx (XVECEXP (x
, i
, j
), newpath
);
285 /* Given a PATH, representing a path down the instruction's
286 pattern from the root to a certain point, output code to
287 evaluate to the rtx at that point. */
293 register int len
= strlen (path
);
296 /* We first write out the operations (XEXP or XVECEXP) in reverse
297 order, then write "insn", then the indices in forward order. */
299 for (i
= len
- 1; i
>=0 ; i
--)
301 if (path
[i
] >= 'a' && path
[i
] <= 'z')
302 printf ("XVECEXP (");
303 else if (path
[i
] >= '0' && path
[i
] <= '9')
311 for (i
= 0; i
< len
; i
++)
313 if (path
[i
] >= 'a' && path
[i
] <= 'z')
314 printf (", 0, %d)", path
[i
] - 'a');
315 else if (path
[i
] >= '0' && path
[i
] <= '9')
316 printf (", %d)", path
[i
] - '0');
326 register char *val
= (char *) malloc (size
);
329 fatal ("virtual memory exhausted");
338 char *result
= (char *) realloc (ptr
, size
);
340 fatal ("virtual memory exhausted");
348 fprintf (stderr
, "genextract: ");
349 fprintf (stderr
, s
, a1
, a2
);
350 fprintf (stderr
, "\n");
351 exit (FATAL_EXIT_CODE
);
354 /* More 'friendly' abort that prints the line and file.
355 config.h can #define abort fancy_abort if you like that sort of thing. */
360 fatal ("Internal gcc abort.");
372 tem
= (char *) xmalloc (strlen (s1
) + 1);
381 register unsigned length
;
395 struct extraction
*p
;
396 struct code_ptr
*link
;
398 obstack_init (rtl_obstack
);
401 fatal ("No input file name.");
403 infile
= fopen (argv
[1], "r");
407 exit (FATAL_EXIT_CODE
);
412 /* Assign sequential codes to all entries in the machine description
413 in parallel with the tables in insn-output.c. */
415 insn_code_number
= 0;
417 printf ("/* Generated automatically by the program `genextract'\n\
418 from the machine description file `md'. */\n\n");
420 printf ("#include \"config.h\"\n");
421 printf ("#include \"rtl.h\"\n\n");
423 /* This variable exists only so it can be the "location"
424 of any missing operand whose numbers are skipped by a given pattern. */
425 printf ("static rtx junk;\n");
427 printf ("extern rtx recog_operand[];\n");
428 printf ("extern rtx *recog_operand_loc[];\n");
429 printf ("extern rtx *recog_dup_loc[];\n");
430 printf ("extern char recog_dup_num[];\n");
431 printf ("extern\n#ifdef __GNUC__\nvolatile\n#endif\n");
432 printf ("void fatal_insn_not_found ();\n\n");
434 printf ("void\ninsn_extract (insn)\n");
435 printf (" rtx insn;\n");
437 printf (" register rtx *ro = recog_operand;\n");
438 printf (" register rtx **ro_loc = recog_operand_loc;\n");
439 printf (" rtx pat = PATTERN (insn);\n");
440 printf (" switch (INSN_CODE (insn))\n");
442 printf (" case -1:\n");
443 printf (" fatal_insn_not_found (insn);\n\n");
445 /* Read the machine description. */
449 c
= read_skip_spaces (infile
);
454 desc
= read_rtx (infile
);
455 if (GET_CODE (desc
) == DEFINE_INSN
)
461 else if (GET_CODE (desc
) == DEFINE_PEEPHOLE
)
463 struct code_ptr
*link
464 = (struct code_ptr
*) xmalloc (sizeof (struct code_ptr
));
466 link
->insn_code
= insn_code_number
;
467 link
->next
= peepholes
;
472 else if (GET_CODE (desc
) == DEFINE_EXPAND
473 || GET_CODE (desc
) == DEFINE_SPLIT
)
477 /* Write out code to handle peepholes and the insn_codes that it should
481 for (link
= peepholes
; link
; link
= link
->next
)
482 printf (" case %d:\n", link
->insn_code
);
484 /* The vector in the insn says how many operands it has.
485 And all it contains are operands. In fact, the vector was
486 created just for the sake of this function. */
487 printf ("#if __GNUC__ > 1 && !defined (bcopy)\n");
488 printf ("#define bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)\n");
490 printf (" bcopy (&XVECEXP (pat, 0, 0), ro,\n");
491 printf (" sizeof (rtx) * XVECLEN (pat, 0));\n");
492 printf (" break;\n\n");
495 /* Write out all the ways to extract insn operands. */
496 for (p
= extractions
; p
; p
= p
->next
)
498 for (link
= p
->insns
; link
; link
= link
->next
)
499 printf (" case %d:\n", link
->insn_code
);
501 for (i
= 0; i
< p
->op_count
; i
++)
503 if (p
->oplocs
[i
] == 0)
505 printf (" ro[%d] = const0_rtx;\n", i
);
506 printf (" ro_loc[%d] = &junk;\n", i
, i
);
510 printf (" ro[%d] = *(ro_loc[%d] = &", i
, i
);
511 print_path (p
->oplocs
[i
]);
516 for (i
= 0; i
< p
->dup_count
; i
++)
518 printf (" recog_dup_loc[%d] = &", i
);
519 print_path (p
->duplocs
[i
]);
521 printf (" recog_dup_num[%d] = %d;\n", i
, p
->dupnums
[i
]);
524 printf (" break;\n\n");
527 /* This should never be reached. Note that we would also reach this abort
528 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
529 DEFINE_SPLIT, but that is correct. */
530 printf (" default:\n abort ();\n");
535 exit (ferror (stdout
) != 0 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);
This page took 0.05967 seconds and 5 git commands to generate.