diff gcc/genemit.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/genemit.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/genemit.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Generate code from machine description to emit insns as rtl.
-   Copyright (C) 1987-2017 Free Software Foundation, Inc.
+   Copyright (C) 1987-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -79,7 +79,7 @@
    substituting any operand references appearing within.  */
 
 static void
-gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
+gen_exp (rtx x, enum rtx_code subroutine_type, char *used, md_rtx_info *info)
 {
   RTX_CODE code;
   int i;
@@ -123,7 +123,7 @@
       for (i = 0; i < XVECLEN (x, 1); i++)
 	{
 	  printf (",\n\t\t");
-	  gen_exp (XVECEXP (x, 1, i), subroutine_type, used);
+	  gen_exp (XVECEXP (x, 1, i), subroutine_type, used, info);
 	}
       printf (")");
       return;
@@ -137,7 +137,7 @@
       for (i = 0; i < XVECLEN (x, 2); i++)
 	{
 	  printf (",\n\t\t");
-	  gen_exp (XVECEXP (x, 2, i), subroutine_type, used);
+	  gen_exp (XVECEXP (x, 2, i), subroutine_type, used, info);
 	}
       printf (")");
       return;
@@ -163,12 +163,21 @@
     case CLOBBER:
       if (REG_P (XEXP (x, 0)))
 	{
-	  printf ("gen_hard_reg_clobber (%smode, %i)", GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
-			  			     REGNO (XEXP (x, 0)));
+	  printf ("gen_hard_reg_clobber (%smode, %i)",
+		  GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+		  REGNO (XEXP (x, 0)));
 	  return;
 	}
       break;
-
+    case CLOBBER_HIGH:
+      if (!REG_P (XEXP (x, 0)))
+	error ("CLOBBER_HIGH argument is not a register expr, at %s:%d",
+	       info->loc.filename, info->loc.lineno);
+      printf ("gen_hard_reg_clobber_high (%smode, %i)",
+	      GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
+	      REGNO (XEXP (x, 0)));
+      return;
+      break;
     case CC0:
       printf ("cc0_rtx");
       return;
@@ -224,7 +233,7 @@
       switch (fmt[i])
 	{
 	case 'e': case 'u':
-	  gen_exp (XEXP (x, i), subroutine_type, used);
+	  gen_exp (XEXP (x, i), subroutine_type, used, info);
 	  break;
 
 	case 'i':
@@ -235,6 +244,12 @@
 	  printf ("%u", REGNO (x));
 	  break;
 
+	case 'p':
+	  /* We don't have a way of parsing polynomial offsets yet,
+	     and hopefully never will.  */
+	  printf ("%d", SUBREG_BYTE (x).to_constant ());
+	  break;
+
 	case 's':
 	  printf ("\"%s\"", XSTR (x, i));
 	  break;
@@ -246,7 +261,7 @@
 	    for (j = 0; j < XVECLEN (x, i); j++)
 	      {
 		printf (",\n\t\t");
-		gen_exp (XVECEXP (x, i, j), subroutine_type, used);
+		gen_exp (XVECEXP (x, i, j), subroutine_type, used, info);
 	      }
 	    printf (")");
 	    break;
@@ -264,7 +279,7 @@
    becoming a separate instruction.  USED is as for gen_exp.  */
 
 static void
-gen_emit_seq (rtvec vec, char *used)
+gen_emit_seq (rtvec vec, char *used, md_rtx_info *info)
 {
   for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i)
     {
@@ -273,7 +288,7 @@
       if (const char *name = get_emit_function (next))
 	{
 	  printf ("  %s (", name);
-	  gen_exp (next, DEFINE_EXPAND, used);
+	  gen_exp (next, DEFINE_EXPAND, used, info);
 	  printf (");\n");
 	  if (!last_p && needs_barrier_p (next))
 	    printf ("  emit_barrier ();");
@@ -281,7 +296,7 @@
       else
 	{
 	  printf ("  emit (");
-	  gen_exp (next, DEFINE_EXPAND, used);
+	  gen_exp (next, DEFINE_EXPAND, used, info);
 	  printf (", %s);\n", last_p ? "false" : "true");
 	}
     }
@@ -328,7 +343,8 @@
 
       for (i = XVECLEN (insn, 1) - 1; i > 0; i--)
 	{
-	  if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER)
+	  if (GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER
+	      && GET_CODE (XVECEXP (insn, 1, i)) != CLOBBER_HIGH)
 	    break;
 
 	  if (REG_P (XEXP (XVECEXP (insn, 1, i), 0)))
@@ -362,7 +378,8 @@
 		  /* OLD and NEW_INSN are the same if both are to be a SCRATCH
 		     of the same mode,
 		     or if both are registers of the same mode and number.  */
-		  if (! (GET_MODE (old_rtx) == GET_MODE (new_rtx)
+		  if (! (GET_CODE (old_rtx) == GET_CODE (new_rtx)
+			 && GET_MODE (old_rtx) == GET_MODE (new_rtx)
 			 && ((GET_CODE (old_rtx) == MATCH_SCRATCH
 			      && GET_CODE (new_rtx) == MATCH_SCRATCH)
 			     || (REG_P (old_rtx) && REG_P (new_rtx)
@@ -425,7 +442,7 @@
 		? NULL
 		: XCNEWVEC (char, stats.num_generator_args));
   printf ("  return ");
-  gen_exp (pattern, DEFINE_INSN, used);
+  gen_exp (pattern, DEFINE_INSN, used, info);
   printf (";\n}\n\n");
   XDELETEVEC (used);
 }
@@ -474,7 +491,7 @@
       && XVECLEN (expand, 1) == 1)
     {
       printf ("  return ");
-      gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL);
+      gen_exp (XVECEXP (expand, 1, 0), DEFINE_EXPAND, NULL, info);
       printf (";\n}\n\n");
       return;
     }
@@ -528,7 +545,7 @@
     }
 
   used = XCNEWVEC (char, stats.num_operand_vars);
-  gen_emit_seq (XVEC (expand, 1), used);
+  gen_emit_seq (XVEC (expand, 1), used, info);
   XDELETEVEC (used);
 
   /* Call `get_insns' to extract the list of all the
@@ -611,7 +628,7 @@
       printf ("  (void) operand%d;\n", i);
     }
 
-  gen_emit_seq (XVEC (split, 2), used);
+  gen_emit_seq (XVEC (split, 2), used, info);
 
   /* Call `get_insns' to make a list of all the
      insns emitted within this gen_... function.  */
@@ -628,7 +645,7 @@
    the end of the vector.  */
 
 static void
-output_add_clobbers (void)
+output_add_clobbers (md_rtx_info *info)
 {
   struct clobber_pat *clobber;
   struct clobber_ent *ent;
@@ -648,7 +665,7 @@
 	{
 	  printf ("      XVECEXP (pattern, 0, %d) = ", i);
 	  gen_exp (XVECEXP (clobber->pattern, 1, i),
-		   GET_CODE (clobber->pattern), NULL);
+		   GET_CODE (clobber->pattern), NULL, info);
 	  printf (";\n");
 	}
 
@@ -746,6 +763,92 @@
     }
 }
 
+/* Print "arg<N>" parameter declarations for each argument N of ONAME.  */
+
+static void
+print_overload_arguments (overloaded_name *oname)
+{
+  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+    printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
+}
+
+/* Print code to test whether INSTANCE should be chosen, given that
+   argument N of the overload is available as "arg<N>".  */
+
+static void
+print_overload_test (overloaded_instance *instance)
+{
+  for (unsigned int i = 0; i < instance->arg_values.length (); ++i)
+    printf ("%sarg%d == %s", i == 0 ? "  if (" : "\n      && ",
+	    i, instance->arg_values[i]);
+  printf (")\n");
+}
+
+/* Emit a maybe_code_for_* function for ONAME.  */
+
+static void
+handle_overloaded_code_for (overloaded_name *oname)
+{
+  /* Print the function prototype.  */
+  printf ("\ninsn_code\nmaybe_code_for_%s (", oname->name);
+  print_overload_arguments (oname);
+  printf (")\n{\n");
+
+  /* Use a sequence of "if" statements for each instance.  */
+  for (overloaded_instance *instance = oname->first_instance;
+       instance; instance = instance->next)
+    {
+      print_overload_test (instance);
+      printf ("    return CODE_FOR_%s;\n", instance->name);
+    }
+
+  /* Return null if no match was found.  */
+  printf ("  return CODE_FOR_nothing;\n}\n");
+}
+
+/* Emit a maybe_gen_* function for ONAME.  */
+
+static void
+handle_overloaded_gen (overloaded_name *oname)
+{
+  /* All patterns must have the same number of operands.  */
+  pattern_stats stats;
+  get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
+  for (overloaded_instance *instance = oname->first_instance->next;
+       instance; instance = instance->next)
+    {
+      pattern_stats stats2;
+      get_pattern_stats (&stats2, XVEC (instance->insn, 1));
+      if (stats.num_generator_args != stats2.num_generator_args)
+	fatal_at (get_file_location (instance->insn),
+		  "inconsistent number of operands for '%s'; "
+		  "this instance has %d, but previous instances had %d",
+		  oname->name, stats2.num_generator_args,
+		  stats.num_generator_args);
+    }
+
+  /* Print the function prototype.  */
+  printf ("\nrtx\nmaybe_gen_%s (", oname->name);
+  print_overload_arguments (oname);
+  for (int i = 0; i < stats.num_generator_args; ++i)
+    printf (", rtx x%d", i);
+  printf (")\n{\n");
+
+  /* Use maybe_code_for_*, instead of duplicating the selection logic here.  */
+  printf ("  insn_code code = maybe_code_for_%s (", oname->name);
+  for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+    printf ("%sarg%d", i == 0 ? "" : ", ", i);
+  printf (");\n"
+	  "  if (code != CODE_FOR_nothing)\n"
+	  "    return GEN_FCN (code) (");
+  for (int i = 0; i < stats.num_generator_args; ++i)
+    printf ("%sx%d", i == 0 ? "" : ", ", i);
+  printf (");\n"
+	  "  else\n"
+	  "    return NULL_RTX;\n"
+	  "}\n");
+}
+
 int
 main (int argc, const char **argv)
 {
@@ -764,6 +867,7 @@
   printf ("/* Generated automatically by the program `genemit'\n\
 from the machine description file `md'.  */\n\n");
 
+  printf ("#define IN_TARGET_CODE 1\n");
   printf ("#include \"config.h\"\n");
   printf ("#include \"system.h\"\n");
   printf ("#include \"coretypes.h\"\n");
@@ -830,9 +934,16 @@
 
   /* Write out the routines to add CLOBBERs to a pattern and say whether they
      clobber a hard reg.  */
-  output_add_clobbers ();
+  output_add_clobbers (&info);
   output_added_clobbers_hard_reg_p ();
 
+  for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
+       oname; oname = oname->next)
+    {
+      handle_overloaded_code_for (oname);
+      handle_overloaded_gen (oname);
+    }
+
   fflush (stdout);
   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
 }