]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/genemit.c
tree-ssa-struct-aliases.c (find_func_aliases_for_builtin_call): Use stack auto_vecs...
[thirdparty/gcc.git] / gcc / genemit.c
CommitLineData
65963943 1/* Generate code from machine description to emit insns as rtl.
23a5b65a 2 Copyright (C) 1987-2014 Free Software Foundation, Inc.
65963943 3
1322177d 4This file is part of GCC.
65963943 5
1322177d
LB
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
1322177d 9version.
65963943 10
1322177d
LB
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
65963943
RK
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
65963943
RK
19
20
4977bab6 21#include "bconfig.h"
0b93b64e 22#include "system.h"
4977bab6
ZW
23#include "coretypes.h"
24#include "tm.h"
65963943 25#include "rtl.h"
f8b6598e 26#include "errors.h"
10692477 27#include "read-md.h"
c88c0d42 28#include "gensupport.h"
65963943 29
65963943 30
65963943
RK
31static int insn_code_number;
32static int insn_index_number;
33
34/* Data structure for recording the patterns of insns that have CLOBBERs.
3d7aafde 35 We use this to output a function that adds these CLOBBERs to a
65963943
RK
36 previously-allocated PARALLEL expression. */
37
38struct clobber_pat
39{
e5f6a288 40 struct clobber_ent *insns;
65963943
RK
41 rtx pattern;
42 int first_clobber;
43 struct clobber_pat *next;
751aa7cc 44 int has_hard_reg;
65963943
RK
45} *clobber_list;
46
e5f6a288
RK
47/* Records one insn that uses the clobber list. */
48
49struct clobber_ent
50{
51 int code_number; /* Counts only insns. */
52 struct clobber_ent *next;
53};
54
3d7aafde
AJ
55static void print_code (RTX_CODE);
56static void gen_exp (rtx, enum rtx_code, char *);
57static void gen_insn (rtx, int);
58static void gen_expand (rtx);
59static void gen_split (rtx);
60static void output_add_clobbers (void);
61static void output_added_clobbers_hard_reg_p (void);
62static void gen_rtx_scratch (rtx, enum rtx_code);
63static void output_peephole2_scratches (rtx);
e009aaf3 64
65963943
RK
65\f
66static void
3d7aafde 67print_code (RTX_CODE code)
65963943 68{
b3694847 69 const char *p1;
65963943 70 for (p1 = GET_RTX_NAME (code); *p1; p1++)
c3284718 71 putchar (TOUPPER (*p1));
65963943
RK
72}
73
ede7cd44 74static void
3d7aafde 75gen_rtx_scratch (rtx x, enum rtx_code subroutine_type)
ede7cd44
RH
76{
77 if (subroutine_type == DEFINE_PEEPHOLE2)
78 {
79 printf ("operand%d", XINT (x, 0));
80 }
81 else
82 {
83 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
84 }
85}
86
65963943
RK
87/* Print a C expression to construct an RTX just like X,
88 substituting any operand references appearing within. */
89
90static void
3d7aafde 91gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
65963943 92{
b3694847
SS
93 RTX_CODE code;
94 int i;
95 int len;
96 const char *fmt;
65963943
RK
97
98 if (x == 0)
99 {
3d678dca 100 printf ("NULL_RTX");
65963943
RK
101 return;
102 }
103
104 code = GET_CODE (x);
105
106 switch (code)
107 {
108 case MATCH_OPERAND:
109 case MATCH_DUP:
ab55f58c
RH
110 if (used)
111 {
112 if (used[XINT (x, 0)])
113 {
114 printf ("copy_rtx (operand%d)", XINT (x, 0));
115 return;
116 }
117 used[XINT (x, 0)] = 1;
118 }
65963943
RK
119 printf ("operand%d", XINT (x, 0));
120 return;
121
122 case MATCH_OP_DUP:
600555f5
KH
123 printf ("gen_rtx_fmt_");
124 for (i = 0; i < XVECLEN (x, 1); i++)
125 printf ("e");
126 printf (" (GET_CODE (operand%d), ", XINT (x, 0));
4ceb7595
JC
127 if (GET_MODE (x) == VOIDmode)
128 printf ("GET_MODE (operand%d)", XINT (x, 0));
129 else
130 printf ("%smode", GET_MODE_NAME (GET_MODE (x)));
65963943
RK
131 for (i = 0; i < XVECLEN (x, 1); i++)
132 {
133 printf (",\n\t\t");
ab55f58c 134 gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
65963943
RK
135 }
136 printf (")");
137 return;
138
139 case MATCH_OPERATOR:
600555f5
KH
140 printf ("gen_rtx_fmt_");
141 for (i = 0; i < XVECLEN (x, 2); i++)
142 printf ("e");
143 printf (" (GET_CODE (operand%d)", XINT (x, 0));
65963943
RK
144 printf (", %smode", GET_MODE_NAME (GET_MODE (x)));
145 for (i = 0; i < XVECLEN (x, 2); i++)
146 {
147 printf (",\n\t\t");
ab55f58c 148 gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
65963943
RK
149 }
150 printf (")");
151 return;
152
153 case MATCH_PARALLEL:
8fabbfe6 154 case MATCH_PAR_DUP:
65963943
RK
155 printf ("operand%d", XINT (x, 0));
156 return;
157
158 case MATCH_SCRATCH:
ede7cd44 159 gen_rtx_scratch (x, subroutine_type);
65963943
RK
160 return;
161
65963943
RK
162 case PC:
163 printf ("pc_rtx");
164 return;
3810076b
BS
165 case RETURN:
166 printf ("ret_rtx");
167 return;
26898771
BS
168 case SIMPLE_RETURN:
169 printf ("simple_return_rtx");
170 return;
3e89ed8d
JH
171 case CLOBBER:
172 if (REG_P (XEXP (x, 0)))
173 {
174 printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
175 REGNO (XEXP (x, 0)));
176 return;
177 }
178 break;
65963943
RK
179
180 case CC0:
181 printf ("cc0_rtx");
182 return;
183
184 case CONST_INT:
185 if (INTVAL (x) == 0)
3d678dca
RS
186 printf ("const0_rtx");
187 else if (INTVAL (x) == 1)
188 printf ("const1_rtx");
189 else if (INTVAL (x) == -1)
190 printf ("constm1_rtx");
11b635fe
KH
191 else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
192 && INTVAL (x) <= MAX_SAVED_CONST_INT)
193 printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
194 (int) INTVAL (x));
3d678dca
RS
195 else if (INTVAL (x) == STORE_FLAG_VALUE)
196 printf ("const_true_rtx");
197 else
76d31c63
JL
198 {
199 printf ("GEN_INT (");
bb9b3805 200 printf (HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
76d31c63
JL
201 printf (")");
202 }
3d678dca
RS
203 return;
204
205 case CONST_DOUBLE:
091a3ac7 206 case CONST_FIXED:
807e902e 207 case CONST_WIDE_INT:
3d678dca
RS
208 /* These shouldn't be written in MD files. Instead, the appropriate
209 routines in varasm.c should be called. */
b2d59f6f 210 gcc_unreachable ();
1d300e19
KG
211
212 default:
213 break;
65963943
RK
214 }
215
3b80f6ca 216 printf ("gen_rtx_");
65963943 217 print_code (code);
3b80f6ca 218 printf (" (%smode", GET_MODE_NAME (GET_MODE (x)));
65963943
RK
219
220 fmt = GET_RTX_FORMAT (code);
221 len = GET_RTX_LENGTH (code);
222 for (i = 0; i < len; i++)
223 {
224 if (fmt[i] == '0')
225 break;
a558d864 226 printf (",\n\t");
b2d59f6f 227 switch (fmt[i])
65963943 228 {
b2d59f6f
NS
229 case 'e': case 'u':
230 gen_exp (XEXP (x, i), subroutine_type, used);
231 break;
232
233 case 'i':
234 printf ("%u", XINT (x, i));
235 break;
236
237 case 's':
238 printf ("\"%s\"", XSTR (x, i));
239 break;
240
241 case 'E':
242 {
243 int j;
244 printf ("gen_rtvec (%d", XVECLEN (x, i));
245 for (j = 0; j < XVECLEN (x, i); j++)
246 {
247 printf (",\n\t\t");
248 gen_exp (XVECEXP (x, i, j), subroutine_type, used);
249 }
250 printf (")");
251 break;
252 }
253
254 default:
255 gcc_unreachable ();
65963943 256 }
65963943
RK
257 }
258 printf (")");
3d7aafde 259}
65963943
RK
260\f
261/* Generate the `gen_...' function for a DEFINE_INSN. */
262
263static void
3d7aafde 264gen_insn (rtx insn, int lineno)
65963943 265{
e792559a 266 struct pattern_stats stats;
b3694847 267 int i;
65963943
RK
268
269 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard)
270 registers or MATCH_SCRATCHes. If so, store away the information for
0f41302f 271 later. */
65963943
RK
272
273 if (XVEC (insn, 1))
274 {
751aa7cc
RK
275 int has_hard_reg = 0;
276
65963943 277 for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
751aa7cc
RK
278 {
279 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
280 break;
281
f8cfc6aa 282 if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
751aa7cc
RK
283 has_hard_reg = 1;
284 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH)
285 break;
286 }
65963943
RK
287
288 if (i != XVECLEN (insn, 1) - 1)
289 {
b3694847 290 struct clobber_pat *p;
5ed6ace5 291 struct clobber_ent *link = XNEW (struct clobber_ent);
b3694847 292 int j;
e5f6a288
RK
293
294 link->code_number = insn_code_number;
295
296 /* See if any previous CLOBBER_LIST entry is the same as this
297 one. */
298
299 for (p = clobber_list; p; p = p->next)
300 {
301 if (p->first_clobber != i + 1
302 || XVECLEN (p->pattern, 1) != XVECLEN (insn, 1))
303 continue;
304
305 for (j = i + 1; j < XVECLEN (insn, 1); j++)
306 {
8ad97cfc
KG
307 rtx old_rtx = XEXP (XVECEXP (p->pattern, 1, j), 0);
308 rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0);
e5f6a288 309
8ad97cfc 310 /* OLD and NEW_INSN are the same if both are to be a SCRATCH
3d7aafde 311 of the same mode,
e5f6a288 312 or if both are registers of the same mode and number. */
8ad97cfc
KG
313 if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
314 && ((GET_CODE (old_rtx) == MATCH_SCRATCH
315 && GET_CODE (new_rtx) == MATCH_SCRATCH)
316 || (REG_P (old_rtx) && REG_P (new_rtx)
317 && REGNO (old_rtx) == REGNO (new_rtx)))))
e5f6a288
RK
318 break;
319 }
3d7aafde 320
e5f6a288
RK
321 if (j == XVECLEN (insn, 1))
322 break;
323 }
324
325 if (p == 0)
326 {
5ed6ace5 327 p = XNEW (struct clobber_pat);
3d7aafde 328
e5f6a288
RK
329 p->insns = 0;
330 p->pattern = insn;
331 p->first_clobber = i + 1;
332 p->next = clobber_list;
751aa7cc 333 p->has_hard_reg = has_hard_reg;
e5f6a288
RK
334 clobber_list = p;
335 }
336
337 link->next = p->insns;
338 p->insns = link;
65963943
RK
339 }
340 }
341
6b6ca844
RK
342 /* Don't mention instructions whose names are the null string
343 or begin with '*'. They are in the machine description just
344 to be recognized. */
345 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*')
65963943
RK
346 return;
347
d2a3ce4e 348 printf ("/* %s:%d */\n", read_md_filename, lineno);
821e35ba 349
85a45cbb 350 /* Find out how many operands this function has. */
e792559a
RS
351 get_pattern_stats (&stats, XVEC (insn, 1));
352 if (stats.max_dup_opno > stats.max_opno)
65963943
RK
353 fatal ("match_dup operand number has no match_operand");
354
355 /* Output the function name and argument declarations. */
356 printf ("rtx\ngen_%s (", XSTR (insn, 0));
e792559a
RS
357 if (stats.num_generator_args)
358 for (i = 0; i < stats.num_generator_args; i++)
6906ba40
KG
359 if (i)
360 printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
361 else
362 printf ("rtx operand%d ATTRIBUTE_UNUSED", i);
363 else
364 printf ("void");
65963943 365 printf (")\n");
65963943
RK
366 printf ("{\n");
367
6614fd40 368 /* Output code to construct and return the rtl for the instruction body. */
65963943
RK
369
370 if (XVECLEN (insn, 1) == 1)
371 {
372 printf (" return ");
ab55f58c 373 gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL);
65963943
RK
374 printf (";\n}\n\n");
375 }
376 else
377 {
e792559a 378 char *used = XCNEWVEC (char, stats.num_generator_args);
329b3cc3 379
c5c76735
JL
380 printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d",
381 XVECLEN (insn, 1));
382
65963943
RK
383 for (i = 0; i < XVECLEN (insn, 1); i++)
384 {
385 printf (",\n\t\t");
329b3cc3 386 gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used);
65963943
RK
387 }
388 printf ("));\n}\n\n");
329b3cc3 389 XDELETEVEC (used);
65963943
RK
390 }
391}
392\f
393/* Generate the `gen_...' function for a DEFINE_EXPAND. */
394
395static void
3d7aafde 396gen_expand (rtx expand)
65963943 397{
e792559a 398 struct pattern_stats stats;
b3694847 399 int i;
329b3cc3 400 char *used;
65963943
RK
401
402 if (strlen (XSTR (expand, 0)) == 0)
403 fatal ("define_expand lacks a name");
404 if (XVEC (expand, 1) == 0)
405 fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0));
406
85a45cbb 407 /* Find out how many operands this function has. */
e792559a 408 get_pattern_stats (&stats, XVEC (expand, 1));
65963943
RK
409
410 /* Output the function name and argument declarations. */
411 printf ("rtx\ngen_%s (", XSTR (expand, 0));
e792559a
RS
412 if (stats.num_generator_args)
413 for (i = 0; i < stats.num_generator_args; i++)
6906ba40
KG
414 if (i)
415 printf (",\n\trtx operand%d", i);
416 else
417 printf ("rtx operand%d", i);
418 else
419 printf ("void");
65963943 420 printf (")\n");
65963943
RK
421 printf ("{\n");
422
423 /* If we don't have any C code to write, only one insn is being written,
424 and no MATCH_DUPs are present, we can just return the desired insn
425 like we do for a DEFINE_INSN. This saves memory. */
426 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0')
e792559a 427 && stats.max_opno >= stats.max_dup_opno
65963943
RK
428 && XVECLEN (expand, 1) == 1)
429 {
430 printf (" return ");
ab55f58c 431 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
65963943
RK
432 printf (";\n}\n\n");
433 return;
434 }
435
436 /* For each operand referred to only with MATCH_DUPs,
437 make a local variable. */
e792559a 438 for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
65963943 439 printf (" rtx operand%d;\n", i);
e792559a 440 for (; i <= stats.max_scratch_opno; i++)
b3656137 441 printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i);
65963943
RK
442 printf (" rtx _val = 0;\n");
443 printf (" start_sequence ();\n");
444
445 /* The fourth operand of DEFINE_EXPAND is some code to be executed
446 before the actual construction.
447 This code expects to refer to `operands'
448 just as the output-code in a DEFINE_INSN does,
449 but here `operands' is an automatic array.
450 So copy the operand values there before executing it. */
451 if (XSTR (expand, 3) && *XSTR (expand, 3))
452 {
e2bef702 453 printf (" {\n");
e792559a
RS
454 if (stats.num_operand_vars > 0)
455 printf (" rtx operands[%d];\n", stats.num_operand_vars);
456
65963943 457 /* Output code to copy the arguments into `operands'. */
e792559a 458 for (i = 0; i < stats.num_generator_args; i++)
e2bef702 459 printf (" operands[%d] = operand%d;\n", i, i);
65963943
RK
460
461 /* Output the special code to be executed before the sequence
462 is generated. */
d2a3ce4e 463 print_md_ptr_loc (XSTR (expand, 3));
65963943
RK
464 printf ("%s\n", XSTR (expand, 3));
465
466 /* Output code to copy the arguments back out of `operands'
467 (unless we aren't going to use them at all). */
468 if (XVEC (expand, 1) != 0)
469 {
e792559a 470 for (i = 0; i < stats.num_operand_vars; i++)
60d3aec4
JJ
471 {
472 printf (" operand%d = operands[%d];\n", i, i);
473 printf (" (void) operand%d;\n", i);
474 }
65963943 475 }
e2bef702 476 printf (" }\n");
65963943
RK
477 }
478
479 /* Output code to construct the rtl for the instruction bodies.
480 Use emit_insn to add them to the sequence being accumulated.
481 But don't do this if the user's code has set `no_more' nonzero. */
482
e792559a 483 used = XCNEWVEC (char, stats.num_operand_vars);
329b3cc3 484
65963943
RK
485 for (i = 0; i < XVECLEN (expand, 1); i++)
486 {
487 rtx next = XVECEXP (expand, 1, i);
488 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
489 || (GET_CODE (next) == PARALLEL
79cbc1f7
BS
490 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET
491 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
26898771
BS
492 || ANY_RETURN_P (XVECEXP (next, 0, 0))))
493 || ANY_RETURN_P (next))
65963943
RK
494 printf (" emit_jump_insn (");
495 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
496 || GET_CODE (next) == CALL
497 || (GET_CODE (next) == PARALLEL
498 && GET_CODE (XVECEXP (next, 0, 0)) == SET
499 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
500 || (GET_CODE (next) == PARALLEL
501 && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
502 printf (" emit_call_insn (");
4b4bf941 503 else if (LABEL_P (next))
65963943
RK
504 printf (" emit_label (");
505 else if (GET_CODE (next) == MATCH_OPERAND
d3ca5cdd 506 || GET_CODE (next) == MATCH_DUP
65963943 507 || GET_CODE (next) == MATCH_OPERATOR
65963943 508 || GET_CODE (next) == MATCH_OP_DUP
d3ca5cdd
JW
509 || GET_CODE (next) == MATCH_PARALLEL
510 || GET_CODE (next) == MATCH_PAR_DUP
65963943
RK
511 || GET_CODE (next) == PARALLEL)
512 printf (" emit (");
513 else
514 printf (" emit_insn (");
329b3cc3 515 gen_exp (next, DEFINE_EXPAND, used);
65963943
RK
516 printf (");\n");
517 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
518 && GET_CODE (SET_SRC (next)) == LABEL_REF)
519 printf (" emit_barrier ();");
520 }
521
329b3cc3
KK
522 XDELETEVEC (used);
523
2f937369 524 /* Call `get_insns' to extract the list of all the
65963943
RK
525 insns emitted within this gen_... function. */
526
2f937369 527 printf (" _val = get_insns ();\n");
65963943
RK
528 printf (" end_sequence ();\n");
529 printf (" return _val;\n}\n\n");
530}
531
2f937369 532/* Like gen_expand, but generates insns resulting from splitting SPLIT. */
0f41302f 533
65963943 534static void
3d7aafde 535gen_split (rtx split)
65963943 536{
e792559a 537 struct pattern_stats stats;
b3694847 538 int i;
27c38fbe
KG
539 const char *const name =
540 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
751aa7cc 541 const char *unused;
ab55f58c 542 char *used;
ede7cd44 543
65963943 544 if (XVEC (split, 0) == 0)
ede7cd44
RH
545 fatal ("define_%s (definition %d) lacks a pattern", name,
546 insn_index_number);
65963943 547 else if (XVEC (split, 2) == 0)
ede7cd44 548 fatal ("define_%s (definition %d) lacks a replacement pattern", name,
3462dc45 549 insn_index_number);
65963943
RK
550
551 /* Find out how many operands this function has. */
552
e792559a
RS
553 get_pattern_stats (&stats, XVEC (split, 2));
554 unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
555 used = XCNEWVEC (char, stats.num_operand_vars);
65963943 556
ede7cd44
RH
557 /* Output the prototype, function name and argument declarations. */
558 if (GET_CODE (split) == DEFINE_PEEPHOLE2)
559 {
95770ca3 560 printf ("extern rtx gen_%s_%d (rtx_insn *, rtx *);\n",
ede7cd44 561 name, insn_code_number);
95770ca3 562 printf ("rtx\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
0641776c 563 name, insn_code_number, unused);
ede7cd44
RH
564 }
565 else
566 {
95770ca3
DM
567 printf ("extern rtx gen_split_%d (rtx_insn *, rtx *);\n", insn_code_number);
568 printf ("rtx\ngen_split_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n",
a406f566 569 insn_code_number, unused);
ede7cd44 570 }
65963943
RK
571 printf ("{\n");
572
573 /* Declare all local variables. */
e792559a 574 for (i = 0; i < stats.num_operand_vars; i++)
65963943 575 printf (" rtx operand%d;\n", i);
91afd8f5 576 printf (" rtx _val = 0;\n");
ede7cd44
RH
577
578 if (GET_CODE (split) == DEFINE_PEEPHOLE2)
579 output_peephole2_scratches (split);
580
65963943
RK
581 printf (" start_sequence ();\n");
582
583 /* The fourth operand of DEFINE_SPLIT is some code to be executed
584 before the actual construction. */
585
586 if (XSTR (split, 3))
7445392c 587 {
d2a3ce4e 588 print_md_ptr_loc (XSTR (split, 3));
7445392c
RS
589 printf ("%s\n", XSTR (split, 3));
590 }
65963943
RK
591
592 /* Output code to copy the arguments back out of `operands' */
e792559a 593 for (i = 0; i < stats.num_operand_vars; i++)
60d3aec4
JJ
594 {
595 printf (" operand%d = operands[%d];\n", i, i);
596 printf (" (void) operand%d;\n", i);
597 }
65963943
RK
598
599 /* Output code to construct the rtl for the instruction bodies.
600 Use emit_insn to add them to the sequence being accumulated.
601 But don't do this if the user's code has set `no_more' nonzero. */
602
603 for (i = 0; i < XVECLEN (split, 2); i++)
604 {
605 rtx next = XVECEXP (split, 2, i);
606 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC)
607 || (GET_CODE (next) == PARALLEL
608 && GET_CODE (XVECEXP (next, 0, 0)) == SET
609 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC)
26898771 610 || ANY_RETURN_P (next))
65963943
RK
611 printf (" emit_jump_insn (");
612 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL)
613 || GET_CODE (next) == CALL
614 || (GET_CODE (next) == PARALLEL
615 && GET_CODE (XVECEXP (next, 0, 0)) == SET
616 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL)
617 || (GET_CODE (next) == PARALLEL
618 && GET_CODE (XVECEXP (next, 0, 0)) == CALL))
619 printf (" emit_call_insn (");
4b4bf941 620 else if (LABEL_P (next))
65963943
RK
621 printf (" emit_label (");
622 else if (GET_CODE (next) == MATCH_OPERAND
623 || GET_CODE (next) == MATCH_OPERATOR
624 || GET_CODE (next) == MATCH_PARALLEL
625 || GET_CODE (next) == MATCH_OP_DUP
626 || GET_CODE (next) == MATCH_DUP
627 || GET_CODE (next) == PARALLEL)
628 printf (" emit (");
629 else
630 printf (" emit_insn (");
ab55f58c 631 gen_exp (next, GET_CODE (split), used);
65963943
RK
632 printf (");\n");
633 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC
634 && GET_CODE (SET_SRC (next)) == LABEL_REF)
635 printf (" emit_barrier ();");
636 }
637
2f937369 638 /* Call `get_insns' to make a list of all the
65963943
RK
639 insns emitted within this gen_... function. */
640
2f937369 641 printf (" _val = get_insns ();\n");
65963943
RK
642 printf (" end_sequence ();\n");
643 printf (" return _val;\n}\n\n");
ab55f58c
RH
644
645 free (used);
65963943
RK
646}
647\f
648/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient
649 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at
650 the end of the vector. */
651
652static void
7e51717c 653output_add_clobbers (void)
65963943
RK
654{
655 struct clobber_pat *clobber;
e5f6a288 656 struct clobber_ent *ent;
65963943
RK
657 int i;
658
6906ba40 659 printf ("\n\nvoid\nadd_clobbers (rtx pattern ATTRIBUTE_UNUSED, int insn_code_number)\n");
65963943 660 printf ("{\n");
65963943
RK
661 printf (" switch (insn_code_number)\n");
662 printf (" {\n");
663
664 for (clobber = clobber_list; clobber; clobber = clobber->next)
665 {
e5f6a288
RK
666 for (ent = clobber->insns; ent; ent = ent->next)
667 printf (" case %d:\n", ent->code_number);
65963943
RK
668
669 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++)
670 {
671 printf (" XVECEXP (pattern, 0, %d) = ", i);
ede7cd44 672 gen_exp (XVECEXP (clobber->pattern, 1, i),
ab55f58c 673 GET_CODE (clobber->pattern), NULL);
65963943
RK
674 printf (";\n");
675 }
676
e5f6a288 677 printf (" break;\n\n");
65963943
RK
678 }
679
680 printf (" default:\n");
b2d59f6f 681 printf (" gcc_unreachable ();\n");
65963943
RK
682 printf (" }\n");
683 printf ("}\n");
684}
685\f
6327d36a
RK
686/* Write a function, `added_clobbers_hard_reg_p' that is given an insn_code
687 number that will have clobbers added (as indicated by `recog') and returns
688 1 if those include a clobber of a hard reg or 0 if all of them just clobber
689 SCRATCH. */
751aa7cc
RK
690
691static void
3d7aafde 692output_added_clobbers_hard_reg_p (void)
751aa7cc
RK
693{
694 struct clobber_pat *clobber;
695 struct clobber_ent *ent;
a29b099d 696 int clobber_p, used;
751aa7cc 697
6906ba40 698 printf ("\n\nint\nadded_clobbers_hard_reg_p (int insn_code_number)\n");
751aa7cc
RK
699 printf ("{\n");
700 printf (" switch (insn_code_number)\n");
701 printf (" {\n");
702
703 for (clobber_p = 0; clobber_p <= 1; clobber_p++)
704 {
a29b099d 705 used = 0;
751aa7cc
RK
706 for (clobber = clobber_list; clobber; clobber = clobber->next)
707 if (clobber->has_hard_reg == clobber_p)
708 for (ent = clobber->insns; ent; ent = ent->next)
a29b099d
JJ
709 {
710 printf (" case %d:\n", ent->code_number);
711 used++;
712 }
751aa7cc 713
a29b099d
JJ
714 if (used)
715 printf (" return %d;\n\n", clobber_p);
751aa7cc
RK
716 }
717
718 printf (" default:\n");
b2d59f6f 719 printf (" gcc_unreachable ();\n");
751aa7cc
RK
720 printf (" }\n");
721 printf ("}\n");
722}
723\f
ede7cd44 724/* Generate code to invoke find_free_register () as needed for the
dc297297 725 scratch registers used by the peephole2 pattern in SPLIT. */
ede7cd44
RH
726
727static void
3d7aafde 728output_peephole2_scratches (rtx split)
ede7cd44
RH
729{
730 int i;
731 int insn_nr = 0;
f1ed99cd 732 bool first = true;
ede7cd44
RH
733
734 for (i = 0; i < XVECLEN (split, 0); i++)
735 {
736 rtx elt = XVECEXP (split, 0, i);
737 if (GET_CODE (elt) == MATCH_SCRATCH)
738 {
739 int last_insn_nr = insn_nr;
740 int cur_insn_nr = insn_nr;
741 int j;
742 for (j = i + 1; j < XVECLEN (split, 0); j++)
743 if (GET_CODE (XVECEXP (split, 0, j)) == MATCH_DUP)
744 {
745 if (XINT (XVECEXP (split, 0, j), 0) == XINT (elt, 0))
746 last_insn_nr = cur_insn_nr;
747 }
748 else if (GET_CODE (XVECEXP (split, 0, j)) != MATCH_SCRATCH)
749 cur_insn_nr++;
23280139 750
f1ed99cd
JJ
751 if (first)
752 {
753 printf (" HARD_REG_SET _regs_allocated;\n");
754 printf (" CLEAR_HARD_REG_SET (_regs_allocated);\n");
755 first = false;
756 }
757
23280139 758 printf (" if ((operands[%d] = peep2_find_free_register (%d, %d, \"%s\", %smode, &_regs_allocated)) == NULL_RTX)\n\
3d7aafde 759 return NULL;\n",
ede7cd44 760 XINT (elt, 0),
23280139 761 insn_nr, last_insn_nr,
ede7cd44
RH
762 XSTR (elt, 1),
763 GET_MODE_NAME (GET_MODE (elt)));
764
765 }
766 else if (GET_CODE (elt) != MATCH_DUP)
767 insn_nr++;
768 }
769}
65963943 770
65963943 771int
3d7aafde 772main (int argc, char **argv)
65963943
RK
773{
774 rtx desc;
65963943 775
f8b6598e 776 progname = "genemit";
65963943 777
600ab3fc 778 if (!init_rtx_reader_args (argc, argv))
c88c0d42 779 return (FATAL_EXIT_CODE);
65963943 780
65963943
RK
781 /* Assign sequential codes to all entries in the machine description
782 in parallel with the tables in insn-output.c. */
783
784 insn_code_number = 0;
785 insn_index_number = 0;
786
787 printf ("/* Generated automatically by the program `genemit'\n\
788from the machine description file `md'. */\n\n");
789
790 printf ("#include \"config.h\"\n");
729da3f5 791 printf ("#include \"system.h\"\n");
4977bab6
ZW
792 printf ("#include \"coretypes.h\"\n");
793 printf ("#include \"tm.h\"\n");
4d648807 794 printf ("#include \"tree.h\"\n");
d8a2d370
DN
795 printf ("#include \"varasm.h\"\n");
796 printf ("#include \"stor-layout.h\"\n");
797 printf ("#include \"calls.h\"\n");
65963943 798 printf ("#include \"rtl.h\"\n");
6baf1cc8 799 printf ("#include \"tm_p.h\"\n");
49ad7cfa 800 printf ("#include \"function.h\"\n");
65963943 801 printf ("#include \"expr.h\"\n");
e78d8e51 802 printf ("#include \"optabs.h\"\n");
c413e1b5 803 printf ("#include \"dfp.h\"\n");
1d300e19 804 printf ("#include \"flags.h\"\n");
65963943 805 printf ("#include \"output.h\"\n");
7f7f8214 806 printf ("#include \"insn-config.h\"\n");
ede7cd44 807 printf ("#include \"hard-reg-set.h\"\n");
23280139 808 printf ("#include \"recog.h\"\n");
ede7cd44 809 printf ("#include \"resource.h\"\n");
d80eb1e1 810 printf ("#include \"reload.h\"\n");
79a3f089 811 printf ("#include \"diagnostic-core.h\"\n");
5abc5de9 812 printf ("#include \"regs.h\"\n");
279bb624 813 printf ("#include \"tm-constrs.h\"\n");
5abc5de9
EC
814 printf ("#include \"ggc.h\"\n");
815 printf ("#include \"basic-block.h\"\n");
3b1552c1 816 printf ("#include \"target.h\"\n\n");
53bfe9cd 817 printf ("#define FAIL return (end_sequence (), _val)\n");
2f937369 818 printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
65963943
RK
819
820 /* Read the machine description. */
821
822 while (1)
823 {
c88c0d42 824 int line_no;
65963943 825
c88c0d42
CP
826 desc = read_md_rtx (&line_no, &insn_code_number);
827 if (desc == NULL)
828 break;
ede7cd44 829
c88c0d42 830 switch (GET_CODE (desc))
65963943 831 {
821e35ba
RH
832 case DEFINE_INSN:
833 gen_insn (desc, line_no);
834 break;
835
836 case DEFINE_EXPAND:
d2a3ce4e 837 printf ("/* %s:%d */\n", read_md_filename, line_no);
821e35ba
RH
838 gen_expand (desc);
839 break;
840
841 case DEFINE_SPLIT:
d2a3ce4e 842 printf ("/* %s:%d */\n", read_md_filename, line_no);
821e35ba
RH
843 gen_split (desc);
844 break;
845
846 case DEFINE_PEEPHOLE2:
d2a3ce4e 847 printf ("/* %s:%d */\n", read_md_filename, line_no);
821e35ba
RH
848 gen_split (desc);
849 break;
850
851 default:
852 break;
853 }
65963943
RK
854 ++insn_index_number;
855 }
856
751aa7cc
RK
857 /* Write out the routines to add CLOBBERs to a pattern and say whether they
858 clobber a hard reg. */
65963943 859 output_add_clobbers ();
751aa7cc 860 output_added_clobbers_hard_reg_p ();
65963943 861
65963943 862 fflush (stdout);
c1b59dce 863 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
65963943 864}