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 }