1 /* Generate code from machine description to extract operands from insn as rtl.
2 Copyright (C) 1987, 1991, 1992, 1993, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
28 #include "insn-config.h"
30 static struct obstack obstack
;
31 struct obstack
*rtl_obstack
= &obstack
;
33 #define obstack_chunk_alloc xmalloc
34 #define obstack_chunk_free free
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 /* Holds an array of names indexed by insn_code_number. */
68 static char **insn_name_ptr
= 0;
69 static int insn_name_ptr_size
= 0;
71 /* Number instruction patterns handled, starting at 0 for first one. */
73 static int insn_code_number
;
75 /* Records the large operand number in this insn. */
79 /* Records the location of any operands using the string format described
82 static char *oplocs
[MAX_RECOG_OPERANDS
];
84 /* Number the occurrences of MATCH_DUP in each instruction,
85 starting at 0 for the first occurrence. */
89 /* Records the location of any MATCH_DUP operands. */
91 static char *duplocs
[MAX_DUP_OPERANDS
];
93 /* Record the operand number of any MATCH_DUPs. */
95 static int dupnums
[MAX_DUP_OPERANDS
];
97 /* Record the list of insn_codes for peepholes. */
99 static struct code_ptr
*peepholes
;
101 static void gen_insn
PARAMS ((rtx
));
102 static void walk_rtx
PARAMS ((rtx
, const char *));
103 static void print_path
PARAMS ((const char *));
104 static void record_insn_name
PARAMS ((int, const char *));
111 register struct extraction
*p
;
112 register struct code_ptr
*link
;
117 /* No operands seen so far in this pattern. */
118 memset (oplocs
, 0, 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
;
194 register const char *fmt
;
195 int depth
= strlen (path
);
213 oplocs
[XINT (x
, 0)] = xstrdup (path
);
214 op_count
= MAX (op_count
, XINT (x
, 0) + 1);
219 duplocs
[dup_count
] = xstrdup (path
);
220 dupnums
[dup_count
] = XINT (x
, 0);
225 duplocs
[dup_count
] = xstrdup (path
);
226 dupnums
[dup_count
] = XINT (x
, 0);
229 newpath
= (char *) alloca (depth
+ 2);
230 strcpy (newpath
, path
);
231 newpath
[depth
+ 1] = 0;
233 for (i
= XVECLEN (x
, 1) - 1; i
>= 0; i
--)
235 newpath
[depth
] = '0' + i
;
236 walk_rtx (XVECEXP (x
, 1, i
), newpath
);
241 oplocs
[XINT (x
, 0)] = xstrdup (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
] = '0' + i
;
251 walk_rtx (XVECEXP (x
, 2, i
), newpath
);
256 oplocs
[XINT (x
, 0)] = xstrdup (path
);
257 op_count
= MAX (op_count
, XINT (x
, 0) + 1);
259 newpath
= (char *) alloca (depth
+ 2);
260 strcpy (newpath
, path
);
261 newpath
[depth
+ 1] = 0;
263 for (i
= XVECLEN (x
, 2) - 1; i
>= 0; i
--)
265 newpath
[depth
] = 'a' + i
;
266 walk_rtx (XVECEXP (x
, 2, i
), newpath
);
271 walk_rtx (XEXP (x
, 0), path
);
278 newpath
= (char *) alloca (depth
+ 2);
279 strcpy (newpath
, path
);
280 newpath
[depth
+ 1] = 0;
282 fmt
= GET_RTX_FORMAT (code
);
283 len
= GET_RTX_LENGTH (code
);
284 for (i
= 0; i
< len
; i
++)
286 if (fmt
[i
] == 'e' || fmt
[i
] == 'u')
288 newpath
[depth
] = '0' + i
;
289 walk_rtx (XEXP (x
, i
), newpath
);
291 else if (fmt
[i
] == 'E')
294 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
296 newpath
[depth
] = 'a' + j
;
297 walk_rtx (XVECEXP (x
, i
, j
), newpath
);
303 /* Given a PATH, representing a path down the instruction's
304 pattern from the root to a certain point, output code to
305 evaluate to the rtx at that point. */
311 register int len
= strlen (path
);
316 /* Don't emit "pat", since we may try to take the address of it,
317 which isn't what is intended. */
318 printf("PATTERN (insn)");
322 /* We first write out the operations (XEXP or XVECEXP) in reverse
323 order, then write "insn", then the indices in forward order. */
325 for (i
= len
- 1; i
>=0 ; i
--)
327 if (ISLOWER(path
[i
]))
328 printf ("XVECEXP (");
329 else if (ISDIGIT(path
[i
]))
337 for (i
= 0; i
< len
; i
++)
339 if (ISLOWER(path
[i
]))
340 printf (", 0, %d)", path
[i
] - 'a');
341 else if (ISDIGIT(path
[i
]))
342 printf (", %d)", path
[i
] - '0');
352 register PTR val
= (PTR
) malloc (size
);
355 fatal ("virtual memory exhausted");
366 ptr
= (PTR
) realloc (old
, size
);
368 ptr
= (PTR
) malloc (size
);
370 fatal ("virtual memory exhausted");
378 register size_t len
= strlen (input
) + 1;
379 register char *output
= xmalloc (len
);
380 memcpy (output
, input
, len
);
384 extern int main
PARAMS ((int, char **));
394 struct extraction
*p
;
395 struct code_ptr
*link
;
398 progname
= "genextract";
399 obstack_init (rtl_obstack
);
402 fatal ("No input file name.");
404 infile
= fopen (argv
[1], "r");
408 return (FATAL_EXIT_CODE
);
410 read_rtx_filename
= argv
[1];
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 \"system.h\"\n");
422 printf ("#include \"rtl.h\"\n");
423 printf ("#include \"insn-config.h\"\n");
424 printf ("#include \"recog.h\"\n");
425 printf ("#include \"toplev.h\"\n\n");
427 /* This variable exists only so it can be the "location"
428 of any missing operand whose numbers are skipped by a given pattern. */
429 printf ("static rtx junk ATTRIBUTE_UNUSED;\n");
431 printf ("void\ninsn_extract (insn)\n");
432 printf (" rtx insn;\n");
434 printf (" register rtx *ro = recog_data.operand;\n");
435 printf (" register rtx **ro_loc = recog_data.operand_loc;\n");
436 printf (" rtx pat = PATTERN (insn);\n");
437 printf (" int i ATTRIBUTE_UNUSED;\n\n");
438 printf (" memset (ro, 0, sizeof (*ro) * MAX_RECOG_OPERANDS);\n");
439 printf (" memset (ro_loc, 0, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\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
)
457 record_insn_name (insn_code_number
, XSTR (desc
, 0));
462 else if (GET_CODE (desc
) == DEFINE_PEEPHOLE
)
464 struct code_ptr
*link
465 = (struct code_ptr
*) xmalloc (sizeof (struct code_ptr
));
467 link
->insn_code
= insn_code_number
;
468 link
->next
= peepholes
;
473 else if (GET_CODE (desc
) == DEFINE_EXPAND
474 || GET_CODE (desc
) == DEFINE_PEEPHOLE2
475 || GET_CODE (desc
) == DEFINE_SPLIT
)
479 /* Write out code to handle peepholes and the insn_codes that it should
483 for (link
= peepholes
; link
; link
= link
->next
)
484 printf (" case %d:\n", link
->insn_code
);
486 /* The vector in the insn says how many operands it has.
487 And all it contains are operands. In fact, the vector was
488 created just for the sake of this function. */
489 printf (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n");
490 printf (" ro[i] = XVECEXP (pat, 0, i);\n");
491 printf (" break;\n\n");
494 /* Write out all the ways to extract insn operands. */
495 for (p
= extractions
; p
; p
= p
->next
)
497 for (link
= p
->insns
; link
; link
= link
->next
)
500 name
= get_insn_name (i
);
502 printf (" case %d: /* %s */\n", i
, name
);
504 printf (" case %d:\n", i
);
507 for (i
= 0; i
< p
->op_count
; i
++)
509 if (p
->oplocs
[i
] == 0)
511 printf (" ro[%d] = const0_rtx;\n", i
);
512 printf (" ro_loc[%d] = &junk;\n", i
);
516 printf (" ro[%d] = *(ro_loc[%d] = &", i
, i
);
517 print_path (p
->oplocs
[i
]);
522 for (i
= 0; i
< p
->dup_count
; i
++)
524 printf (" recog_data.dup_loc[%d] = &", i
);
525 print_path (p
->duplocs
[i
]);
527 printf (" recog_data.dup_num[%d] = %d;\n", i
, p
->dupnums
[i
]);
530 printf (" break;\n\n");
533 /* This should never be reached. Note that we would also reach this abort
534 if we tried to extract something whose INSN_CODE was a DEFINE_EXPAND or
535 DEFINE_SPLIT, but that is correct. */
536 printf (" default:\n abort ();\n");
541 return (ferror (stdout
) != 0 ? FATAL_EXIT_CODE
: SUCCESS_EXIT_CODE
);
544 /* Define this so we can link with print-rtl.o to get debug_rtx function. */
547 int code ATTRIBUTE_UNUSED
;
549 if (code
< insn_name_ptr_size
)
550 return insn_name_ptr
[code
];
556 record_insn_name (code
, name
)
560 static const char *last_real_name
= "insn";
561 static int last_real_code
= 0;
564 if (insn_name_ptr_size
<= code
)
567 new_size
= (insn_name_ptr_size
? insn_name_ptr_size
* 2 : 512);
569 (char **) xrealloc (insn_name_ptr
, sizeof(char *) * new_size
);
570 memset (insn_name_ptr
+ insn_name_ptr_size
, 0,
571 sizeof(char *) * (new_size
- insn_name_ptr_size
));
572 insn_name_ptr_size
= new_size
;
575 if (!name
|| name
[0] == '\0')
577 new = xmalloc (strlen (last_real_name
) + 10);
578 sprintf (new, "%s+%d", last_real_name
, code
- last_real_code
);
582 last_real_name
= new = xstrdup (name
);
583 last_real_code
= code
;
586 insn_name_ptr
[code
] = new;