Mercurial > hg > CbC > CbC_gcc
comparison gcc/genemit.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
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-2017 Free Software Foundation, Inc. | 2 Copyright (C) 1987-2018 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 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 |
7 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 |
77 | 77 |
78 /* Print a C expression to construct an RTX just like X, | 78 /* Print a C expression to construct an RTX just like X, |
79 substituting any operand references appearing within. */ | 79 substituting any operand references appearing within. */ |
80 | 80 |
81 static void | 81 static void |
82 gen_exp (rtx x, enum rtx_code subroutine_type, char *used) | 82 gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info) |
83 { | 83 { |
84 RTX_CODE code; | 84 RTX_CODE code; |
85 int i; | 85 int i; |
86 int len; | 86 int len; |
87 const char *fmt; | 87 const char *fmt; |
121 else | 121 else |
122 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); | 122 printf ("%smode", GET_MODE_NAME (GET_MODE (x))); |
123 for (i = 0; i < XVECLEN (x, 1); i++) | 123 for (i = 0; i < XVECLEN (x, 1); i++) |
124 { | 124 { |
125 printf (",\n\t\t"); | 125 printf (",\n\t\t"); |
126 gen_exp (XVECEXP (x, 1, i), subroutine_type, used); | 126 gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info); |
127 } | 127 } |
128 printf (")"); | 128 printf (")"); |
129 return; | 129 return; |
130 | 130 |
131 case MATCH_OPERATOR: | 131 case MATCH_OPERATOR: |
135 printf (" (GET_CODE (operand%d)", XINT (x, 0)); | 135 printf (" (GET_CODE (operand%d)", XINT (x, 0)); |
136 printf (", %smode", GET_MODE_NAME (GET_MODE (x))); | 136 printf (", %smode", GET_MODE_NAME (GET_MODE (x))); |
137 for (i = 0; i < XVECLEN (x, 2); i++) | 137 for (i = 0; i < XVECLEN (x, 2); i++) |
138 { | 138 { |
139 printf (",\n\t\t"); | 139 printf (",\n\t\t"); |
140 gen_exp (XVECEXP (x, 2, i), subroutine_type, used); | 140 gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info); |
141 } | 141 } |
142 printf (")"); | 142 printf (")"); |
143 return; | 143 return; |
144 | 144 |
145 case MATCH_PARALLEL: | 145 case MATCH_PARALLEL: |
161 printf ("simple_return_rtx"); | 161 printf ("simple_return_rtx"); |
162 return; | 162 return; |
163 case CLOBBER: | 163 case CLOBBER: |
164 if (REG_P (XEXP (x, 0))) | 164 if (REG_P (XEXP (x, 0))) |
165 { | 165 { |
166 printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))), | 166 printf ("gen_hard_reg_clobber (%smode, %i)", |
167 REGNO (XEXP (x, 0))); | 167 GET_MODE_NAME (GET_MODE (XEXP (x, 0))), |
168 REGNO (XEXP (x, 0))); | |
168 return; | 169 return; |
169 } | 170 } |
170 break; | 171 break; |
171 | 172 case CLOBBER_HIGH: |
173 if (!REG_P (XEXP (x, 0))) | |
174 error ("CLOBBER_HIGH argument is not a register expr, at %s:%d", | |
175 info->loc.filename, info->loc.lineno); | |
176 printf ("gen_hard_reg_clobber_high (%smode, %i)", | |
177 GET_MODE_NAME (GET_MODE (XEXP (x, 0))), | |
178 REGNO (XEXP (x, 0))); | |
179 return; | |
180 break; | |
172 case CC0: | 181 case CC0: |
173 printf ("cc0_rtx"); | 182 printf ("cc0_rtx"); |
174 return; | 183 return; |
175 | 184 |
176 case CONST_INT: | 185 case CONST_INT: |
222 break; | 231 break; |
223 fputs (sep, stdout); | 232 fputs (sep, stdout); |
224 switch (fmt[i]) | 233 switch (fmt[i]) |
225 { | 234 { |
226 case 'e': case 'u': | 235 case 'e': case 'u': |
227 gen_exp (XEXP (x, i), subroutine_type, used); | 236 gen_exp (XEXP (x, i), subroutine_type, used, info); |
228 break; | 237 break; |
229 | 238 |
230 case 'i': | 239 case 'i': |
231 printf ("%u", XINT (x, i)); | 240 printf ("%u", XINT (x, i)); |
232 break; | 241 break; |
233 | 242 |
234 case 'r': | 243 case 'r': |
235 printf ("%u", REGNO (x)); | 244 printf ("%u", REGNO (x)); |
245 break; | |
246 | |
247 case 'p': | |
248 /* We don't have a way of parsing polynomial offsets yet, | |
249 and hopefully never will. */ | |
250 printf ("%d", SUBREG_BYTE (x).to_constant ()); | |
236 break; | 251 break; |
237 | 252 |
238 case 's': | 253 case 's': |
239 printf ("\"%s\"", XSTR (x, i)); | 254 printf ("\"%s\"", XSTR (x, i)); |
240 break; | 255 break; |
244 int j; | 259 int j; |
245 printf ("gen_rtvec (%d", XVECLEN (x, i)); | 260 printf ("gen_rtvec (%d", XVECLEN (x, i)); |
246 for (j = 0; j < XVECLEN (x, i); j++) | 261 for (j = 0; j < XVECLEN (x, i); j++) |
247 { | 262 { |
248 printf (",\n\t\t"); | 263 printf (",\n\t\t"); |
249 gen_exp (XVECEXP (x, i, j), subroutine_type, used); | 264 gen_exp (XVECEXP (x, i, j), subroutine_type, used, info); |
250 } | 265 } |
251 printf (")"); | 266 printf (")"); |
252 break; | 267 break; |
253 } | 268 } |
254 | 269 |
262 | 277 |
263 /* Output code to emit the instruction patterns in VEC, with each element | 278 /* Output code to emit the instruction patterns in VEC, with each element |
264 becoming a separate instruction. USED is as for gen_exp. */ | 279 becoming a separate instruction. USED is as for gen_exp. */ |
265 | 280 |
266 static void | 281 static void |
267 gen_emit_seq (rtvec vec, char *used) | 282 gen_emit_seq (rtvec vec, char *used, md_rtx_info *info) |
268 { | 283 { |
269 for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) | 284 for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i) |
270 { | 285 { |
271 bool last_p = (i == len - 1); | 286 bool last_p = (i == len - 1); |
272 rtx next = RTVEC_ELT (vec, i); | 287 rtx next = RTVEC_ELT (vec, i); |
273 if (const char *name = get_emit_function (next)) | 288 if (const char *name = get_emit_function (next)) |
274 { | 289 { |
275 printf (" %s (", name); | 290 printf (" %s (", name); |
276 gen_exp (next, DEFINE_EXPAND, used); | 291 gen_exp (next, DEFINE_EXPAND, used, info); |
277 printf (");\n"); | 292 printf (");\n"); |
278 if (!last_p && needs_barrier_p (next)) | 293 if (!last_p && needs_barrier_p (next)) |
279 printf (" emit_barrier ();"); | 294 printf (" emit_barrier ();"); |
280 } | 295 } |
281 else | 296 else |
282 { | 297 { |
283 printf (" emit ("); | 298 printf (" emit ("); |
284 gen_exp (next, DEFINE_EXPAND, used); | 299 gen_exp (next, DEFINE_EXPAND, used, info); |
285 printf (", %s);\n", last_p ? "false" : "true"); | 300 printf (", %s);\n", last_p ? "false" : "true"); |
286 } | 301 } |
287 } | 302 } |
288 } | 303 } |
289 | 304 |
326 { | 341 { |
327 int has_hard_reg = 0; | 342 int has_hard_reg = 0; |
328 | 343 |
329 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) | 344 for (i = XVECLEN (insn, 1) - 1; i > 0; i--) |
330 { | 345 { |
331 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER) | 346 if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER |
347 && GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER_HIGH) | |
332 break; | 348 break; |
333 | 349 |
334 if (REG_P (XEXP (XVECEXP (insn, 1, i), 0))) | 350 if (REG_P (XEXP (XVECEXP (insn, 1, i), 0))) |
335 has_hard_reg = 1; | 351 has_hard_reg = 1; |
336 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH) | 352 else if (GET_CODE (XEXP (XVECEXP (insn, 1, i), 0)) != MATCH_SCRATCH) |
360 rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0); | 376 rtx new_rtx = XEXP (XVECEXP (insn, 1, j), 0); |
361 | 377 |
362 /* OLD and NEW_INSN are the same if both are to be a SCRATCH | 378 /* OLD and NEW_INSN are the same if both are to be a SCRATCH |
363 of the same mode, | 379 of the same mode, |
364 or if both are registers of the same mode and number. */ | 380 or if both are registers of the same mode and number. */ |
365 if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx) | 381 if (! (GET_CODE (old_rtx) == GET_CODE (new_rtx) |
382 && GET_MODE (old_rtx) == GET_MODE (new_rtx) | |
366 && ((GET_CODE (old_rtx) == MATCH_SCRATCH | 383 && ((GET_CODE (old_rtx) == MATCH_SCRATCH |
367 && GET_CODE (new_rtx) == MATCH_SCRATCH) | 384 && GET_CODE (new_rtx) == MATCH_SCRATCH) |
368 || (REG_P (old_rtx) && REG_P (new_rtx) | 385 || (REG_P (old_rtx) && REG_P (new_rtx) |
369 && REGNO (old_rtx) == REGNO (new_rtx))))) | 386 && REGNO (old_rtx) == REGNO (new_rtx))))) |
370 break; | 387 break; |
423 /* ??? This is the traditional behavior, but seems suspect. */ | 440 /* ??? This is the traditional behavior, but seems suspect. */ |
424 char *used = (XVECLEN (insn, 1) == 1 | 441 char *used = (XVECLEN (insn, 1) == 1 |
425 ? NULL | 442 ? NULL |
426 : XCNEWVEC (char, stats.num_generator_args)); | 443 : XCNEWVEC (char, stats.num_generator_args)); |
427 printf (" return "); | 444 printf (" return "); |
428 gen_exp (pattern, DEFINE_INSN, used); | 445 gen_exp (pattern, DEFINE_INSN, used, info); |
429 printf (";\n}\n\n"); | 446 printf (";\n}\n\n"); |
430 XDELETEVEC (used); | 447 XDELETEVEC (used); |
431 } | 448 } |
432 | 449 |
433 /* Generate the `gen_...' function for a DEFINE_EXPAND. */ | 450 /* Generate the `gen_...' function for a DEFINE_EXPAND. */ |
472 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') | 489 if ((XSTR (expand, 3) == 0 || *XSTR (expand, 3) == '\0') |
473 && stats.max_opno >= stats.max_dup_opno | 490 && stats.max_opno >= stats.max_dup_opno |
474 && XVECLEN (expand, 1) == 1) | 491 && XVECLEN (expand, 1) == 1) |
475 { | 492 { |
476 printf (" return "); | 493 printf (" return "); |
477 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL); | 494 gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info); |
478 printf (";\n}\n\n"); | 495 printf (";\n}\n\n"); |
479 return; | 496 return; |
480 } | 497 } |
481 | 498 |
482 /* For each operand referred to only with MATCH_DUPs, | 499 /* For each operand referred to only with MATCH_DUPs, |
526 } | 543 } |
527 printf (" }\n"); | 544 printf (" }\n"); |
528 } | 545 } |
529 | 546 |
530 used = XCNEWVEC (char, stats.num_operand_vars); | 547 used = XCNEWVEC (char, stats.num_operand_vars); |
531 gen_emit_seq (XVEC (expand, 1), used); | 548 gen_emit_seq (XVEC (expand, 1), used, info); |
532 XDELETEVEC (used); | 549 XDELETEVEC (used); |
533 | 550 |
534 /* Call `get_insns' to extract the list of all the | 551 /* Call `get_insns' to extract the list of all the |
535 insns emitted within this gen_... function. */ | 552 insns emitted within this gen_... function. */ |
536 | 553 |
609 { | 626 { |
610 printf (" operand%d = operands[%d];\n", i, i); | 627 printf (" operand%d = operands[%d];\n", i, i); |
611 printf (" (void) operand%d;\n", i); | 628 printf (" (void) operand%d;\n", i); |
612 } | 629 } |
613 | 630 |
614 gen_emit_seq (XVEC (split, 2), used); | 631 gen_emit_seq (XVEC (split, 2), used, info); |
615 | 632 |
616 /* Call `get_insns' to make a list of all the | 633 /* Call `get_insns' to make a list of all the |
617 insns emitted within this gen_... function. */ | 634 insns emitted within this gen_... function. */ |
618 | 635 |
619 printf (" _val = get_insns ();\n"); | 636 printf (" _val = get_insns ();\n"); |
626 /* Write a function, `add_clobbers', that is given a PARALLEL of sufficient | 643 /* Write a function, `add_clobbers', that is given a PARALLEL of sufficient |
627 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at | 644 size for the insn and an INSN_CODE, and inserts the required CLOBBERs at |
628 the end of the vector. */ | 645 the end of the vector. */ |
629 | 646 |
630 static void | 647 static void |
631 output_add_clobbers (void) | 648 output_add_clobbers (md_rtx_info *info) |
632 { | 649 { |
633 struct clobber_pat *clobber; | 650 struct clobber_pat *clobber; |
634 struct clobber_ent *ent; | 651 struct clobber_ent *ent; |
635 int i; | 652 int i; |
636 | 653 |
646 | 663 |
647 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) | 664 for (i = clobber->first_clobber; i < XVECLEN (clobber->pattern, 1); i++) |
648 { | 665 { |
649 printf (" XVECEXP (pattern, 0, %d) = ", i); | 666 printf (" XVECEXP (pattern, 0, %d) = ", i); |
650 gen_exp (XVECEXP (clobber->pattern, 1, i), | 667 gen_exp (XVECEXP (clobber->pattern, 1, i), |
651 GET_CODE (clobber->pattern), NULL); | 668 GET_CODE (clobber->pattern), NULL, info); |
652 printf (";\n"); | 669 printf (";\n"); |
653 } | 670 } |
654 | 671 |
655 printf (" break;\n\n"); | 672 printf (" break;\n\n"); |
656 } | 673 } |
744 else if (GET_CODE (elt) != MATCH_DUP) | 761 else if (GET_CODE (elt) != MATCH_DUP) |
745 insn_nr++; | 762 insn_nr++; |
746 } | 763 } |
747 } | 764 } |
748 | 765 |
766 /* Print "arg<N>" parameter declarations for each argument N of ONAME. */ | |
767 | |
768 static void | |
769 print_overload_arguments (overloaded_name *oname) | |
770 { | |
771 for (unsigned int i = 0; i < oname->arg_types.length (); ++i) | |
772 printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i); | |
773 } | |
774 | |
775 /* Print code to test whether INSTANCE should be chosen, given that | |
776 argument N of the overload is available as "arg<N>". */ | |
777 | |
778 static void | |
779 print_overload_test (overloaded_instance *instance) | |
780 { | |
781 for (unsigned int i = 0; i < instance->arg_values.length (); ++i) | |
782 printf ("%sarg%d == %s", i == 0 ? " if (" : "\n && ", | |
783 i, instance->arg_values[i]); | |
784 printf (")\n"); | |
785 } | |
786 | |
787 /* Emit a maybe_code_for_* function for ONAME. */ | |
788 | |
789 static void | |
790 handle_overloaded_code_for (overloaded_name *oname) | |
791 { | |
792 /* Print the function prototype. */ | |
793 printf ("\ninsn_code\nmaybe_code_for_%s (", oname->name); | |
794 print_overload_arguments (oname); | |
795 printf (")\n{\n"); | |
796 | |
797 /* Use a sequence of "if" statements for each instance. */ | |
798 for (overloaded_instance *instance = oname->first_instance; | |
799 instance; instance = instance->next) | |
800 { | |
801 print_overload_test (instance); | |
802 printf (" return CODE_FOR_%s;\n", instance->name); | |
803 } | |
804 | |
805 /* Return null if no match was found. */ | |
806 printf (" return CODE_FOR_nothing;\n}\n"); | |
807 } | |
808 | |
809 /* Emit a maybe_gen_* function for ONAME. */ | |
810 | |
811 static void | |
812 handle_overloaded_gen (overloaded_name *oname) | |
813 { | |
814 /* All patterns must have the same number of operands. */ | |
815 pattern_stats stats; | |
816 get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1)); | |
817 for (overloaded_instance *instance = oname->first_instance->next; | |
818 instance; instance = instance->next) | |
819 { | |
820 pattern_stats stats2; | |
821 get_pattern_stats (&stats2, XVEC (instance->insn, 1)); | |
822 if (stats.num_generator_args != stats2.num_generator_args) | |
823 fatal_at (get_file_location (instance->insn), | |
824 "inconsistent number of operands for '%s'; " | |
825 "this instance has %d, but previous instances had %d", | |
826 oname->name, stats2.num_generator_args, | |
827 stats.num_generator_args); | |
828 } | |
829 | |
830 /* Print the function prototype. */ | |
831 printf ("\nrtx\nmaybe_gen_%s (", oname->name); | |
832 print_overload_arguments (oname); | |
833 for (int i = 0; i < stats.num_generator_args; ++i) | |
834 printf (", rtx x%d", i); | |
835 printf (")\n{\n"); | |
836 | |
837 /* Use maybe_code_for_*, instead of duplicating the selection logic here. */ | |
838 printf (" insn_code code = maybe_code_for_%s (", oname->name); | |
839 for (unsigned int i = 0; i < oname->arg_types.length (); ++i) | |
840 printf ("%sarg%d", i == 0 ? "" : ", ", i); | |
841 printf (");\n" | |
842 " if (code != CODE_FOR_nothing)\n" | |
843 " return GEN_FCN (code) ("); | |
844 for (int i = 0; i < stats.num_generator_args; ++i) | |
845 printf ("%sx%d", i == 0 ? "" : ", ", i); | |
846 printf (");\n" | |
847 " else\n" | |
848 " return NULL_RTX;\n" | |
849 "}\n"); | |
850 } | |
851 | |
749 int | 852 int |
750 main (int argc, const char **argv) | 853 main (int argc, const char **argv) |
751 { | 854 { |
752 progname = "genemit"; | 855 progname = "genemit"; |
753 | 856 |
762 in parallel with the tables in insn-output.c. */ | 865 in parallel with the tables in insn-output.c. */ |
763 | 866 |
764 printf ("/* Generated automatically by the program `genemit'\n\ | 867 printf ("/* Generated automatically by the program `genemit'\n\ |
765 from the machine description file `md'. */\n\n"); | 868 from the machine description file `md'. */\n\n"); |
766 | 869 |
870 printf ("#define IN_TARGET_CODE 1\n"); | |
767 printf ("#include \"config.h\"\n"); | 871 printf ("#include \"config.h\"\n"); |
768 printf ("#include \"system.h\"\n"); | 872 printf ("#include \"system.h\"\n"); |
769 printf ("#include \"coretypes.h\"\n"); | 873 printf ("#include \"coretypes.h\"\n"); |
770 printf ("#include \"backend.h\"\n"); | 874 printf ("#include \"backend.h\"\n"); |
771 printf ("#include \"predict.h\"\n"); | 875 printf ("#include \"predict.h\"\n"); |
828 break; | 932 break; |
829 } | 933 } |
830 | 934 |
831 /* Write out the routines to add CLOBBERs to a pattern and say whether they | 935 /* Write out the routines to add CLOBBERs to a pattern and say whether they |
832 clobber a hard reg. */ | 936 clobber a hard reg. */ |
833 output_add_clobbers (); | 937 output_add_clobbers (&info); |
834 output_added_clobbers_hard_reg_p (); | 938 output_added_clobbers_hard_reg_p (); |
939 | |
940 for (overloaded_name *oname = rtx_reader_ptr->get_overloads (); | |
941 oname; oname = oname->next) | |
942 { | |
943 handle_overloaded_code_for (oname); | |
944 handle_overloaded_gen (oname); | |
945 } | |
835 | 946 |
836 fflush (stdout); | 947 fflush (stdout); |
837 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); | 948 return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); |
838 } | 949 } |