genflags.c (gen_macro): Delete.
authorRichard Sandiford <richard.sandiford@arm.com>
Mon, 24 Aug 2015 17:59:51 +0000 (17:59 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 24 Aug 2015 17:59:51 +0000 (17:59 +0000)
gcc/
* genflags.c (gen_macro): Delete.
(gen_proto): Don't create GEN.*CALL.* macros.
* gensupport.h (get_file_location): Declare.
* gensupport.c (rtx_locs): New variable.
(read_md_rtx): Record rtx locations.
(get_file_location): New function.
* target-insns.def (call, call_pop, call_value, call_value_pop)
(sibcall, sibcall_value): New patterns.
* gentarget-def.c (parse_argument): New function.
(def_target_insn): Use it.  Handle optional operands.  Raise an
error if an .md pattern has the wrong number of operands for the
pattern name.  Remove the names of unused operands from the prototype.
* builtins.c (expand_builtin_apply): Use targetm functions
instead of HAVE_call_value and GEN_CALL_VALUE.
* calls.c (emit_call_1): Likewise.  Remove support for sibcall_pop
and sibcall_value_pop.
* config/aarch64/aarch64.md (untyped_call): Use gen_call instead
of GEN_CALL.
* config/alpha/alpha.md (untyped_call): Likewise.
* config/iq2000/iq2000.md (untyped_call): Likewise.
* config/m68k/m68k.md (untyped_call): Likewise.
* config/mips/mips.md (untyped_call): Likewise.
* config/pa/pa.md (untyped_call): Likewise.
* config/rs6000/rs6000.md (untyped_call): Likewise.
* config/sparc/sparc.md (untyped_call): Likewise.
* config/tilegx/tilegx.md (untyped_call): Likewise.
* config/tilepro/tilepro.md (untyped_call): Likewise.
* config/visium/visium.md (untyped_call): Likewise.
* config/alpha/alpha.c (alpha_emit_xfloating_libcall): Use
gen_call_value instead of GEN_CALL_VALUE.
* config/arm/arm.md (untyped_call): Likewise.
* config/cr16/cr16.c (cr16_function_arg): Remove reference to
GEN_CALL.

From-SVN: r227143

22 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/calls.c
gcc/config/aarch64/aarch64.md
gcc/config/alpha/alpha.c
gcc/config/alpha/alpha.md
gcc/config/arm/arm.md
gcc/config/cr16/cr16.c
gcc/config/iq2000/iq2000.md
gcc/config/m68k/m68k.md
gcc/config/mips/mips.md
gcc/config/pa/pa.md
gcc/config/rs6000/rs6000.md
gcc/config/sparc/sparc.md
gcc/config/tilegx/tilegx.md
gcc/config/tilepro/tilepro.md
gcc/config/visium/visium.md
gcc/genflags.c
gcc/gensupport.c
gcc/gensupport.h
gcc/gentarget-def.c
gcc/target-insns.def

index 7ef1166c1453c2c76024e5f11a324d508f1bd464..8c8352347f08cab7c2e3a97a13b9dfc1a31faf34 100644 (file)
@@ -1,3 +1,39 @@
+2015-08-24  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * genflags.c (gen_macro): Delete.
+       (gen_proto): Don't create GEN.*CALL.* macros.
+       * gensupport.h (get_file_location): Declare.
+       * gensupport.c (rtx_locs): New variable.
+       (read_md_rtx): Record rtx locations.
+       (get_file_location): New function.
+       * target-insns.def (call, call_pop, call_value, call_value_pop)
+       (sibcall, sibcall_value): New patterns.
+       * gentarget-def.c (parse_argument): New function.
+       (def_target_insn): Use it.  Handle optional operands.  Raise an
+       error if an .md pattern has the wrong number of operands for the
+       pattern name.  Remove the names of unused operands from the prototype.
+       * builtins.c (expand_builtin_apply): Use targetm functions
+       instead of HAVE_call_value and GEN_CALL_VALUE.
+       * calls.c (emit_call_1): Likewise.  Remove support for sibcall_pop
+       and sibcall_value_pop.
+       * config/aarch64/aarch64.md (untyped_call): Use gen_call instead
+       of GEN_CALL.
+       * config/alpha/alpha.md (untyped_call): Likewise.
+       * config/iq2000/iq2000.md (untyped_call): Likewise.
+       * config/m68k/m68k.md (untyped_call): Likewise.
+       * config/mips/mips.md (untyped_call): Likewise.
+       * config/pa/pa.md (untyped_call): Likewise.
+       * config/rs6000/rs6000.md (untyped_call): Likewise.
+       * config/sparc/sparc.md (untyped_call): Likewise.
+       * config/tilegx/tilegx.md (untyped_call): Likewise.
+       * config/tilepro/tilepro.md (untyped_call): Likewise.
+       * config/visium/visium.md (untyped_call): Likewise.
+       * config/alpha/alpha.c (alpha_emit_xfloating_libcall): Use
+       gen_call_value instead of GEN_CALL_VALUE.
+       * config/arm/arm.md (untyped_call): Likewise.
+       * config/cr16/cr16.c (cr16_function_arg): Remove reference to
+       GEN_CALL.
+
 2015-08-24  Richard Sandiford  <richard.sandiford@arm.com>
 
        * ifcvt.c (HAVE_incscc, HAVE_decscc, HAVE_cbranchcc4): Delete.
index 5021dcfa8ce3962e666a121128caefa751a6190b..d79372cf2684294b1c2effb0ff05180993fab55f 100644 (file)
@@ -1686,9 +1686,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
       emit_call_insn (targetm.gen_untyped_call (mem, result,
                                                result_vector (1, result)));
     }
-  else
-#ifdef HAVE_call_value
-  if (HAVE_call_value)
+  else if (targetm.have_call_value ())
     {
       rtx valreg = 0;
 
@@ -1699,19 +1697,18 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize)
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
        if ((mode = apply_result_mode[regno]) != VOIDmode)
          {
-           gcc_assert (!valreg); /* HAVE_untyped_call required.  */
+           gcc_assert (!valreg); /* have_untyped_call required.  */
 
            valreg = gen_rtx_REG (mode, regno);
          }
 
-      emit_call_insn (GEN_CALL_VALUE (valreg,
-                                     gen_rtx_MEM (FUNCTION_MODE, function),
-                                     const0_rtx, NULL_RTX, const0_rtx));
+      emit_insn (targetm.gen_call_value (valreg,
+                                        gen_rtx_MEM (FUNCTION_MODE, function),
+                                        const0_rtx, NULL_RTX, const0_rtx));
 
       emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg);
     }
   else
-#endif
     gcc_unreachable ();
 
   /* Find the CALL insn we just emitted, and attach the register usage
index 563672512beea3b448d8d552c0208036dc06f8bd..026cb53eed96508fee5a3634d26b9067b38a69fa 100644 (file)
@@ -291,7 +291,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
             cumulative_args_t args_so_far ATTRIBUTE_UNUSED)
 {
   rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
-  rtx call, funmem;
+  rtx call, funmem, pat;
   int already_popped = 0;
   HOST_WIDE_INT n_popped
     = targetm.calls.return_pops_args (fndecl, funtype, stack_size);
@@ -330,90 +330,50 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
   else if (fntree)
     set_mem_expr (funmem, build_simple_mem_ref (CALL_EXPR_FN (fntree)));
 
-#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
-  if ((ecf_flags & ECF_SIBCALL)
-      && HAVE_sibcall_pop && HAVE_sibcall_value_pop
-      && (n_popped > 0 || stack_size == 0))
+  if (ecf_flags & ECF_SIBCALL)
     {
-      rtx n_pop = GEN_INT (n_popped);
-      rtx pat;
-
-      /* If this subroutine pops its own args, record that in the call insn
-        if possible, for the sake of frame pointer elimination.  */
-
       if (valreg)
-       pat = GEN_SIBCALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx,
-                                    next_arg_reg, n_pop);
+       pat = targetm.gen_sibcall_value (valreg, funmem,
+                                        rounded_stack_size_rtx,
+                                        next_arg_reg, NULL_RTX);
       else
-       pat = GEN_SIBCALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg,
-                              n_pop);
-
-      emit_call_insn (pat);
-      already_popped = 1;
+       pat = targetm.gen_sibcall (funmem, rounded_stack_size_rtx,
+                                  next_arg_reg, GEN_INT (struct_value_size));
     }
-  else
-#endif
-
-#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop)
   /* If the target has "call" or "call_value" insns, then prefer them
      if no arguments are actually popped.  If the target does not have
      "call" or "call_value" insns, then we must use the popping versions
      even if the call has no arguments to pop.  */
-#if defined (HAVE_call) && defined (HAVE_call_value)
-  if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop
-      && n_popped > 0)
-#else
-  if (HAVE_call_pop && HAVE_call_value_pop)
-#endif
+  else if (n_popped > 0
+          || !(valreg
+               ? targetm.have_call_value ()
+               : targetm.have_call ()))
     {
       rtx n_pop = GEN_INT (n_popped);
-      rtx pat;
 
       /* If this subroutine pops its own args, record that in the call insn
         if possible, for the sake of frame pointer elimination.  */
 
       if (valreg)
-       pat = GEN_CALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx,
-                                 next_arg_reg, n_pop);
+       pat = targetm.gen_call_value_pop (valreg, funmem,
+                                         rounded_stack_size_rtx,
+                                         next_arg_reg, n_pop);
       else
-       pat = GEN_CALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg,
-                           n_pop);
+       pat = targetm.gen_call_pop (funmem, rounded_stack_size_rtx,
+                                   next_arg_reg, n_pop);
 
-      emit_call_insn (pat);
       already_popped = 1;
     }
   else
-#endif
-
-#if defined (HAVE_sibcall) && defined (HAVE_sibcall_value)
-  if ((ecf_flags & ECF_SIBCALL)
-      && HAVE_sibcall && HAVE_sibcall_value)
-    {
-      if (valreg)
-       emit_call_insn (GEN_SIBCALL_VALUE (valreg, funmem,
-                                          rounded_stack_size_rtx,
-                                          next_arg_reg, NULL_RTX));
-      else
-       emit_call_insn (GEN_SIBCALL (funmem, rounded_stack_size_rtx,
-                                    next_arg_reg,
-                                    GEN_INT (struct_value_size)));
-    }
-  else
-#endif
-
-#if defined (HAVE_call) && defined (HAVE_call_value)
-  if (HAVE_call && HAVE_call_value)
     {
       if (valreg)
-       emit_call_insn (GEN_CALL_VALUE (valreg, funmem, rounded_stack_size_rtx,
-                                       next_arg_reg, NULL_RTX));
+       pat = targetm.gen_call_value (valreg, funmem, rounded_stack_size_rtx,
+                                     next_arg_reg, NULL_RTX);
       else
-       emit_call_insn (GEN_CALL (funmem, rounded_stack_size_rtx, next_arg_reg,
-                                 GEN_INT (struct_value_size)));
+       pat = targetm.gen_call (funmem, rounded_stack_size_rtx, next_arg_reg,
+                               GEN_INT (struct_value_size));
     }
-  else
-#endif
-    gcc_unreachable ();
+  emit_insn (pat);
 
   /* Find the call we just emitted.  */
   rtx_call_insn *call_insn = last_call_insn ();
index 35255e91a95cdf20d52270470202f7499ba46bb2..f8c44683752130d8557dc160f7bb2b62147fb2c2 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index ca07cc7052bf0ca41a859cf38cb3b18d69dd1cf0..32bb36eec33d374bdad498295688d3f739e969ac 100644 (file)
@@ -3110,7 +3110,7 @@ alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
     }
 
   tmp = gen_rtx_MEM (QImode, func);
-  tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
+  tmp = emit_call_insn (gen_call_value (reg, tmp, const0_rtx,
                                        const0_rtx, const0_rtx));
   CALL_INSN_FUNCTION_USAGE (tmp) = usage;
   RTL_CONST_CALL_P (tmp) = 1;
index 7626d3f0233f27d3261274b3ea3cf2ed43af5557..5068f60ad6c87acc479e524f1b12d10cc5b404fd 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index eefb7fa773fbb5f9c90884f9a2ad5ae1586f949f..b6c20478f9c06e0c692c99643b79cde5a49933e7 100644 (file)
         size += GET_MODE_SIZE (GET_MODE (src));
       }
 
-    emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
-                                   const0_rtx));
+    emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL));
 
     size = 0;
 
index 8185b59b2822144212fb4602684eac426ab24b94..7b3b6efd3db206fb16a0f4f54e31768ed0188cb8 100644 (file)
@@ -583,7 +583,7 @@ cr16_function_arg (cumulative_args_t cum_v, machine_mode mode,
   /* function_arg () is called with this type just after all the args have 
      had their registers assigned. The rtx that function_arg returns from 
      this type is supposed to pass to 'gen_call' but currently it is not 
-     implemented (see macro GEN_CALL).  */
+     implemented.  */
   if (type == void_type_node)
     return NULL_RTX;
 
index e87cb6802e3920c186042bc696cdea99d9735941..bba67600d9650a5c93786190ce009434f67f6130 100644 (file)
     {
       int i;
 
-      emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+      emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
 
       for (i = 0; i < XVECLEN (operands[2], 0); i++)
        {
index 7f4195a9f2fa9462bf0b6297fa31c43d9890bfbd..463c8277b43ed404f7434a58862f5f90448dfcf6 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index a0079d5c97466cc8427e91c6e5828a449fd79e3b..f4ffd682415399352d19d322b11fedd2b539e40a 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index ad9289236ffe933550a8a94c06a7c9980e9d439c..46fc0f5719c68e7f1e5a45c4b154975466ed5fe9 100644 (file)
@@ -8248,7 +8248,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index 527ad985423cd141a62eb8fc0145ace7aaf340f9..e7d97df89a122402c853e3f8ed518b0b9645d43f 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, const0_rtx, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index 9665ee6da9bdc73b2b9316f7ed4cb54a580c3c76..5b9f0517b90831490d3a8473cf1331bb5d061c6f 100644 (file)
 
   /* Pass constm1 to indicate that it may expect a structure value, but
      we don't know what size it is.  */
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx));
 
   /* Save the function value registers.  */
   emit_move_insn (adjust_address (result, DImode, 0), valreg1);
index 75322e167219ad7427c5ce453e8b00eed82ee747..944953c34b2da0ef64bb72e4252f7a02cfae70c8 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index a97ebf9eb22be69074534c13631e156c75ee3687..b1e6b81e71f7ed5b9819e6fe30a208b688240c03 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index 969cb887a6c1da274ed5c9d26a472ac92c3855ba..370b6a4b5b298bd07f060ec9c85db4dcf4675505 100644 (file)
 {
   int i;
 
-  emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+  emit_call_insn (gen_call (operands[0], const0_rtx, NULL));
 
   for (i = 0; i < XVECLEN (operands[2], 0); i++)
     {
index e67a48ba83f126a62ca19fd2f61706a2bb70d487..0dedc8dc2aa421d994306d2582c4997013e7a4d9 100644 (file)
@@ -42,7 +42,6 @@ static int max_opno;
 static void max_operand_1 (rtx);
 static int num_operands (rtx);
 static void gen_proto (rtx);
-static void gen_macro (const char *, int, int);
 
 /* Count the number of match_operand's found.  */
 
@@ -92,32 +91,6 @@ num_operands (rtx insn)
   return max_opno + 1;
 }
 
-/* Print out a wrapper macro for a function which corrects the number
-   of arguments it takes.  Any missing arguments are assumed to be at
-   the end.  */
-static void
-gen_macro (const char *name, int real, int expect)
-{
-  int i;
-
-  gcc_assert (real <= expect);
-  gcc_assert (real);
-
-  /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */
-  fputs ("#define GEN_", stdout);
-  for (i = 0; name[i]; i++)
-    putchar (TOUPPER (name[i]));
-
-  putchar ('(');
-  for (i = 0; i < expect - 1; i++)
-    printf ("%c, ", i + 'A');
-  printf ("%c) gen_%s (", i + 'A', name);
-
-  for (i = 0; i < real - 1; i++)
-    printf ("(%c), ", i + 'A');
-  printf ("(%c))\n", i + 'A');
-}
-
 /* Print out prototype information for a generator function.  If the
    insn pattern has been elided, print out a dummy generator that
    does nothing.  */
@@ -130,25 +103,6 @@ gen_proto (rtx insn)
   const char *name = XSTR (insn, 0);
   int truth = maybe_eval_c_test (XSTR (insn, 2));
 
-  /* Many md files don't refer to the last two operands passed to the
-     call patterns.  This means their generator functions will be two
-     arguments too short.  Instead of changing every md file to touch
-     those operands, we wrap the prototypes in macros that take the
-     correct number of arguments.  */
-  if (name[0] == 'c' || name[0] == 's')
-    {
-      if (!strcmp (name, "call")
-         || !strcmp (name, "call_pop")
-         || !strcmp (name, "sibcall")
-         || !strcmp (name, "sibcall_pop"))
-       gen_macro (name, num, 4);
-      else if (!strcmp (name, "call_value")
-              || !strcmp (name, "call_value_pop")
-              || !strcmp (name, "sibcall_value")
-              || !strcmp (name, "sibcall_value_pop"))
-       gen_macro (name, num, 5);
-    }
-
   if (truth != 0)
     printf ("extern rtx        gen_%-*s (", max_id_len, name);
   else
index 9e00f13a2f9f0dcf9ad004fa97a7d6f7e8b1fc80..0480e17fac36ae4d4233eb52ee528d27c9ebb671 100644 (file)
@@ -93,6 +93,9 @@ static struct queue_elem **other_tail = &other_queue;
 static struct queue_elem *define_subst_attr_queue;
 static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
 
+/* Mapping from DEFINE_* rtxes to their location in the source file.  */
+static hash_map <rtx, file_location> *rtx_locs;
+
 static void remove_constraints (rtx);
 
 static int is_predicable (struct queue_elem *);
@@ -2619,9 +2622,24 @@ read_md_rtx (md_rtx_info *info)
   else
     info->index = -1;
 
+  if (!rtx_locs)
+    rtx_locs = new hash_map <rtx, file_location>;
+  rtx_locs->put (info->def, info->loc);
+
   return true;
 }
 
+/* Return the file location of DEFINE_* rtx X, which was previously
+   returned by read_md_rtx.  */
+file_location
+get_file_location (rtx x)
+{
+  gcc_assert (rtx_locs);
+  file_location *entry = rtx_locs->get (x);
+  gcc_assert (entry);
+  return *entry;
+}
+
 /* Return the number of possible INSN_CODEs.  Only meaningful once the
    whole file has been processed.  */
 unsigned int
index a15c36a10168dc55bb1d6c21490a6b818f9d2661..0199e398034460aaf71bcab17cb2045ec2f89298 100644 (file)
@@ -132,6 +132,7 @@ struct pattern_stats
 
 extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec);
 extern void compute_test_codes (rtx, file_location, char *);
+extern file_location get_file_location (rtx);
 extern const char *get_emit_function (rtx);
 extern bool needs_barrier_p (rtx);
 
index e5e291ecfd7daec2bb3ad107a7553117be2ccd50..9c8a2503ee2f2f47efdb037552c72ae542fc0440 100644 (file)
@@ -60,6 +60,43 @@ static hash_table <nofree_string_hash> *stubs;
    from the C condition to the function name.  */
 static hash_map <nofree_string_hash, const char *> *have_funcs;
 
+/* Return true if the part of the prototype at P is for an argument
+   name.  If so, point *END_OUT to the first character after the name.
+   If OPNO_OUT is nonnull, set *OPNO_OUT to the number of the associated
+   operand.  If REQUIRED_OUT is nonnull, set *REQUIRED_OUT to whether the
+   .md pattern is required to match the operand.  */
+
+static bool
+parse_argument (const char *p, const char **end_out,
+               unsigned int *opno_out = 0,
+               bool *required_out = 0)
+{
+  while (ISSPACE (*p))
+    p++;
+  if (p[0] == 'x' && ISDIGIT (p[1]))
+    {
+      p += 1;
+      if (required_out)
+       *required_out = true;
+    }
+  else if (p[0] == 'o' && p[1] == 'p' && p[2] == 't' && ISDIGIT (p[3]))
+    {
+      p += 3;
+      if (required_out)
+       *required_out = false;
+    }
+  else
+    return false;
+
+  char *endptr;
+  unsigned int opno = strtol (p, &endptr, 10);
+  if (opno_out)
+    *opno_out = opno;
+  *end_out = endptr;
+  return true;
+}
+
+
 /* Output hook definitions for pattern NAME, which has target-insns.def
    prototype PROTOTYPE.  */
 
@@ -78,21 +115,27 @@ def_target_insn (const char *name, const char *prototype)
   char *suffix = XALLOCAVEC (char, strlen (prototype) + 1);
   i = 0;
   unsigned int opno = 0;
+  unsigned int required_ops = 0;
+  unsigned int this_opno;
+  bool required_p;
   for (const char *p = prototype; *p; ++p)
-    if (*p == 'x' && ISDIGIT (p[1]))
+    if (parse_argument (p, &p, &this_opno, &required_p))
       {
-       /* This should be a parameter name of the form "x<OPNO>".
-          That doesn't contribute to the suffix, so skip ahead and
-          process the following character.  */
-       char *endptr;
-       if ((unsigned int) strtol (p + 1, &endptr, 10) != opno
-           || (*endptr != ',' && *endptr != ')'))
+       if (this_opno != opno || (*p != ',' && *p != ')'))
          {
            error ("invalid prototype for '%s'", name);
            exit (FATAL_EXIT_CODE);
          }
+       if (required_p && required_ops < opno)
+         {
+           error ("prototype for '%s' has required operands after"
+                  " optional operands", name);
+           exit (FATAL_EXIT_CODE);
+         }
        opno += 1;
-       p = endptr;
+       if (required_p)
+         required_ops = opno;
+       /* Skip over ')'s.  */
        if (*p == ',')
          suffix[i++] = '_';
       }
@@ -117,6 +160,22 @@ def_target_insn (const char *name, const char *prototype)
   const char *have_name = name;
   if (rtx insn = insns->find_with_hash (name, hash))
     {
+      pattern_stats stats;
+      get_pattern_stats (&stats, XVEC (insn, 1));
+      unsigned int actual_ops = stats.num_generator_args;
+      if (opno == required_ops && opno != actual_ops)
+       error_at (get_file_location (insn),
+                 "'%s' must have %d operands (excluding match_dups)",
+                 name, required_ops);
+      else if (actual_ops < required_ops)
+       error_at (get_file_location (insn),
+                 "'%s' must have at least %d operands (excluding match_dups)",
+                 name, required_ops);
+      else if (actual_ops > opno)
+       error_at (get_file_location (insn),
+                 "'%s' must have no more than %d operands"
+                 " (excluding match_dups)", name, opno);
+
       const char *test = XSTR (insn, 2);
       truth = maybe_eval_c_test (test);
       gcc_assert (truth != 0);
@@ -139,13 +198,23 @@ def_target_insn (const char *name, const char *prototype)
          have_name = entry;
        }
       printf ("\nstatic rtx_insn *\n");
-      printf ("target_gen_%s %s\n", name, prototype);
-      printf ("{\n");
+      printf ("target_gen_%s ", name);
+      /* Print the prototype with the argument names after ACTUAL_OPS
+        removed.  */
+      const char *p = prototype, *end;
+      while (*p)
+       if (parse_argument (p, &end, &this_opno) && this_opno >= actual_ops)
+         p = end;
+       else
+         fputc (*p++, stdout);
+
+      printf ("\n{\n");
       if (truth < 0)
        printf ("  gcc_checking_assert (targetm.have_%s ());\n", name);
       printf ("  return insnify (gen_%s (", name);
-      for (i = 0; i < opno; ++i)
-       printf ("%sx%d", i == 0 ? "" : ", ", i);
+      for (i = 0; i < actual_ops; ++i)
+       printf ("%s%s%d", i == 0 ? "" : ", ",
+               i < required_ops ? "x" : "opt", i);
       printf ("));\n");
       printf ("}\n");
     }
@@ -157,18 +226,11 @@ def_target_insn (const char *name, const char *prototype)
          *slot = xstrdup (suffix);
          printf ("\nstatic rtx_insn *\n");
          printf ("invalid_%s ", suffix);
+         /* Print the prototype with the argument names removed.  */
          const char *p = prototype;
          while (*p)
-           {
-             if (p[0] == 'x' && ISDIGIT (p[1]))
-               {
-                 char *endptr;
-                 strtol (p + 1, &endptr, 10);
-                 p = endptr;
-               }
-             else
-               fputc (*p++, stdout);
-           }
+           if (!parse_argument (p, &p))
+             fputc (*p++, stdout);
          printf ("\n{\n");
          printf ("  gcc_unreachable ();\n");
          printf ("}\n");
index d2041050ccf72eb4ad133cf7d6fc21922c64da9f..00e00273cd0132263df76c62421bc091fec604d7 100644 (file)
 
    where NAME is the name of the pattern and PROTOTYPE is its C prototype.
    The prototype should use parameter names of the form "x0", "x1", etc.
-   Patterns that take no operands should have a prototype "(void)".
+   for the operands that the .md pattern is required to have, followed by
+   parameter names of the form "optN" for operands that the .md pattern
+   may choose to ignore.  Patterns that never take operands should have
+   a prototype "(void)".
 
-   Instructions should be documented in md.texi rather than here.  */
+   Pattern names should be documented in md.texi rather than here.  */
 DEF_TARGET_INSN (allocate_stack, (rtx x0, rtx x1))
 DEF_TARGET_INSN (atomic_test_and_set, (rtx x0, rtx x1, rtx x2))
 DEF_TARGET_INSN (builtin_longjmp, (rtx x0))
 DEF_TARGET_INSN (builtin_setjmp_receiver, (rtx x0))
 DEF_TARGET_INSN (builtin_setjmp_setup, (rtx x0))
 DEF_TARGET_INSN (canonicalize_funcptr_for_compare, (rtx x0, rtx x1))
+DEF_TARGET_INSN (call, (rtx x0, rtx opt1, rtx opt2, rtx opt3))
+DEF_TARGET_INSN (call_pop, (rtx x0, rtx opt1, rtx opt2, rtx opt3))
+DEF_TARGET_INSN (call_value, (rtx x0, rtx x1, rtx opt2, rtx opt3, rtx opt4))
+DEF_TARGET_INSN (call_value_pop, (rtx x0, rtx x1, rtx opt2, rtx opt3,
+                                 rtx opt4))
 DEF_TARGET_INSN (casesi, (rtx x0, rtx x1, rtx x2, rtx x3, rtx x4))
 DEF_TARGET_INSN (check_stack, (rtx x0))
 DEF_TARGET_INSN (clear_cache, (rtx x0, rtx x1))
@@ -69,7 +77,10 @@ DEF_TARGET_INSN (return, (void))
 DEF_TARGET_INSN (save_stack_block, (rtx x0, rtx x1))
 DEF_TARGET_INSN (save_stack_function, (rtx x0, rtx x1))
 DEF_TARGET_INSN (save_stack_nonlocal, (rtx x0, rtx x1))
+DEF_TARGET_INSN (sibcall, (rtx x0, rtx opt1, rtx opt2, rtx opt3))
 DEF_TARGET_INSN (sibcall_epilogue, (void))
+DEF_TARGET_INSN (sibcall_value, (rtx x0, rtx x1, rtx opt2, rtx opt3,
+                                rtx opt4))
 DEF_TARGET_INSN (simple_return, (void))
 DEF_TARGET_INSN (split_stack_prologue, (void))
 DEF_TARGET_INSN (split_stack_space_check, (rtx x0, rtx x1))