1c3d31fe1Smrg /* Generate code from machine description to extract operands from insn as rtl.
2*dd083157Smrg Copyright (C) 1987-2020 Free Software Foundation, Inc.
3c3d31fe1Smrg
4c3d31fe1Smrg This file is part of GCC.
5c3d31fe1Smrg
6c3d31fe1Smrg GCC is free software; you can redistribute it and/or modify it under
7c3d31fe1Smrg the terms of the GNU General Public License as published by the Free
8c3d31fe1Smrg Software Foundation; either version 3, or (at your option) any later
9c3d31fe1Smrg version.
10c3d31fe1Smrg
11c3d31fe1Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12c3d31fe1Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
13c3d31fe1Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14c3d31fe1Smrg for more details.
15c3d31fe1Smrg
16c3d31fe1Smrg You should have received a copy of the GNU General Public License
17c3d31fe1Smrg along with GCC; see the file COPYING3. If not see
18c3d31fe1Smrg <http://www.gnu.org/licenses/>. */
19c3d31fe1Smrg
20c3d31fe1Smrg
21c3d31fe1Smrg #include "bconfig.h"
22c3d31fe1Smrg #include "system.h"
23c3d31fe1Smrg #include "coretypes.h"
24c3d31fe1Smrg #include "tm.h"
25c3d31fe1Smrg #include "rtl.h"
26c3d31fe1Smrg #include "errors.h"
27af526226Smrg #include "read-md.h"
28c3d31fe1Smrg #include "gensupport.h"
29c3d31fe1Smrg
30c3d31fe1Smrg /* This structure contains all the information needed to describe one
31c3d31fe1Smrg set of extractions methods. Each method may be used by more than
32c3d31fe1Smrg one pattern if the operands are in the same place.
33c3d31fe1Smrg
34c3d31fe1Smrg The string for each operand describes that path to the operand and
35c3d31fe1Smrg contains `0' through `9' when going into an expression and `a' through
363903d7f3Smrg `z' then 'A' through to 'Z' when going into a vector. We assume here that
373903d7f3Smrg only the first operand of an rtl expression is a vector. genrecog.c makes
383903d7f3Smrg the same assumption (and uses the same representation) and it is currently
393903d7f3Smrg true. */
40c3d31fe1Smrg
41c3d31fe1Smrg typedef char *locstr;
42c3d31fe1Smrg
43c3d31fe1Smrg struct extraction
44c3d31fe1Smrg {
45c3d31fe1Smrg unsigned int op_count;
46c3d31fe1Smrg unsigned int dup_count;
47c3d31fe1Smrg locstr *oplocs;
48c3d31fe1Smrg locstr *duplocs;
49c3d31fe1Smrg int *dupnums;
50c3d31fe1Smrg struct code_ptr *insns;
51c3d31fe1Smrg struct extraction *next;
52c3d31fe1Smrg };
53c3d31fe1Smrg
54c3d31fe1Smrg /* Holds a single insn code that uses an extraction method. */
55c3d31fe1Smrg struct code_ptr
56c3d31fe1Smrg {
57c3d31fe1Smrg int insn_code;
58c3d31fe1Smrg struct code_ptr *next;
59c3d31fe1Smrg };
60c3d31fe1Smrg
61c3d31fe1Smrg /* All extractions needed for this machine description. */
62c3d31fe1Smrg static struct extraction *extractions;
63c3d31fe1Smrg
64c3d31fe1Smrg /* All insn codes for old-style peepholes. */
65c3d31fe1Smrg static struct code_ptr *peepholes;
66c3d31fe1Smrg
67c3d31fe1Smrg /* This structure is used by gen_insn and walk_rtx to accumulate the
68c3d31fe1Smrg data that will be used to produce an extractions structure. */
69c3d31fe1Smrg
70c3d31fe1Smrg
71*dd083157Smrg class accum_extract
72c3d31fe1Smrg {
73*dd083157Smrg public:
accum_extract()746a5c9aabSmrg accum_extract () : oplocs (10), duplocs (10), dupnums (10), pathstr (20) {}
756a5c9aabSmrg
766a5c9aabSmrg auto_vec<locstr> oplocs;
776a5c9aabSmrg auto_vec<locstr> duplocs;
786a5c9aabSmrg auto_vec<int> dupnums;
796a5c9aabSmrg auto_vec<char> pathstr;
80c3d31fe1Smrg };
81c3d31fe1Smrg
82c3d31fe1Smrg /* Forward declarations. */
83*dd083157Smrg static void walk_rtx (md_rtx_info *, rtx, class accum_extract *);
84c3d31fe1Smrg
853903d7f3Smrg #define UPPER_OFFSET ('A' - ('z' - 'a' + 1))
863903d7f3Smrg
873903d7f3Smrg /* Convert integer OPERAND into a character - either into [a-zA-Z] for vector
883903d7f3Smrg operands or [0-9] for integer operands - and push onto the end of the path
893903d7f3Smrg in ACC. */
903903d7f3Smrg static void
push_pathstr_operand(int operand,bool is_vector,class accum_extract * acc)913903d7f3Smrg push_pathstr_operand (int operand, bool is_vector,
92*dd083157Smrg class accum_extract *acc)
933903d7f3Smrg {
943903d7f3Smrg if (is_vector && 'a' + operand > 'z')
953903d7f3Smrg acc->pathstr.safe_push (operand + UPPER_OFFSET);
963903d7f3Smrg else if (is_vector)
973903d7f3Smrg acc->pathstr.safe_push (operand + 'a');
983903d7f3Smrg else
993903d7f3Smrg acc->pathstr.safe_push (operand + '0');
1003903d7f3Smrg }
1013903d7f3Smrg
102c3d31fe1Smrg static void
gen_insn(md_rtx_info * info)10363aace61Smrg gen_insn (md_rtx_info *info)
104c3d31fe1Smrg {
105c3d31fe1Smrg int i;
106c3d31fe1Smrg unsigned int op_count, dup_count, j;
107c3d31fe1Smrg struct extraction *p;
108c3d31fe1Smrg struct code_ptr *link;
109*dd083157Smrg class accum_extract acc;
110c3d31fe1Smrg
111c3d31fe1Smrg /* Walk the insn's pattern, remembering at all times the path
112c3d31fe1Smrg down to the walking point. */
113c3d31fe1Smrg
11463aace61Smrg rtx insn = info->def;
115c3d31fe1Smrg if (XVECLEN (insn, 1) == 1)
11663aace61Smrg walk_rtx (info, XVECEXP (insn, 1, 0), &acc);
117c3d31fe1Smrg else
118c3d31fe1Smrg for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
119c3d31fe1Smrg {
1203903d7f3Smrg push_pathstr_operand (i, true, &acc);
12163aace61Smrg walk_rtx (info, XVECEXP (insn, 1, i), &acc);
122af526226Smrg acc.pathstr.pop ();
123c3d31fe1Smrg }
124c3d31fe1Smrg
125c3d31fe1Smrg link = XNEW (struct code_ptr);
12663aace61Smrg link->insn_code = info->index;
127c3d31fe1Smrg
128c3d31fe1Smrg /* See if we find something that already had this extraction method. */
129c3d31fe1Smrg
130af526226Smrg op_count = acc.oplocs.length ();
131af526226Smrg dup_count = acc.duplocs.length ();
132af526226Smrg gcc_assert (dup_count == acc.dupnums.length ());
133c3d31fe1Smrg
134c3d31fe1Smrg for (p = extractions; p; p = p->next)
135c3d31fe1Smrg {
136c3d31fe1Smrg if (p->op_count != op_count || p->dup_count != dup_count)
137c3d31fe1Smrg continue;
138c3d31fe1Smrg
139c3d31fe1Smrg for (j = 0; j < op_count; j++)
140c3d31fe1Smrg {
141c3d31fe1Smrg char *a = p->oplocs[j];
142af526226Smrg char *b = acc.oplocs[j];
143c3d31fe1Smrg if (a != b && (!a || !b || strcmp (a, b)))
144c3d31fe1Smrg break;
145c3d31fe1Smrg }
146c3d31fe1Smrg
147c3d31fe1Smrg if (j != op_count)
148c3d31fe1Smrg continue;
149c3d31fe1Smrg
150c3d31fe1Smrg for (j = 0; j < dup_count; j++)
151af526226Smrg if (p->dupnums[j] != acc.dupnums[j]
152af526226Smrg || strcmp (p->duplocs[j], acc.duplocs[j]))
153c3d31fe1Smrg break;
154c3d31fe1Smrg
155c3d31fe1Smrg if (j != dup_count)
156c3d31fe1Smrg continue;
157c3d31fe1Smrg
158c3d31fe1Smrg /* This extraction is the same as ours. Just link us in. */
159c3d31fe1Smrg link->next = p->insns;
160c3d31fe1Smrg p->insns = link;
1616a5c9aabSmrg return;
162c3d31fe1Smrg }
163c3d31fe1Smrg
164c3d31fe1Smrg /* Otherwise, make a new extraction method. We stash the arrays
165c3d31fe1Smrg after the extraction structure in memory. */
166c3d31fe1Smrg
167c3d31fe1Smrg p = XNEWVAR (struct extraction, sizeof (struct extraction)
168c3d31fe1Smrg + op_count*sizeof (char *)
169c3d31fe1Smrg + dup_count*sizeof (char *)
170c3d31fe1Smrg + dup_count*sizeof (int));
171c3d31fe1Smrg p->op_count = op_count;
172c3d31fe1Smrg p->dup_count = dup_count;
173c3d31fe1Smrg p->next = extractions;
174c3d31fe1Smrg extractions = p;
175c3d31fe1Smrg p->insns = link;
176c3d31fe1Smrg link->next = 0;
177c3d31fe1Smrg
178c3d31fe1Smrg p->oplocs = (char **)((char *)p + sizeof (struct extraction));
179c3d31fe1Smrg p->duplocs = p->oplocs + op_count;
180c3d31fe1Smrg p->dupnums = (int *)(p->duplocs + dup_count);
181c3d31fe1Smrg
182af526226Smrg memcpy (p->oplocs, acc.oplocs.address (), op_count * sizeof (locstr));
183af526226Smrg memcpy (p->duplocs, acc.duplocs.address (), dup_count * sizeof (locstr));
184af526226Smrg memcpy (p->dupnums, acc.dupnums.address (), dup_count * sizeof (int));
185c3d31fe1Smrg }
186c3d31fe1Smrg
187af526226Smrg /* Helper subroutine of walk_rtx: given a vec<locstr>, an index, and a
188c3d31fe1Smrg string, insert the string at the index, which should either already
189c3d31fe1Smrg exist and be NULL, or not yet exist within the vector. In the latter
19063aace61Smrg case the vector is enlarged as appropriate. INFO describes the
19163aace61Smrg containing define_* expression. */
192c3d31fe1Smrg static void
VEC_safe_set_locstr(md_rtx_info * info,vec<locstr> * vp,unsigned int ix,char * str)19363aace61Smrg VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp,
19463aace61Smrg unsigned int ix, char *str)
195c3d31fe1Smrg {
196af526226Smrg if (ix < (*vp).length ())
197c3d31fe1Smrg {
198af526226Smrg if ((*vp)[ix])
199c3d31fe1Smrg {
20063aace61Smrg message_at (info->loc, "repeated operand number %d", ix);
201c3d31fe1Smrg have_error = 1;
202c3d31fe1Smrg }
203c3d31fe1Smrg else
204af526226Smrg (*vp)[ix] = str;
205c3d31fe1Smrg }
206c3d31fe1Smrg else
207c3d31fe1Smrg {
208af526226Smrg while (ix > (*vp).length ())
209af526226Smrg vp->safe_push (NULL);
210af526226Smrg vp->safe_push (str);
211c3d31fe1Smrg }
212c3d31fe1Smrg }
213c3d31fe1Smrg
214af526226Smrg /* Another helper subroutine of walk_rtx: given a vec<char>, convert it
215c3d31fe1Smrg to a NUL-terminated string in malloc memory. */
216c3d31fe1Smrg static char *
VEC_char_to_string(vec<char> v)217af526226Smrg VEC_char_to_string (vec<char> v)
218c3d31fe1Smrg {
219af526226Smrg size_t n = v.length ();
220c3d31fe1Smrg char *s = XNEWVEC (char, n + 1);
221af526226Smrg memcpy (s, v.address (), n);
222c3d31fe1Smrg s[n] = '\0';
223c3d31fe1Smrg return s;
224c3d31fe1Smrg }
225c3d31fe1Smrg
226c3d31fe1Smrg static void
walk_rtx(md_rtx_info * info,rtx x,class accum_extract * acc)227*dd083157Smrg walk_rtx (md_rtx_info *info, rtx x, class accum_extract *acc)
228c3d31fe1Smrg {
229c3d31fe1Smrg RTX_CODE code;
2303903d7f3Smrg int i, len;
231c3d31fe1Smrg const char *fmt;
232c3d31fe1Smrg
233c3d31fe1Smrg if (x == 0)
234c3d31fe1Smrg return;
235c3d31fe1Smrg
236c3d31fe1Smrg code = GET_CODE (x);
237c3d31fe1Smrg switch (code)
238c3d31fe1Smrg {
239c3d31fe1Smrg case PC:
240c3d31fe1Smrg case CC0:
241c3d31fe1Smrg case CONST_INT:
242c3d31fe1Smrg case SYMBOL_REF:
243c3d31fe1Smrg return;
244c3d31fe1Smrg
245c3d31fe1Smrg case MATCH_OPERAND:
246c3d31fe1Smrg case MATCH_SCRATCH:
24763aace61Smrg VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0),
248c3d31fe1Smrg VEC_char_to_string (acc->pathstr));
249c3d31fe1Smrg break;
250c3d31fe1Smrg
251c3d31fe1Smrg case MATCH_OPERATOR:
252c3d31fe1Smrg case MATCH_PARALLEL:
25363aace61Smrg VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0),
254c3d31fe1Smrg VEC_char_to_string (acc->pathstr));
255c3d31fe1Smrg
256c3d31fe1Smrg for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
257c3d31fe1Smrg {
2583903d7f3Smrg push_pathstr_operand (i, code != MATCH_OPERATOR, acc);
25963aace61Smrg walk_rtx (info, XVECEXP (x, 2, i), acc);
260af526226Smrg acc->pathstr.pop ();
261c3d31fe1Smrg }
262c3d31fe1Smrg return;
263c3d31fe1Smrg
264c3d31fe1Smrg case MATCH_DUP:
265c3d31fe1Smrg case MATCH_PAR_DUP:
266c3d31fe1Smrg case MATCH_OP_DUP:
267af526226Smrg acc->duplocs.safe_push (VEC_char_to_string (acc->pathstr));
268af526226Smrg acc->dupnums.safe_push (XINT (x, 0));
269c3d31fe1Smrg
270c3d31fe1Smrg if (code == MATCH_DUP)
271c3d31fe1Smrg break;
272c3d31fe1Smrg
273c3d31fe1Smrg for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
274c3d31fe1Smrg {
2753903d7f3Smrg push_pathstr_operand (i, code != MATCH_OP_DUP, acc);
27663aace61Smrg walk_rtx (info, XVECEXP (x, 1, i), acc);
277af526226Smrg acc->pathstr.pop ();
278c3d31fe1Smrg }
279c3d31fe1Smrg return;
280c3d31fe1Smrg
281c3d31fe1Smrg default:
282c3d31fe1Smrg break;
283c3d31fe1Smrg }
284c3d31fe1Smrg
285c3d31fe1Smrg fmt = GET_RTX_FORMAT (code);
286c3d31fe1Smrg len = GET_RTX_LENGTH (code);
287c3d31fe1Smrg for (i = 0; i < len; i++)
288c3d31fe1Smrg {
289c3d31fe1Smrg if (fmt[i] == 'e' || fmt[i] == 'u')
290c3d31fe1Smrg {
2913903d7f3Smrg push_pathstr_operand (i, false, acc);
29263aace61Smrg walk_rtx (info, XEXP (x, i), acc);
293af526226Smrg acc->pathstr.pop ();
294c3d31fe1Smrg }
295c3d31fe1Smrg else if (fmt[i] == 'E')
296c3d31fe1Smrg {
297c3d31fe1Smrg int j;
298c3d31fe1Smrg for (j = XVECLEN (x, i) - 1; j >= 0; j--)
299c3d31fe1Smrg {
3003903d7f3Smrg push_pathstr_operand (j, true, acc);
30163aace61Smrg walk_rtx (info, XVECEXP (x, i, j), acc);
302af526226Smrg acc->pathstr.pop ();
303c3d31fe1Smrg }
304c3d31fe1Smrg }
305c3d31fe1Smrg }
306c3d31fe1Smrg }
307c3d31fe1Smrg
308c3d31fe1Smrg /* Given a PATH, representing a path down the instruction's
309c3d31fe1Smrg pattern from the root to a certain point, output code to
310c3d31fe1Smrg evaluate to the rtx at that point. */
311c3d31fe1Smrg
312c3d31fe1Smrg static void
print_path(const char * path)313c3d31fe1Smrg print_path (const char *path)
314c3d31fe1Smrg {
315c3d31fe1Smrg int len = strlen (path);
316c3d31fe1Smrg int i;
317c3d31fe1Smrg
318c3d31fe1Smrg if (len == 0)
319c3d31fe1Smrg {
320c3d31fe1Smrg /* Don't emit "pat", since we may try to take the address of it,
321c3d31fe1Smrg which isn't what is intended. */
322c3d31fe1Smrg fputs ("PATTERN (insn)", stdout);
323c3d31fe1Smrg return;
324c3d31fe1Smrg }
325c3d31fe1Smrg
326c3d31fe1Smrg /* We first write out the operations (XEXP or XVECEXP) in reverse
327c3d31fe1Smrg order, then write "pat", then the indices in forward order. */
328c3d31fe1Smrg
329c3d31fe1Smrg for (i = len - 1; i >= 0 ; i--)
330c3d31fe1Smrg {
3313903d7f3Smrg if (ISLOWER (path[i]) || ISUPPER (path[i]))
332c3d31fe1Smrg fputs ("XVECEXP (", stdout);
333c3d31fe1Smrg else if (ISDIGIT (path[i]))
334c3d31fe1Smrg fputs ("XEXP (", stdout);
335c3d31fe1Smrg else
336c3d31fe1Smrg gcc_unreachable ();
337c3d31fe1Smrg }
338c3d31fe1Smrg
339c3d31fe1Smrg fputs ("pat", stdout);
340c3d31fe1Smrg
341c3d31fe1Smrg for (i = 0; i < len; i++)
342c3d31fe1Smrg {
3433903d7f3Smrg if (ISUPPER (path[i]))
3443903d7f3Smrg printf (", 0, %d)", path[i] - UPPER_OFFSET);
3453903d7f3Smrg else if (ISLOWER (path[i]))
346c3d31fe1Smrg printf (", 0, %d)", path[i] - 'a');
347c3d31fe1Smrg else if (ISDIGIT (path[i]))
348c3d31fe1Smrg printf (", %d)", path[i] - '0');
349c3d31fe1Smrg else
350c3d31fe1Smrg gcc_unreachable ();
351c3d31fe1Smrg }
352c3d31fe1Smrg }
353c3d31fe1Smrg
354c3d31fe1Smrg static void
print_header(void)355c3d31fe1Smrg print_header (void)
356c3d31fe1Smrg {
357c3d31fe1Smrg /* N.B. Code below avoids putting squiggle braces in column 1 inside
358c3d31fe1Smrg a string, because this confuses some editors' syntax highlighting
359c3d31fe1Smrg engines. */
360c3d31fe1Smrg
361c3d31fe1Smrg puts ("\
362c3d31fe1Smrg /* Generated automatically by the program `genextract'\n\
363c3d31fe1Smrg from the machine description file `md'. */\n\
364c3d31fe1Smrg \n\
3653903d7f3Smrg #define IN_TARGET_CODE 1\n\
366c3d31fe1Smrg #include \"config.h\"\n\
367c3d31fe1Smrg #include \"system.h\"\n\
368c3d31fe1Smrg #include \"coretypes.h\"\n\
369c3d31fe1Smrg #include \"tm.h\"\n\
370c3d31fe1Smrg #include \"rtl.h\"\n\
371c3d31fe1Smrg #include \"insn-config.h\"\n\
372c3d31fe1Smrg #include \"recog.h\"\n\
373af526226Smrg #include \"diagnostic-core.h\"\n\
374c3d31fe1Smrg \n\
375c3d31fe1Smrg /* This variable is used as the \"location\" of any missing operand\n\
376c3d31fe1Smrg whose numbers are skipped by a given pattern. */\n\
377c3d31fe1Smrg static rtx junk ATTRIBUTE_UNUSED;\n");
378c3d31fe1Smrg
379c3d31fe1Smrg puts ("\
380c3d31fe1Smrg void\n\
3815ef59e75Smrg insn_extract (rtx_insn *insn)\n{\n\
382c3d31fe1Smrg rtx *ro = recog_data.operand;\n\
383c3d31fe1Smrg rtx **ro_loc = recog_data.operand_loc;\n\
384c3d31fe1Smrg rtx pat = PATTERN (insn);\n\
385c3d31fe1Smrg int i ATTRIBUTE_UNUSED; /* only for peepholes */\n\
386c3d31fe1Smrg \n\
38763aace61Smrg if (flag_checking)\n\
38863aace61Smrg {\n\
389c3d31fe1Smrg memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\
390c3d31fe1Smrg memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\
39163aace61Smrg }\n");
392c3d31fe1Smrg
393c3d31fe1Smrg puts ("\
394c3d31fe1Smrg switch (INSN_CODE (insn))\n\
395c3d31fe1Smrg {\n\
396c3d31fe1Smrg default:\n\
397c3d31fe1Smrg /* Control reaches here if insn_extract has been called with an\n\
398c3d31fe1Smrg unrecognizable insn (code -1), or an insn whose INSN_CODE\n\
399c3d31fe1Smrg corresponds to a DEFINE_EXPAND in the machine description;\n\
400c3d31fe1Smrg either way, a bug. */\n\
401c3d31fe1Smrg if (INSN_CODE (insn) < 0)\n\
402c3d31fe1Smrg fatal_insn (\"unrecognizable insn:\", insn);\n\
403c3d31fe1Smrg else\n\
404c3d31fe1Smrg fatal_insn (\"insn with invalid code number:\", insn);\n");
405c3d31fe1Smrg }
406c3d31fe1Smrg
407c3d31fe1Smrg int
main(int argc,const char ** argv)4086a5c9aabSmrg main (int argc, const char **argv)
409c3d31fe1Smrg {
410c3d31fe1Smrg unsigned int i;
411c3d31fe1Smrg struct extraction *p;
412c3d31fe1Smrg struct code_ptr *link;
413c3d31fe1Smrg const char *name;
414c3d31fe1Smrg
415c3d31fe1Smrg progname = "genextract";
416c3d31fe1Smrg
417af526226Smrg if (!init_rtx_reader_args (argc, argv))
418c3d31fe1Smrg return (FATAL_EXIT_CODE);
419c3d31fe1Smrg
420c3d31fe1Smrg /* Read the machine description. */
421c3d31fe1Smrg
42263aace61Smrg md_rtx_info info;
42363aace61Smrg while (read_md_rtx (&info))
42463aace61Smrg switch (GET_CODE (info.def))
425c3d31fe1Smrg {
42663aace61Smrg case DEFINE_INSN:
42763aace61Smrg gen_insn (&info);
42863aace61Smrg break;
429c3d31fe1Smrg
43063aace61Smrg case DEFINE_PEEPHOLE:
431c3d31fe1Smrg {
432c3d31fe1Smrg struct code_ptr *link = XNEW (struct code_ptr);
433c3d31fe1Smrg
43463aace61Smrg link->insn_code = info.index;
435c3d31fe1Smrg link->next = peepholes;
436c3d31fe1Smrg peepholes = link;
437c3d31fe1Smrg }
43863aace61Smrg break;
43963aace61Smrg
44063aace61Smrg default:
44163aace61Smrg break;
442c3d31fe1Smrg }
443c3d31fe1Smrg
444c3d31fe1Smrg if (have_error)
445c3d31fe1Smrg return FATAL_EXIT_CODE;
446c3d31fe1Smrg
447c3d31fe1Smrg print_header ();
448c3d31fe1Smrg
449c3d31fe1Smrg /* Write out code to handle peepholes and the insn_codes that it should
450c3d31fe1Smrg be called for. */
451c3d31fe1Smrg if (peepholes)
452c3d31fe1Smrg {
453c3d31fe1Smrg for (link = peepholes; link; link = link->next)
454c3d31fe1Smrg printf (" case %d:\n", link->insn_code);
455c3d31fe1Smrg
456c3d31fe1Smrg /* The vector in the insn says how many operands it has.
457c3d31fe1Smrg And all it contains are operands. In fact, the vector was
458c3d31fe1Smrg created just for the sake of this function. We need to set the
459c3d31fe1Smrg location of the operands for sake of simplifications after
460c3d31fe1Smrg extraction, like eliminating subregs. */
461c3d31fe1Smrg puts (" for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)\n"
462c3d31fe1Smrg " ro[i] = *(ro_loc[i] = &XVECEXP (pat, 0, i));\n"
463c3d31fe1Smrg " break;\n");
464c3d31fe1Smrg }
465c3d31fe1Smrg
466c3d31fe1Smrg /* Write out all the ways to extract insn operands. */
467c3d31fe1Smrg for (p = extractions; p; p = p->next)
468c3d31fe1Smrg {
469c3d31fe1Smrg for (link = p->insns; link; link = link->next)
470c3d31fe1Smrg {
471c3d31fe1Smrg i = link->insn_code;
472c3d31fe1Smrg name = get_insn_name (i);
473c3d31fe1Smrg if (name)
474c3d31fe1Smrg printf (" case %d: /* %s */\n", i, name);
475c3d31fe1Smrg else
476c3d31fe1Smrg printf (" case %d:\n", i);
477c3d31fe1Smrg }
478c3d31fe1Smrg
479c3d31fe1Smrg for (i = 0; i < p->op_count; i++)
480c3d31fe1Smrg {
481c3d31fe1Smrg if (p->oplocs[i] == 0)
482c3d31fe1Smrg {
483c3d31fe1Smrg printf (" ro[%d] = const0_rtx;\n", i);
484c3d31fe1Smrg printf (" ro_loc[%d] = &junk;\n", i);
485c3d31fe1Smrg }
486c3d31fe1Smrg else
487c3d31fe1Smrg {
488c3d31fe1Smrg printf (" ro[%d] = *(ro_loc[%d] = &", i, i);
489c3d31fe1Smrg print_path (p->oplocs[i]);
490c3d31fe1Smrg puts (");");
491c3d31fe1Smrg }
492c3d31fe1Smrg }
493c3d31fe1Smrg
494c3d31fe1Smrg for (i = 0; i < p->dup_count; i++)
495c3d31fe1Smrg {
496c3d31fe1Smrg printf (" recog_data.dup_loc[%d] = &", i);
497c3d31fe1Smrg print_path (p->duplocs[i]);
498c3d31fe1Smrg puts (";");
499c3d31fe1Smrg printf (" recog_data.dup_num[%d] = %d;\n", i, p->dupnums[i]);
500c3d31fe1Smrg }
501c3d31fe1Smrg
502c3d31fe1Smrg puts (" break;\n");
503c3d31fe1Smrg }
504c3d31fe1Smrg
505c3d31fe1Smrg puts (" }\n}");
506c3d31fe1Smrg fflush (stdout);
507c3d31fe1Smrg return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
508c3d31fe1Smrg }
509