Mercurial > hg > CbC > GCC_original
comparison gcc/genemit.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
15:561a7518be6b | 16:04ced10e8804 |
---|---|
1 /* Generate code from machine description to emit insns as rtl. | 1 /* Generate code from machine description to emit insns as rtl. |
2 Copyright (C) 1987, 1988, 1991, 1994, 1995, 1997, 1998, 1999, 2000, 2001, | 2 Copyright (C) 1987-2017 Free Software Foundation, Inc. |
3 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. | |
4 | 3 |
5 This file is part of GCC. | 4 This file is part of GCC. |
6 | 5 |
7 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
8 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
27 #include "errors.h" | 26 #include "errors.h" |
28 #include "read-md.h" | 27 #include "read-md.h" |
29 #include "gensupport.h" | 28 #include "gensupport.h" |
30 | 29 |
31 | 30 |
32 static int max_opno; | |
33 static int max_dup_opno; | |
34 static int max_scratch_opno; | |
35 static int insn_code_number; | |
36 static int insn_index_number; | |
37 | |
38 /* Data structure for recording the patterns of insns that have CLOBBERs. | 31 /* Data structure for recording the patterns of insns that have CLOBBERs. |
39 We use this to output a function that adds these CLOBBERs to a | 32 We use this to output a function that adds these CLOBBERs to a |
40 previously-allocated PARALLEL expression. */ | 33 previously-allocated PARALLEL expression. */ |
41 | 34 |
42 struct clobber_pat | 35 struct clobber_pat |
54 { | 47 { |
55 int code_number; /* Counts only insns. */ | 48 int code_number; /* Counts only insns. */ |
56 struct clobber_ent *next; | 49 struct clobber_ent *next; |
57 }; | 50 }; |
58 | 51 |
59 static void max_operand_1 (rtx); | |
60 static int max_operand_vec (rtx, int); | |
61 static void print_code (RTX_CODE); | |
62 static void gen_exp (rtx, enum rtx_code, char *); | |
63 static void gen_insn (rtx, int); | |
64 static void gen_expand (rtx); | |
65 static void gen_split (rtx); | |
66 static void output_add_clobbers (void); | |
67 static void output_added_clobbers_hard_reg_p (void); | |
68 static void gen_rtx_scratch (rtx, enum rtx_code); | |
69 static void output_peephole2_scratches (rtx); | 52 static void output_peephole2_scratches (rtx); |
70 | 53 |
54 /* True for <X>_optab if that optab isn't allowed to fail. */ | |
55 static bool nofail_optabs[NUM_OPTABS]; | |
71 | 56 |
72 static void | 57 static void |
73 max_operand_1 (rtx x) | 58 print_code (RTX_CODE code) |
59 { | |
60 const char *p1; | |
61 for (p1 = GET_RTX_NAME (code); *p1; p1++) | |
62 putchar (TOUPPER (*p1)); | |
63 } | |
64 | |
65 static void | |
66 gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) | |
67 { | |
68 if (subroutine_type == DEFINE_PEEPHOLE2) | |
69 { | |
70 printf ("operand%d", XINT (x, 0)); | |
71 } | |
72 else | |
73 { | |
74 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); | |
75 } | |
76 } | |
77 | |
78 /* Print a C expression to construct an RTX just like X, | |
79 substituting any operand references appearing within. */ | |
80 | |
81 static void | |
82 gen_exp (rtx x, enum rtx_code subroutine_type, char *used) | |
74 { | 83 { |
75 RTX_CODE code; | 84 RTX_CODE code; |
76 int i; | 85 int i; |
77 int len; | 86 int len; |
78 const char *fmt; | 87 const char *fmt; |
79 | 88 const char *sep = ""; |
80 if (x == 0) | |
81 return; | |
82 | |
83 code = GET_CODE (x); | |
84 | |
85 if (code == MATCH_OPERAND || code == MATCH_OPERATOR | |
86 || code == MATCH_PARALLEL) | |
87 max_opno = MAX (max_opno, XINT (x, 0)); | |
88 if (code == MATCH_DUP || code == MATCH_OP_DUP || code == MATCH_PAR_DUP) | |
89 max_dup_opno = MAX (max_dup_opno, XINT (x, 0)); | |
90 if (code == MATCH_SCRATCH) | |
91 max_scratch_opno = MAX (max_scratch_opno, XINT (x, 0)); | |
92 | |
93 fmt = GET_RTX_FORMAT (code); | |
94 len = GET_RTX_LENGTH (code); | |
95 for (i = 0; i < len; i++) | |
96 { | |
97 if (fmt[i] == 'e' || fmt[i] == 'u') | |
98 max_operand_1 (XEXP (x, i)); | |
99 else if (fmt[i] == 'E') | |
100 { | |
101 int j; | |
102 for (j = 0; j < XVECLEN (x, i); j++) | |
103 max_operand_1 (XVECEXP (x, i, j)); | |
104 } | |
105 } | |
106 } | |
107 | |
108 static int | |
109 max_operand_vec (rtx insn, int arg) | |
110 { | |
111 int len = XVECLEN (insn, arg); | |
112 int i; | |
113 | |
114 max_opno = -1; | |
115 max_dup_opno = -1; | |
116 max_scratch_opno = -1; | |
117 | |
118 for (i = 0; i < len; i++) | |
119 max_operand_1 (XVECEXP (insn, arg, i)); | |
120 | |
121 return max_opno + 1; | |
122 } | |
123 | |
124 static void | |
125 print_code (RTX_CODE code) | |
126 { | |
127 const char *p1; | |
128 for (p1 = GET_RTX_NAME (code); *p1; p1++) | |
129 putchar (TOUPPER(*p1)); | |
130 } | |
131 | |
132 static void | |
133 gen_rtx_scratch (rtx x, enum rtx_code subroutine_type) | |
134 { | |
135 if (subroutine_type == DEFINE_PEEPHOLE2) | |
136 { | |
137 printf ("operand%d", XINT (x, 0)); | |
138 } | |
139 else | |
140 { | |
141 printf ("gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x))); | |
142 } | |
143 } | |
144 | |
145 /* Print a C expression to construct an RTX just like X, | |
146 substituting any operand references appearing within. */ | |
147 | |
148 static void | |
149 gen_exp (rtx x, enum rtx_code subroutine_type, char *used) | |
150 { | |
151 RTX_CODE code; | |
152 int i; | |
153 int len; | |
154 const char *fmt; | |
155 | 89 |
156 if (x == 0) | 90 if (x == 0) |
157 { | 91 { |
158 printf ("NULL_RTX"); | 92 printf ("NULL_RTX"); |
159 return; | 93 return; |
215 | 149 |
216 case MATCH_SCRATCH: | 150 case MATCH_SCRATCH: |
217 gen_rtx_scratch (x, subroutine_type); | 151 gen_rtx_scratch (x, subroutine_type); |
218 return; | 152 return; |
219 | 153 |
220 case ADDRESS: | |
221 fatal ("ADDRESS expression code used in named instruction pattern"); | |
222 | |
223 case PC: | 154 case PC: |
224 printf ("pc_rtx"); | 155 printf ("pc_rtx"); |
156 return; | |
157 case RETURN: | |
158 printf ("ret_rtx"); | |
159 return; | |
160 case SIMPLE_RETURN: | |
161 printf ("simple_return_rtx"); | |
225 return; | 162 return; |
226 case CLOBBER: | 163 case CLOBBER: |
227 if (REG_P (XEXP (x, 0))) | 164 if (REG_P (XEXP (x, 0))) |
228 { | 165 { |
229 printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))), | 166 printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))), |
242 else if (INTVAL (x) == 1) | 179 else if (INTVAL (x) == 1) |
243 printf ("const1_rtx"); | 180 printf ("const1_rtx"); |
244 else if (INTVAL (x) == -1) | 181 else if (INTVAL (x) == -1) |
245 printf ("constm1_rtx"); | 182 printf ("constm1_rtx"); |
246 else if (-MAX_SAVED_CONST_INT <= INTVAL (x) | 183 else if (-MAX_SAVED_CONST_INT <= INTVAL (x) |
247 && INTVAL (x) <= MAX_SAVED_CONST_INT) | 184 && INTVAL (x) <= MAX_SAVED_CONST_INT) |
248 printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", | 185 printf ("const_int_rtx[MAX_SAVED_CONST_INT + (%d)]", |
249 (int) INTVAL (x)); | 186 (int) INTVAL (x)); |
250 else if (INTVAL (x) == STORE_FLAG_VALUE) | 187 else if (INTVAL (x) == STORE_FLAG_VALUE) |
251 printf ("const_true_rtx"); | 188 printf ("const_true_rtx"); |
252 else | 189 else |
257 } | 194 } |
258 return; | 195 return; |
259 | 196 |
260 case CONST_DOUBLE: | 197 case CONST_DOUBLE: |
261 case CONST_FIXED: | 198 case CONST_FIXED: |
199 case CONST_WIDE_INT: | |
262 /* These shouldn't be written in MD files. Instead, the appropriate | 200 /* These shouldn't be written in MD files. Instead, the appropriate |
263 routines in varasm.c should be called. */ | 201 routines in varasm.c should be called. */ |
264 gcc_unreachable (); | 202 gcc_unreachable (); |
265 | 203 |
266 default: | 204 default: |
267 break; | 205 break; |
268 } | 206 } |
269 | 207 |
270 printf ("gen_rtx_"); | 208 printf ("gen_rtx_"); |
271 print_code (code); | 209 print_code (code); |
272 printf (" (%smode", GET_MODE_NAME (GET_MODE (x))); | 210 printf (" ("); |
211 if (!always_void_p (code)) | |
212 { | |
213 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); | |
214 sep = ",\n\t"; | |
215 } | |
273 | 216 |
274 fmt = GET_RTX_FORMAT (code); | 217 fmt = GET_RTX_FORMAT (code); |
275 len = GET_RTX_LENGTH (code); | 218 len = GET_RTX_LENGTH (code); |
276 for (i = 0; i < len; i++) | 219 for (i = 0; i < len; i++) |
277 { | 220 { |
278 if (fmt[i] == '0') | 221 if (fmt[i] == '0') |
279 break; | 222 break; |
280 printf (",\n\t"); | 223 fputs (sep, stdout); |
281 switch (fmt[i]) | 224 switch (fmt[i]) |
282 { | 225 { |
283 case 'e': case 'u': | 226 case 'e': case 'u': |
284 gen_exp (XEXP (x, i), subroutine_type, used); | 227 gen_exp (XEXP (x, i), subroutine_type, used); |
285 break; | 228 break; |
286 | 229 |
287 case 'i': | 230 case 'i': |
288 printf ("%u", XINT (x, i)); | 231 printf ("%u", XINT (x, i)); |
232 break; | |
233 | |
234 case 'r': | |
235 printf ("%u", REGNO (x)); | |
289 break; | 236 break; |
290 | 237 |
291 case 's': | 238 case 's': |
292 printf ("\"%s\"", XSTR (x, i)); | 239 printf ("\"%s\"", XSTR (x, i)); |
293 break; | 240 break; |
306 } | 253 } |
307 | 254 |
308 default: | 255 default: |
309 gcc_unreachable (); | 256 gcc_unreachable (); |
310 } | 257 } |
258 sep = ",\n\t"; | |
311 } | 259 } |
312 printf (")"); | 260 printf (")"); |
261 } | |
262 | |
263 /* Output code to emit the instruction patterns in VEC, with each element | |
264 becoming a separate instruction. USED is as for gen_exp. */ | |
265 | |
266 static void | |
267 gen_emit_seq (rtvec vec, char *used) | |
268 { | |
269 for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) | |
270 { | |
271 bool last_p = (i == len - 1); | |
272 rtx next = RTVEC_ELT (vec, i); | |
273 if (const char *name = get_emit_function (next)) | |
274 { | |
275 printf (" %s (", name); | |
276 gen_exp (next, DEFINE_EXPAND, used); | |
277 printf (");\n"); | |
278 if (!last_p && needs_barrier_p (next)) | |
279 printf (" emit_barrier ();"); | |
280 } | |
281 else | |
282 { | |
283 printf (" emit ("); | |
284 gen_exp (next, DEFINE_EXPAND, used); | |
285 printf (", %s);\n", last_p ? "false" : "true"); | |
286 } | |
287 } | |
288 } | |
289 | |
290 /* Emit the given C code to the output file. The code is allowed to | |
291 fail if CAN_FAIL_P. NAME describes what we're generating, | |
292 for use in error messages. */ | |
293 | |
294 static void | |
295 emit_c_code (const char *code, bool can_fail_p, const char *name) | |
296 { | |
297 if (can_fail_p) | |
298 printf ("#define FAIL return (end_sequence (), _val)\n"); | |
299 else | |
300 printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")" | |
301 " (void)0\n", name); | |
302 printf ("#define DONE return (_val = get_insns ()," | |
303 "end_sequence (), _val)\n"); | |
304 | |
305 rtx_reader_ptr->print_md_ptr_loc (code); | |
306 printf ("%s\n", code); | |
307 | |
308 printf ("#undef DONE\n"); | |
309 printf ("#undef FAIL\n"); | |
313 } | 310 } |
314 | 311 |
315 /* Generate the `gen_...' function for a DEFINE_INSN. */ | 312 /* Generate the `gen_...' function for a DEFINE_INSN. */ |
316 | 313 |
317 static void | 314 static void |
318 gen_insn (rtx insn, int lineno) | 315 gen_insn (md_rtx_info *info) |
319 { | 316 { |
320 int operands; | 317 struct pattern_stats stats; |
321 int i; | 318 int i; |
322 | 319 |
323 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) | 320 /* See if the pattern for this insn ends with a group of CLOBBERs of (hard) |
324 registers or MATCH_SCRATCHes. If so, store away the information for | 321 registers or MATCH_SCRATCHes. If so, store away the information for |
325 later. */ | 322 later. */ |
326 | 323 |
324 rtx insn = info->def; | |
327 if (XVEC (insn, 1)) | 325 if (XVEC (insn, 1)) |
328 { | 326 { |
329 int has_hard_reg = 0; | 327 int has_hard_reg = 0; |
330 | 328 |
331 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) | 329 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) |
343 { | 341 { |
344 struct clobber_pat *p; | 342 struct clobber_pat *p; |
345 struct clobber_ent *link = XNEW (struct clobber_ent); | 343 struct clobber_ent *link = XNEW (struct clobber_ent); |
346 int j; | 344 int j; |
347 | 345 |
348 link->code_number = insn_code_number; | 346 link->code_number = info->index; |
349 | 347 |
350 /* See if any previous CLOBBER_LIST entry is the same as this | 348 /* See if any previous CLOBBER_LIST entry is the same as this |
351 one. */ | 349 one. */ |
352 | 350 |
353 for (p = clobber_list; p; p = p->next) | 351 for (p = clobber_list; p; p = p->next) |
397 or begin with '*'. They are in the machine description just | 395 or begin with '*'. They are in the machine description just |
398 to be recognized. */ | 396 to be recognized. */ |
399 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') | 397 if (XSTR (insn, 0)[0] == 0 || XSTR (insn, 0)[0] == '*') |
400 return; | 398 return; |
401 | 399 |
402 printf ("/* %s:%d */\n", read_md_filename, lineno); | 400 printf ("/* %s:%d */\n", info->loc.filename, info->loc.lineno); |
403 | 401 |
404 /* Find out how many operands this function has. */ | 402 /* Find out how many operands this function has. */ |
405 operands = max_operand_vec (insn, 1); | 403 get_pattern_stats (&stats, XVEC (insn, 1)); |
406 if (max_dup_opno >= operands) | 404 if (stats.max_dup_opno > stats.max_opno) |
407 fatal ("match_dup operand number has no match_operand"); | 405 fatal_at (info->loc, "match_dup operand number has no match_operand"); |
408 | 406 |
409 /* Output the function name and argument declarations. */ | 407 /* Output the function name and argument declarations. */ |
410 printf ("rtx\ngen_%s (", XSTR (insn, 0)); | 408 printf ("rtx\ngen_%s (", XSTR (insn, 0)); |
411 if (operands) | 409 if (stats.num_generator_args) |
412 for (i = 0; i < operands; i++) | 410 for (i = 0; i < stats.num_generator_args; i++) |
413 if (i) | 411 if (i) |
414 printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); | 412 printf (",\n\trtx operand%d ATTRIBUTE_UNUSED", i); |
415 else | 413 else |
416 printf ("rtx operand%d ATTRIBUTE_UNUSED", i); | 414 printf ("rtx operand%d ATTRIBUTE_UNUSED", i); |
417 else | 415 else |
419 printf (")\n"); | 417 printf (")\n"); |
420 printf ("{\n"); | 418 printf ("{\n"); |
421 | 419 |
422 /* Output code to construct and return the rtl for the instruction body. */ | 420 /* Output code to construct and return the rtl for the instruction body. */ |
423 | 421 |
424 if (XVECLEN (insn, 1) == 1) | 422 rtx pattern = add_implicit_parallel (XVEC (insn, 1)); |
425 { | 423 /* ??? This is the traditional behavior, but seems suspect. */ |
426 printf (" return "); | 424 char *used = (XVECLEN (insn, 1) == 1 |
427 gen_exp (XVECEXP (insn, 1, 0), DEFINE_INSN, NULL); | 425 ? NULL |
428 printf (";\n}\n\n"); | 426 : XCNEWVEC (char, stats.num_generator_args)); |
429 } | 427 printf (" return "); |
430 else | 428 gen_exp (pattern, DEFINE_INSN, used); |
431 { | 429 printf (";\n}\n\n"); |
432 char *used = XCNEWVEC (char, operands); | 430 XDELETEVEC (used); |
433 | |
434 printf (" return gen_rtx_PARALLEL (VOIDmode, gen_rtvec (%d", | |
435 XVECLEN (insn, 1)); | |
436 | |
437 for (i = 0; i < XVECLEN (insn, 1); i++) | |
438 { | |
439 printf (",\n\t\t"); | |
440 gen_exp (XVECEXP (insn, 1, i), DEFINE_INSN, used); | |
441 } | |
442 printf ("));\n}\n\n"); | |
443 XDELETEVEC (used); | |
444 } | |
445 } | 431 } |
446 | 432 |
447 /* Generate the `gen_...' function for a DEFINE_EXPAND. */ | 433 /* Generate the `gen_...' function for a DEFINE_EXPAND. */ |
448 | 434 |
449 static void | 435 static void |
450 gen_expand (rtx expand) | 436 gen_expand (md_rtx_info *info) |
451 { | 437 { |
452 int operands; | 438 struct pattern_stats stats; |
453 int i; | 439 int i; |
454 char *used; | 440 char *used; |
455 | 441 |
442 rtx expand = info->def; | |
456 if (strlen (XSTR (expand, 0)) == 0) | 443 if (strlen (XSTR (expand, 0)) == 0) |
457 fatal ("define_expand lacks a name"); | 444 fatal_at (info->loc, "define_expand lacks a name"); |
458 if (XVEC (expand, 1) == 0) | 445 if (XVEC (expand, 1) == 0) |
459 fatal ("define_expand for %s lacks a pattern", XSTR (expand, 0)); | 446 fatal_at (info->loc, "define_expand for %s lacks a pattern", |
447 XSTR (expand, 0)); | |
460 | 448 |
461 /* Find out how many operands this function has. */ | 449 /* Find out how many operands this function has. */ |
462 operands = max_operand_vec (expand, 1); | 450 get_pattern_stats (&stats, XVEC (expand, 1)); |
451 if (stats.min_scratch_opno != -1 | |
452 && stats.min_scratch_opno <= MAX (stats.max_opno, stats.max_dup_opno)) | |
453 fatal_at (info->loc, "define_expand for %s needs to have match_scratch " | |
454 "numbers above all other operands", XSTR (expand, 0)); | |
463 | 455 |
464 /* Output the function name and argument declarations. */ | 456 /* Output the function name and argument declarations. */ |
465 printf ("rtx\ngen_%s (", XSTR (expand, 0)); | 457 printf ("rtx\ngen_%s (", XSTR (expand, 0)); |
466 if (operands) | 458 if (stats.num_generator_args) |
467 for (i = 0; i < operands; i++) | 459 for (i = 0; i < stats.num_generator_args; i++) |
468 if (i) | 460 if (i) |
469 printf (",\n\trtx operand%d", i); | 461 printf (",\n\trtx operand%d", i); |
470 else | 462 else |
471 printf ("rtx operand%d", i); | 463 printf ("rtx operand%d", i); |
472 else | 464 else |
476 | 468 |
477 /* If we don't have any C code to write, only one insn is being written, | 469 /* If we don't have any C code to write, only one insn is being written, |
478 and no MATCH_DUPs are present, we can just return the desired insn | 470 and no MATCH_DUPs are present, we can just return the desired insn |
479 like we do for a DEFINE_INSN. This saves memory. */ | 471 like we do for a DEFINE_INSN. This saves memory. */ |
480 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') | 472 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') |
481 && operands > max_dup_opno | 473 && stats.max_opno >= stats.max_dup_opno |
482 && XVECLEN (expand, 1) == 1) | 474 && XVECLEN (expand, 1) == 1) |
483 { | 475 { |
484 printf (" return "); | 476 printf (" return "); |
485 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); | 477 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); |
486 printf (";\n}\n\n"); | 478 printf (";\n}\n\n"); |
487 return; | 479 return; |
488 } | 480 } |
489 | 481 |
490 /* For each operand referred to only with MATCH_DUPs, | 482 /* For each operand referred to only with MATCH_DUPs, |
491 make a local variable. */ | 483 make a local variable. */ |
492 for (i = operands; i <= max_dup_opno; i++) | 484 for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++) |
493 printf (" rtx operand%d;\n", i); | 485 printf (" rtx operand%d;\n", i); |
494 for (; i <= max_scratch_opno; i++) | 486 printf (" rtx_insn *_val = 0;\n"); |
495 printf (" rtx operand%d ATTRIBUTE_UNUSED;\n", i); | |
496 printf (" rtx _val = 0;\n"); | |
497 printf (" start_sequence ();\n"); | 487 printf (" start_sequence ();\n"); |
498 | 488 |
499 /* The fourth operand of DEFINE_EXPAND is some code to be executed | 489 /* The fourth operand of DEFINE_EXPAND is some code to be executed |
500 before the actual construction. | 490 before the actual construction. |
501 This code expects to refer to `operands' | 491 This code expects to refer to `operands' |
503 but here `operands' is an automatic array. | 493 but here `operands' is an automatic array. |
504 So copy the operand values there before executing it. */ | 494 So copy the operand values there before executing it. */ |
505 if (XSTR (expand, 3) && *XSTR (expand, 3)) | 495 if (XSTR (expand, 3) && *XSTR (expand, 3)) |
506 { | 496 { |
507 printf (" {\n"); | 497 printf (" {\n"); |
508 if (operands > 0 || max_dup_opno >= 0 || max_scratch_opno >= 0) | 498 if (stats.num_operand_vars > 0) |
509 printf (" rtx operands[%d];\n", | 499 printf (" rtx operands[%d];\n", stats.num_operand_vars); |
510 MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1)); | 500 |
511 /* Output code to copy the arguments into `operands'. */ | 501 /* Output code to copy the arguments into `operands'. */ |
512 for (i = 0; i < operands; i++) | 502 for (i = 0; i < stats.num_generator_args; i++) |
513 printf (" operands[%d] = operand%d;\n", i, i); | 503 printf (" operands[%d] = operand%d;\n", i, i); |
514 | 504 |
515 /* Output the special code to be executed before the sequence | 505 /* Output the special code to be executed before the sequence |
516 is generated. */ | 506 is generated. */ |
517 print_md_ptr_loc (XSTR (expand, 3)); | 507 optab_pattern p; |
518 printf ("%s\n", XSTR (expand, 3)); | 508 bool can_fail_p = true; |
509 if (find_optab (&p, XSTR (expand, 0))) | |
510 { | |
511 gcc_assert (p.op < NUM_OPTABS); | |
512 if (nofail_optabs[p.op]) | |
513 can_fail_p = false; | |
514 } | |
515 emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0)); | |
519 | 516 |
520 /* Output code to copy the arguments back out of `operands' | 517 /* Output code to copy the arguments back out of `operands' |
521 (unless we aren't going to use them at all). */ | 518 (unless we aren't going to use them at all). */ |
522 if (XVEC (expand, 1) != 0) | 519 if (XVEC (expand, 1) != 0) |
523 { | 520 { |
524 for (i = 0; | 521 for (i = 0; i <= MAX (stats.max_opno, stats.max_dup_opno); i++) |
525 i < MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1); | |
526 i++) | |
527 { | 522 { |
528 printf (" operand%d = operands[%d];\n", i, i); | 523 printf (" operand%d = operands[%d];\n", i, i); |
529 printf (" (void) operand%d;\n", i); | 524 printf (" (void) operand%d;\n", i); |
530 } | 525 } |
531 } | 526 } |
532 printf (" }\n"); | 527 printf (" }\n"); |
533 } | 528 } |
534 | 529 |
535 /* Output code to construct the rtl for the instruction bodies. | 530 used = XCNEWVEC (char, stats.num_operand_vars); |
536 Use emit_insn to add them to the sequence being accumulated. | 531 gen_emit_seq (XVEC (expand, 1), used); |
537 But don't do this if the user's code has set `no_more' nonzero. */ | |
538 | |
539 used = XCNEWVEC (char, | |
540 MAX (operands, MAX (max_scratch_opno, max_dup_opno) + 1)); | |
541 | |
542 for (i = 0; i < XVECLEN (expand, 1); i++) | |
543 { | |
544 rtx next = XVECEXP (expand, 1, i); | |
545 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) | |
546 || (GET_CODE (next) == PARALLEL | |
547 && ((GET_CODE (XVECEXP (next, 0, 0)) == SET | |
548 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) | |
549 || GET_CODE (XVECEXP (next, 0, 0)) == RETURN)) | |
550 || GET_CODE (next) == RETURN) | |
551 printf (" emit_jump_insn ("); | |
552 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) | |
553 || GET_CODE (next) == CALL | |
554 || (GET_CODE (next) == PARALLEL | |
555 && GET_CODE (XVECEXP (next, 0, 0)) == SET | |
556 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) | |
557 || (GET_CODE (next) == PARALLEL | |
558 && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) | |
559 printf (" emit_call_insn ("); | |
560 else if (LABEL_P (next)) | |
561 printf (" emit_label ("); | |
562 else if (GET_CODE (next) == MATCH_OPERAND | |
563 || GET_CODE (next) == MATCH_DUP | |
564 || GET_CODE (next) == MATCH_OPERATOR | |
565 || GET_CODE (next) == MATCH_OP_DUP | |
566 || GET_CODE (next) == MATCH_PARALLEL | |
567 || GET_CODE (next) == MATCH_PAR_DUP | |
568 || GET_CODE (next) == PARALLEL) | |
569 printf (" emit ("); | |
570 else | |
571 printf (" emit_insn ("); | |
572 gen_exp (next, DEFINE_EXPAND, used); | |
573 printf (");\n"); | |
574 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC | |
575 && GET_CODE (SET_SRC (next)) == LABEL_REF) | |
576 printf (" emit_barrier ();"); | |
577 } | |
578 | |
579 XDELETEVEC (used); | 532 XDELETEVEC (used); |
580 | 533 |
581 /* Call `get_insns' to extract the list of all the | 534 /* Call `get_insns' to extract the list of all the |
582 insns emitted within this gen_... function. */ | 535 insns emitted within this gen_... function. */ |
583 | 536 |
587 } | 540 } |
588 | 541 |
589 /* Like gen_expand, but generates insns resulting from splitting SPLIT. */ | 542 /* Like gen_expand, but generates insns resulting from splitting SPLIT. */ |
590 | 543 |
591 static void | 544 static void |
592 gen_split (rtx split) | 545 gen_split (md_rtx_info *info) |
593 { | 546 { |
547 struct pattern_stats stats; | |
594 int i; | 548 int i; |
595 int operands; | 549 rtx split = info->def; |
596 const char *const name = | 550 const char *const name = |
597 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); | 551 ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split"); |
598 const char *unused; | 552 const char *unused; |
599 char *used; | 553 char *used; |
600 | 554 |
601 if (XVEC (split, 0) == 0) | 555 if (XVEC (split, 0) == 0) |
602 fatal ("define_%s (definition %d) lacks a pattern", name, | 556 fatal_at (info->loc, "%s lacks a pattern", |
603 insn_index_number); | 557 GET_RTX_NAME (GET_CODE (split))); |
604 else if (XVEC (split, 2) == 0) | 558 else if (XVEC (split, 2) == 0) |
605 fatal ("define_%s (definition %d) lacks a replacement pattern", name, | 559 fatal_at (info->loc, "%s lacks a replacement pattern", |
606 insn_index_number); | 560 GET_RTX_NAME (GET_CODE (split))); |
607 | 561 |
608 /* Find out how many operands this function has. */ | 562 /* Find out how many operands this function has. */ |
609 | 563 |
610 max_operand_vec (split, 2); | 564 get_pattern_stats (&stats, XVEC (split, 2)); |
611 operands = MAX (max_opno, MAX (max_dup_opno, max_scratch_opno)) + 1; | 565 unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : ""); |
612 unused = (operands == 0 ? " ATTRIBUTE_UNUSED" : ""); | 566 used = XCNEWVEC (char, stats.num_operand_vars); |
613 used = XCNEWVEC (char, operands); | |
614 | 567 |
615 /* Output the prototype, function name and argument declarations. */ | 568 /* Output the prototype, function name and argument declarations. */ |
616 if (GET_CODE (split) == DEFINE_PEEPHOLE2) | 569 if (GET_CODE (split) == DEFINE_PEEPHOLE2) |
617 { | 570 { |
618 printf ("extern rtx gen_%s_%d (rtx, rtx *);\n", | 571 printf ("extern rtx_insn *gen_%s_%d (rtx_insn *, rtx *);\n", |
619 name, insn_code_number); | 572 name, info->index); |
620 printf ("rtx\ngen_%s_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", | 573 printf ("rtx_insn *\ngen_%s_%d (rtx_insn *curr_insn ATTRIBUTE_UNUSED," |
621 name, insn_code_number, unused); | 574 " rtx *operands%s)\n", |
575 name, info->index, unused); | |
622 } | 576 } |
623 else | 577 else |
624 { | 578 { |
625 printf ("extern rtx gen_split_%d (rtx, rtx *);\n", insn_code_number); | 579 printf ("extern rtx_insn *gen_split_%d (rtx_insn *, rtx *);\n", |
626 printf ("rtx\ngen_split_%d (rtx curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", | 580 info->index); |
627 insn_code_number, unused); | 581 printf ("rtx_insn *\ngen_split_%d " |
582 "(rtx_insn *curr_insn ATTRIBUTE_UNUSED, rtx *operands%s)\n", | |
583 info->index, unused); | |
628 } | 584 } |
629 printf ("{\n"); | 585 printf ("{\n"); |
630 | 586 |
631 /* Declare all local variables. */ | 587 /* Declare all local variables. */ |
632 for (i = 0; i < operands; i++) | 588 for (i = 0; i < stats.num_operand_vars; i++) |
633 printf (" rtx operand%d;\n", i); | 589 printf (" rtx operand%d;\n", i); |
634 printf (" rtx _val = 0;\n"); | 590 printf (" rtx_insn *_val = NULL;\n"); |
635 | 591 |
636 if (GET_CODE (split) == DEFINE_PEEPHOLE2) | 592 if (GET_CODE (split) == DEFINE_PEEPHOLE2) |
637 output_peephole2_scratches (split); | 593 output_peephole2_scratches (split); |
638 | 594 |
595 printf (" if (dump_file)\n"); | |
596 printf (" fprintf (dump_file, \"Splitting with gen_%s_%d\\n\");\n", | |
597 name, info->index); | |
598 | |
639 printf (" start_sequence ();\n"); | 599 printf (" start_sequence ();\n"); |
640 | 600 |
641 /* The fourth operand of DEFINE_SPLIT is some code to be executed | 601 /* The fourth operand of DEFINE_SPLIT is some code to be executed |
642 before the actual construction. */ | 602 before the actual construction. */ |
643 | 603 |
644 if (XSTR (split, 3)) | 604 if (XSTR (split, 3)) |
645 { | 605 emit_c_code (XSTR (split, 3), true, name); |
646 print_md_ptr_loc (XSTR (split, 3)); | |
647 printf ("%s\n", XSTR (split, 3)); | |
648 } | |
649 | 606 |
650 /* Output code to copy the arguments back out of `operands' */ | 607 /* Output code to copy the arguments back out of `operands' */ |
651 for (i = 0; i < operands; i++) | 608 for (i = 0; i < stats.num_operand_vars; i++) |
652 { | 609 { |
653 printf (" operand%d = operands[%d];\n", i, i); | 610 printf (" operand%d = operands[%d];\n", i, i); |
654 printf (" (void) operand%d;\n", i); | 611 printf (" (void) operand%d;\n", i); |
655 } | 612 } |
656 | 613 |
657 /* Output code to construct the rtl for the instruction bodies. | 614 gen_emit_seq (XVEC (split, 2), used); |
658 Use emit_insn to add them to the sequence being accumulated. | |
659 But don't do this if the user's code has set `no_more' nonzero. */ | |
660 | |
661 for (i = 0; i < XVECLEN (split, 2); i++) | |
662 { | |
663 rtx next = XVECEXP (split, 2, i); | |
664 if ((GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC) | |
665 || (GET_CODE (next) == PARALLEL | |
666 && GET_CODE (XVECEXP (next, 0, 0)) == SET | |
667 && GET_CODE (SET_DEST (XVECEXP (next, 0, 0))) == PC) | |
668 || GET_CODE (next) == RETURN) | |
669 printf (" emit_jump_insn ("); | |
670 else if ((GET_CODE (next) == SET && GET_CODE (SET_SRC (next)) == CALL) | |
671 || GET_CODE (next) == CALL | |
672 || (GET_CODE (next) == PARALLEL | |
673 && GET_CODE (XVECEXP (next, 0, 0)) == SET | |
674 && GET_CODE (SET_SRC (XVECEXP (next, 0, 0))) == CALL) | |
675 || (GET_CODE (next) == PARALLEL | |
676 && GET_CODE (XVECEXP (next, 0, 0)) == CALL)) | |
677 printf (" emit_call_insn ("); | |
678 else if (LABEL_P (next)) | |
679 printf (" emit_label ("); | |
680 else if (GET_CODE (next) == MATCH_OPERAND | |
681 || GET_CODE (next) == MATCH_OPERATOR | |
682 || GET_CODE (next) == MATCH_PARALLEL | |
683 || GET_CODE (next) == MATCH_OP_DUP | |
684 || GET_CODE (next) == MATCH_DUP | |
685 || GET_CODE (next) == PARALLEL) | |
686 printf (" emit ("); | |
687 else | |
688 printf (" emit_insn ("); | |
689 gen_exp (next, GET_CODE (split), used); | |
690 printf (");\n"); | |
691 if (GET_CODE (next) == SET && GET_CODE (SET_DEST (next)) == PC | |
692 && GET_CODE (SET_SRC (next)) == LABEL_REF) | |
693 printf (" emit_barrier ();"); | |
694 } | |
695 | 615 |
696 /* Call `get_insns' to make a list of all the | 616 /* Call `get_insns' to make a list of all the |
697 insns emitted within this gen_... function. */ | 617 insns emitted within this gen_... function. */ |
698 | 618 |
699 printf (" _val = get_insns ();\n"); | 619 printf (" _val = get_insns ();\n"); |
825 insn_nr++; | 745 insn_nr++; |
826 } | 746 } |
827 } | 747 } |
828 | 748 |
829 int | 749 int |
830 main (int argc, char **argv) | 750 main (int argc, const char **argv) |
831 { | 751 { |
832 rtx desc; | |
833 | |
834 progname = "genemit"; | 752 progname = "genemit"; |
835 | 753 |
836 if (!init_rtx_reader_args (argc, argv)) | 754 if (!init_rtx_reader_args (argc, argv)) |
837 return (FATAL_EXIT_CODE); | 755 return (FATAL_EXIT_CODE); |
838 | 756 |
757 #define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \ | |
758 nofail_optabs[OPTAB##_optab] = true; | |
759 #include "internal-fn.def" | |
760 | |
839 /* Assign sequential codes to all entries in the machine description | 761 /* Assign sequential codes to all entries in the machine description |
840 in parallel with the tables in insn-output.c. */ | 762 in parallel with the tables in insn-output.c. */ |
841 | |
842 insn_code_number = 0; | |
843 insn_index_number = 0; | |
844 | 763 |
845 printf ("/* Generated automatically by the program `genemit'\n\ | 764 printf ("/* Generated automatically by the program `genemit'\n\ |
846 from the machine description file `md'. */\n\n"); | 765 from the machine description file `md'. */\n\n"); |
847 | 766 |
848 printf ("#include \"config.h\"\n"); | 767 printf ("#include \"config.h\"\n"); |
849 printf ("#include \"system.h\"\n"); | 768 printf ("#include \"system.h\"\n"); |
850 printf ("#include \"coretypes.h\"\n"); | 769 printf ("#include \"coretypes.h\"\n"); |
851 printf ("#include \"tm.h\"\n"); | 770 printf ("#include \"backend.h\"\n"); |
771 printf ("#include \"predict.h\"\n"); | |
772 printf ("#include \"tree.h\"\n"); | |
852 printf ("#include \"rtl.h\"\n"); | 773 printf ("#include \"rtl.h\"\n"); |
774 printf ("#include \"alias.h\"\n"); | |
775 printf ("#include \"varasm.h\"\n"); | |
776 printf ("#include \"stor-layout.h\"\n"); | |
777 printf ("#include \"calls.h\"\n"); | |
778 printf ("#include \"memmodel.h\"\n"); | |
853 printf ("#include \"tm_p.h\"\n"); | 779 printf ("#include \"tm_p.h\"\n"); |
854 printf ("#include \"function.h\"\n"); | 780 printf ("#include \"flags.h\"\n"); |
781 printf ("#include \"insn-config.h\"\n"); | |
782 printf ("#include \"expmed.h\"\n"); | |
783 printf ("#include \"dojump.h\"\n"); | |
784 printf ("#include \"explow.h\"\n"); | |
785 printf ("#include \"emit-rtl.h\"\n"); | |
786 printf ("#include \"stmt.h\"\n"); | |
855 printf ("#include \"expr.h\"\n"); | 787 printf ("#include \"expr.h\"\n"); |
788 printf ("#include \"insn-codes.h\"\n"); | |
856 printf ("#include \"optabs.h\"\n"); | 789 printf ("#include \"optabs.h\"\n"); |
857 printf ("#include \"dfp.h\"\n"); | 790 printf ("#include \"dfp.h\"\n"); |
858 printf ("#include \"flags.h\"\n"); | |
859 printf ("#include \"output.h\"\n"); | 791 printf ("#include \"output.h\"\n"); |
860 printf ("#include \"insn-config.h\"\n"); | |
861 printf ("#include \"hard-reg-set.h\"\n"); | |
862 printf ("#include \"recog.h\"\n"); | 792 printf ("#include \"recog.h\"\n"); |
793 printf ("#include \"df.h\"\n"); | |
863 printf ("#include \"resource.h\"\n"); | 794 printf ("#include \"resource.h\"\n"); |
864 printf ("#include \"reload.h\"\n"); | 795 printf ("#include \"reload.h\"\n"); |
865 printf ("#include \"diagnostic-core.h\"\n"); | 796 printf ("#include \"diagnostic-core.h\"\n"); |
866 printf ("#include \"regs.h\"\n"); | 797 printf ("#include \"regs.h\"\n"); |
867 printf ("#include \"tm-constrs.h\"\n"); | 798 printf ("#include \"tm-constrs.h\"\n"); |
868 printf ("#include \"ggc.h\"\n"); | 799 printf ("#include \"ggc.h\"\n"); |
869 printf ("#include \"basic-block.h\"\n"); | 800 printf ("#include \"target.h\"\n\n"); |
870 printf ("#include \"integrate.h\"\n\n"); | |
871 printf ("#define FAIL return (end_sequence (), _val)\n"); | |
872 printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n"); | |
873 | 801 |
874 /* Read the machine description. */ | 802 /* Read the machine description. */ |
875 | 803 |
876 while (1) | 804 md_rtx_info info; |
877 { | 805 while (read_md_rtx (&info)) |
878 int line_no; | 806 switch (GET_CODE (info.def)) |
879 | 807 { |
880 desc = read_md_rtx (&line_no, &insn_code_number); | 808 case DEFINE_INSN: |
881 if (desc == NULL) | 809 gen_insn (&info); |
882 break; | 810 break; |
883 | 811 |
884 switch (GET_CODE (desc)) | 812 case DEFINE_EXPAND: |
885 { | 813 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); |
886 case DEFINE_INSN: | 814 gen_expand (&info); |
887 gen_insn (desc, line_no); | 815 break; |
888 break; | 816 |
889 | 817 case DEFINE_SPLIT: |
890 case DEFINE_EXPAND: | 818 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); |
891 printf ("/* %s:%d */\n", read_md_filename, line_no); | 819 gen_split (&info); |
892 gen_expand (desc); | 820 break; |
893 break; | 821 |
894 | 822 case DEFINE_PEEPHOLE2: |
895 case DEFINE_SPLIT: | 823 printf ("/* %s:%d */\n", info.loc.filename, info.loc.lineno); |
896 printf ("/* %s:%d */\n", read_md_filename, line_no); | 824 gen_split (&info); |
897 gen_split (desc); | 825 break; |
898 break; | 826 |
899 | 827 default: |
900 case DEFINE_PEEPHOLE2: | 828 break; |
901 printf ("/* %s:%d */\n", read_md_filename, line_no); | 829 } |
902 gen_split (desc); | |
903 break; | |
904 | |
905 default: | |
906 break; | |
907 } | |
908 ++insn_index_number; | |
909 } | |
910 | 830 |
911 /* Write out the routines to add CLOBBERs to a pattern and say whether they | 831 /* Write out the routines to add CLOBBERs to a pattern and say whether they |
912 clobber a hard reg. */ | 832 clobber a hard reg. */ |
913 output_add_clobbers (); | 833 output_add_clobbers (); |
914 output_added_clobbers_hard_reg_p (); | 834 output_added_clobbers_hard_reg_p (); |