Check for invalid FAILs
authorRichard Sandiford <richard.sandiford@arm.com>
Wed, 2 Dec 2015 09:06:28 +0000 (09:06 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 2 Dec 2015 09:06:28 +0000 (09:06 +0000)
This patch makes it a compile-time error for an internal-fn optab
to FAIL.  There are certainly other optabs and patterns besides these
that aren't allowed to fail, but this at least deals with the immediate
point of controversy.

Tested normally on x86_64-linux-gnu.  Also tested by building one
configuration per cpu directory.  arc-elf and pdp11 didn't build
for unrelated reasons, but I checked that insn-emit.o built for
both without error.

gcc/
* Makefile.in (GENSUPPORT_H): New macro.
(build/gensupport.o, build/read-rtl.o, build/genattr.o)
(build/genattr-common.o, build/genattrtab.o, build/genautomata.o)
(build/gencodes.o, build/genconditions.o, build/genconfig.o)
(build/genconstants.o, build/genextract.o, build/genflags.o)
(build/gentarget-def.o): Use it.
(build/genemit.o): Likewise.  Depend on internal-fn.def.
* genopinit.c: Move block comment to optabs.def.
(optab_tag, optab_def): Move to gensupport.h
(pattern): Likewise, renaming to optab_pattern.
(match_pattern): Move to gensupport.c
(gen_insn): Use find_optab.
(patterns, pattern_cmp): Replace pattern with optab_pattern.
(main): Likewise.  Use num_optabs.
* optabs.def: Add comment that was previously in genopinit.c.
* gensupport.h (optab_tag): Moved from genopinit.c
(optab_def): Likewise, expanding commentary.
(optab_pattern): Likewise, after renaming from pattern.
(optabs, num_optabs, find_optab): Declare.
* gensupport.c (optabs): Moved from genopinit.c.
(num_optabs): New variable.
(match_pattern): Moved from genopinit.c.
(find_optab): New function, extracted from genopinit.c:gen_insn.
* genemit.c (nofail_optabs): New variable.
(emit_c_code): New function.
(gen_expand): Check whether the instruction is an optab that isn't
allowed to fail.  Call emit_c_code.
(gen_split): Call emit_c_code here too.
(main): Initialize nofail_optabs.  Don't emit FAIL and DONE here.

From-SVN: r231160

gcc/ChangeLog
gcc/Makefile.in
gcc/genemit.c
gcc/genopinit.c
gcc/gensupport.c
gcc/gensupport.h
gcc/optabs.def

index 8d30d04a53faa1d239897bcd96c7205c67d8e5ea..09bc243ef7fa81388d4c05f44cdf46ad7c1fd0d8 100644 (file)
@@ -1,3 +1,35 @@
+2015-12-02  Richard Sandiford  <richard.sandiford@arm.com>
+
+       * Makefile.in (GENSUPPORT_H): New macro.
+       (build/gensupport.o, build/read-rtl.o, build/genattr.o)
+       (build/genattr-common.o, build/genattrtab.o, build/genautomata.o)
+       (build/gencodes.o, build/genconditions.o, build/genconfig.o)
+       (build/genconstants.o, build/genextract.o, build/genflags.o)
+       (build/gentarget-def.o): Use it.
+       (build/genemit.o): Likewise.  Depend on internal-fn.def.
+       * genopinit.c: Move block comment to optabs.def.
+       (optab_tag, optab_def): Move to gensupport.h
+       (pattern): Likewise, renaming to optab_pattern.
+       (match_pattern): Move to gensupport.c
+       (gen_insn): Use find_optab.
+       (patterns, pattern_cmp): Replace pattern with optab_pattern.
+       (main): Likewise.  Use num_optabs.
+       * optabs.def: Add comment that was previously in genopinit.c.
+       * gensupport.h (optab_tag): Moved from genopinit.c
+       (optab_def): Likewise, expanding commentary.
+       (optab_pattern): Likewise, after renaming from pattern.
+       (optabs, num_optabs, find_optab): Declare.
+       * gensupport.c (optabs): Moved from genopinit.c.
+       (num_optabs): New variable.
+       (match_pattern): Moved from genopinit.c.
+       (find_optab): New function, extracted from genopinit.c:gen_insn.
+       * genemit.c (nofail_optabs): New variable.
+       (emit_c_code): New function.
+       (gen_expand): Check whether the instruction is an optab that isn't
+       allowed to fail.  Call emit_c_code.
+       (gen_split): Call emit_c_code here too.
+       (main): Initialize nofail_optabs.  Don't emit FAIL and DONE here.
+
 2015-12-02  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>
 
        * config/s390/predicates.md (const_mask_operand): New predicate.
index bee28797ae798e4f685259fde794a96ecfd564e6..d2d09f64f5fb0b1b3dbac387187b55ea798181dc 100644 (file)
@@ -978,6 +978,7 @@ GCC_PLUGIN_H = gcc-plugin.h highlev-plugin-common.h plugin.def \
 PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
 PLUGIN_VERSION_H = plugin-version.h configargs.h
 CONTEXT_H = context.h
+GENSUPPORT_H = gensupport.h read-md.h optabs.def
 
 #\f
 # Now figure out from those variables how to compile and link.
@@ -2476,7 +2477,7 @@ build/version.o:  version.c version.h \
 build/errors.o : errors.c $(BCONFIG_H) $(SYSTEM_H) errors.h
 build/gensupport.o: gensupport.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h  \
   $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) errors.h $(HASHTAB_H)            \
-  $(READ_MD_H) gensupport.h
+  $(READ_MD_H) $(GENSUPPORT_H)
 build/ggc-none.o : ggc-none.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h     \
   $(GGC_H)
 build/min-insn-modes.o : min-insn-modes.c $(BCONFIG_H) $(SYSTEM_H)     \
@@ -2487,7 +2488,7 @@ build/read-md.o: read-md.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h           \
   $(HASHTAB_H) errors.h $(READ_MD_H)
 build/read-rtl.o: read-rtl.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h      \
   $(GTM_H) $(RTL_BASE_H) $(OBSTACK_H) $(HASHTAB_H) $(READ_MD_H)                \
-  gensupport.h
+  $(GENSUPPORT_H)
 build/rtl.o: rtl.c $(BCONFIG_H) coretypes.h $(GTM_H) $(SYSTEM_H)       \
   $(RTL_H) $(GGC_H) errors.h
 build/vec.o : vec.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(VEC_H)      \
@@ -2509,38 +2510,38 @@ build/gencondmd.o : \
 
 # ...these are the programs themselves.
 build/genattr.o : genattr.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)     \
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/genattr-common.o : genattr-common.c $(RTL_BASE_H) $(BCONFIG_H)   \
-  $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/genattrtab.o : genattrtab.c $(RTL_BASE_H) $(OBSTACK_H)           \
   $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(GGC_H)      \
-  $(READ_MD_H) gensupport.h $(FNMATCH_H)
+  $(READ_MD_H) $(GENSUPPORT_H) $(FNMATCH_H)
 build/genautomata.o : genautomata.c $(RTL_BASE_H) $(OBSTACK_H)         \
   $(BCONFIG_H) $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(VEC_H)      \
-  $(HASHTAB_H) gensupport.h $(FNMATCH_H)
+  $(HASHTAB_H) $(GENSUPPORT_H) $(FNMATCH_H)
 build/gencheck.o : gencheck.c all-tree.def $(BCONFIG_H) $(GTM_H)       \
        $(SYSTEM_H) coretypes.h tree.def c-family/c-common.def          \
        $(lang_tree_files) gimple.def
 build/genchecksum.o : genchecksum.c $(BCONFIG_H) $(SYSTEM_H) $(MD5_H)
 build/gencodes.o : gencodes.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)   \
-  coretypes.h $(GTM_H) errors.h gensupport.h
+  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H)
 build/genconditions.o : genconditions.c $(RTL_BASE_H) $(BCONFIG_H)     \
   $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(HASHTAB_H) $(READ_MD_H)  \
-  gensupport.h
+  $(GENSUPPORT_H)
 build/genconfig.o : genconfig.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
-  coretypes.h $(GTM_H) errors.h gensupport.h
+  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H)
 build/genconstants.o : genconstants.c $(BCONFIG_H) $(SYSTEM_H)         \
   coretypes.h errors.h $(READ_MD_H)
 build/genemit.o : genemit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)     \
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) internal-fn.def
 build/genenums.o : genenums.c $(BCONFIG_H) $(SYSTEM_H)                 \
   coretypes.h errors.h $(READ_MD_H)
 build/genextract.o : genextract.c $(RTL_BASE_H) $(BCONFIG_H)           \
-  $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/genflags.o : genflags.c $(RTL_BASE_H) $(OBSTACK_H) $(BCONFIG_H)  \
-  $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  $(SYSTEM_H) coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/gentarget-def.o : gentarget-def.c $(BCONFIG_H) $(SYSTEM_H)       \
-  coretypes.h $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) gensupport.h        \
+  coretypes.h $(GTM_H) $(RTL_BASE_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)     \
   $(HASH_TABLE_H) target-insns.def
 build/gengenrtl.o : gengenrtl.c $(BCONFIG_H) $(SYSTEM_H) rtl.def
 
@@ -2582,20 +2583,20 @@ build/genmddeps.o: genmddeps.c $(BCONFIG_H) $(SYSTEM_H) coretypes.h     \
 build/genmodes.o : genmodes.c $(BCONFIG_H) $(SYSTEM_H) errors.h                \
   $(HASHTAB_H) machmode.def $(extra_modes_file)
 build/genopinit.o : genopinit.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
-  coretypes.h $(GTM_H) errors.h gensupport.h optabs.def
+  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) optabs.def
 build/genoutput.o : genoutput.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/genpeep.o : genpeep.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)     \
-  coretypes.h $(GTM_H) errors.h gensupport.h toplev.h $(DIAGNOSTIC_CORE_H)
+  coretypes.h $(GTM_H) errors.h $(GENSUPPORT_H) toplev.h $(DIAGNOSTIC_CORE_H)
 build/genpreds.o : genpreds.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)   \
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h $(OBSTACK_H)
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H) $(OBSTACK_H)
 build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H)   \
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h              \
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)           \
   $(HASH_TABLE_H) inchash.h
 build/genhooks.o : genhooks.c $(TARGET_DEF) $(C_TARGET_DEF)            \
   $(COMMON_TARGET_DEF) $(BCONFIG_H) $(SYSTEM_H) errors.h
 build/genmddump.o : genmddump.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
-  coretypes.h $(GTM_H) errors.h $(READ_MD_H) gensupport.h
+  coretypes.h $(GTM_H) errors.h $(READ_MD_H) $(GENSUPPORT_H)
 build/genmatch.o : genmatch.c $(BCONFIG_H) $(SYSTEM_H) \
   coretypes.h errors.h $(HASH_TABLE_H) hash-map.h $(GGC_H) is-a.h \
   tree.def builtins.def internal-fn.def
index e92f75750ecc63b9f443e61240e64cff65718237..cd85a809ae101d70db4127be479c63c622a60867 100644 (file)
@@ -51,6 +51,8 @@ struct clobber_ent
 
 static void output_peephole2_scratches (rtx);
 
+/* True for <X>_optab if that optab isn't allowed to fail.  */
+static bool nofail_optabs[NUM_OPTABS];
 \f
 static void
 print_code (RTX_CODE code)
@@ -285,6 +287,28 @@ gen_emit_seq (rtvec vec, char *used)
     }
 }
 \f
+/* Emit the given C code to the output file.  The code is allowed to
+   fail if CAN_FAIL_P.  NAME describes what we're generating,
+   for use in error messages.  */
+
+static void
+emit_c_code (const char *code, bool can_fail_p, const char *name)
+{
+  if (can_fail_p)
+    printf ("#define FAIL return (end_sequence (), _val)\n");
+  else
+    printf ("#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")"
+           " (void)0\n", name);
+  printf ("#define DONE return (_val = get_insns (),"
+         "end_sequence (), _val)\n");
+
+  print_md_ptr_loc (code);
+  printf ("%s\n", code);
+
+  printf ("#undef DONE\n");
+  printf ("#undef FAIL\n");
+}
+\f
 /* Generate the `gen_...' function for a DEFINE_INSN.  */
 
 static void
@@ -478,8 +502,15 @@ gen_expand (md_rtx_info *info)
 
       /* Output the special code to be executed before the sequence
         is generated.  */
-      print_md_ptr_loc (XSTR (expand, 3));
-      printf ("%s\n", XSTR (expand, 3));
+      optab_pattern p;
+      bool can_fail_p = true;
+      if (find_optab (&p, XSTR (expand, 0)))
+       {
+         gcc_assert (p.op < NUM_OPTABS);
+         if (nofail_optabs[p.op])
+           can_fail_p = false;
+       }
+      emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0));
 
       /* Output code to copy the arguments back out of `operands'
         (unless we aren't going to use them at all).  */
@@ -569,10 +600,7 @@ gen_split (md_rtx_info *info)
      before the actual construction.  */
 
   if (XSTR (split, 3))
-    {
-      print_md_ptr_loc (XSTR (split, 3));
-      printf ("%s\n", XSTR (split, 3));
-    }
+    emit_c_code (XSTR (split, 3), true, name);
 
   /* Output code to copy the arguments back out of `operands'  */
   for (i = 0; i < stats.num_operand_vars; i++)
@@ -724,6 +752,10 @@ main (int argc, char **argv)
   if (!init_rtx_reader_args (argc, argv))
     return (FATAL_EXIT_CODE);
 
+#define DEF_INTERNAL_OPTAB_FN(NAME, FLAGS, OPTAB, TYPE) \
+  nofail_optabs[OPTAB##_optab] = true;
+#include "internal-fn.def"
+
   /* Assign sequential codes to all entries in the machine description
      in parallel with the tables in insn-output.c.  */
 
@@ -764,8 +796,6 @@ from the machine description file `md'.  */\n\n");
   printf ("#include \"ggc.h\"\n");
   printf ("#include \"dumpfile.h\"\n");
   printf ("#include \"target.h\"\n\n");
-  printf ("#define FAIL return (end_sequence (), _val)\n");
-  printf ("#define DONE return (_val = get_insns (), end_sequence (), _val)\n\n");
 
   /* Read the machine description.  */
 
index 167815d561d50247226f6e014f937617d7304e86..3b91112e9ec34ef8cca2a71928203a195659a4ae 100644 (file)
@@ -35,246 +35,22 @@ static const char * const rtx_upname[] = {
 
 #undef DEF_RTL_EXPR
 
-
-/* The entries in optabs.def are categorized:
-     C: A "conversion" optab, which uses two modes; has libcall data.
-     N: A "normal" optab, which uses one mode; has libcall data.
-     D: A "direct" optab, which uses one mode; does not have libcall data.
-     V: An "oVerflow" optab.  Like N, but does not record its code in
-        code_to_optab.
-
-     CX, NX, VX: An extra pattern entry for a conversion or normal optab.
-
-   These patterns may be present in the MD file with names that contain
-   the mode(s) used and the name of the operation.  This array contains
-   a list of optabs that need to be initialized.  Within each name,
-   $a and $b are used to match a short mode name (the part of the mode
-   name not including `mode' and converted to lower-case).
-
-   $I means that only full integer modes should be considered for the
-   next mode, and $F means that only float modes should be considered.
-   $P means that both full and partial integer modes should be considered.
-   $Q means that only fixed-point modes should be considered.
-
-   The pattern may be NULL if the optab exists only for the libcalls
-   that we plan to attach to it, and there are no named patterns in
-   the md files.  */
-
-#define OPTAB_CL(name, pat, c, b, l)           name,
-#define OPTAB_CX(name, pat)
-#define OPTAB_CD(name, pat)                    name,
-#define OPTAB_NL(name, pat, c, b, s, l)                name,
-#define OPTAB_NC(name, pat, c)                 name,
-#define OPTAB_NX(name, pat)
-#define OPTAB_VL(name, pat, c, b, s, l)                name,
-#define OPTAB_VC(name, pat, c)                 name,
-#define OPTAB_VX(name, pat)
-#define OPTAB_DC(name, pat, c)                 name,
-#define OPTAB_D(name, pat)                     name,
-
-typedef enum optab_tag {
-  unknown_optab,
-#include "optabs.def"
-  NUM_OPTABS
-} optab;
-
-#undef OPTAB_CL
-#undef OPTAB_CX
-#undef OPTAB_CD
-#undef OPTAB_NL
-#undef OPTAB_NC
-#undef OPTAB_NX
-#undef OPTAB_VL
-#undef OPTAB_VC
-#undef OPTAB_VX
-#undef OPTAB_DC
-#undef OPTAB_D
-
-#define NS "NULL"
-#define ZS "'\\0'"
-#define OPTAB_CL(o, p, c, b, l)    { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
-#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
-#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
-#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
-#define OPTAB_NC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 3 },
-#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
-#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
-#define OPTAB_VC(o, p, c)          { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
-#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
-#define OPTAB_DC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 4 },
-#define OPTAB_D(o, p)  { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
-
-struct optab_def
-{
-  const char *name;
-  const char *pattern;
-  const char *base;
-  const char *suffix;
-  const char *libcall;
-  unsigned int op;
-  enum rtx_code fcode;
-  enum rtx_code rcode;
-  unsigned int kind;
-};
-
-static optab_def optabs[] = {
-  { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
-#include "optabs.def"
-};
-
-#undef OPTAB_CL
-#undef OPTAB_CX
-#undef OPTAB_CD
-#undef OPTAB_NL
-#undef OPTAB_NC
-#undef OPTAB_NX
-#undef OPTAB_VL
-#undef OPTAB_VC
-#undef OPTAB_VX
-#undef OPTAB_DC
-#undef OPTAB_D
-
 /* Vector in which to collect insns that match.  */
-
-struct pattern
-{
-  const char *name;
-  unsigned int op;
-  unsigned int m1, m2;
-  unsigned int sort_num;
-};
-
-
-static vec<pattern> patterns;
-
-static bool
-match_pattern (pattern *p, const char *name, const char *pat)
-{
-  bool force_float = false;
-  bool force_int = false;
-  bool force_partial_int = false;
-  bool force_fixed = false;
-
-  if (pat == NULL)
-    return false;
-  for (; ; ++pat)
-    {
-      if (*pat != '$')
-       {
-         if (*pat != *name++)
-           return false;
-         if (*pat == '\0')
-           return true;
-         continue;
-       }
-      switch (*++pat)
-       {
-       case 'I':
-         force_int = 1;
-         break;
-       case 'P':
-         force_partial_int = 1;
-         break;
-       case 'F':
-         force_float = 1;
-         break;
-       case 'Q':
-         force_fixed = 1;
-         break;
-
-       case 'a':
-       case 'b':
-         {
-           int i;
-
-           /* This loop will stop at the first prefix match, so
-              look through the modes in reverse order, in case
-              there are extra CC modes and CC is a prefix of the
-              CC modes (as it should be).  */
-           for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
-             {
-               const char *p, *q;
-               for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
-                 if (TOLOWER (*p) != *q)
-                   break;
-               if (*p == 0
-                   && (! force_int || mode_class[i] == MODE_INT
-                       || mode_class[i] == MODE_VECTOR_INT)
-                   && (! force_partial_int
-                       || mode_class[i] == MODE_INT
-                       || mode_class[i] == MODE_PARTIAL_INT
-                       || mode_class[i] == MODE_VECTOR_INT)
-                   && (! force_float
-                       || mode_class[i] == MODE_FLOAT
-                       || mode_class[i] == MODE_DECIMAL_FLOAT
-                       || mode_class[i] == MODE_COMPLEX_FLOAT
-                       || mode_class[i] == MODE_VECTOR_FLOAT)
-                   && (! force_fixed
-                       || mode_class[i] == MODE_FRACT
-                       || mode_class[i] == MODE_UFRACT
-                       || mode_class[i] == MODE_ACCUM
-                       || mode_class[i] == MODE_UACCUM
-                       || mode_class[i] == MODE_VECTOR_FRACT
-                       || mode_class[i] == MODE_VECTOR_UFRACT
-                       || mode_class[i] == MODE_VECTOR_ACCUM
-                       || mode_class[i] == MODE_VECTOR_UACCUM))
-                 break;
-             }
-
-           if (i < 0)
-             return false;
-           name += strlen (GET_MODE_NAME (i));
-           if (*pat == 'a')
-             p->m1 = i;
-           else
-             p->m2 = i;
-
-           force_int = false;
-           force_partial_int = false;
-           force_float = false;
-           force_fixed = false;
-         }
-         break;
-
-       default:
-         gcc_unreachable ();
-       }
-    }
-}
+static vec<optab_pattern> patterns;
 
 static void
 gen_insn (md_rtx_info *info)
 {
-  rtx insn = info->def;
-  const char *name = XSTR (insn, 0);
-  pattern p;
-  unsigned pindex;
-
-  /* Don't mention "unnamed" instructions.  */
-  if (*name == 0 || *name == '*')
-    return;
-  p.name = name;
-
-  /* See if NAME matches one of the patterns we have for the optabs
-     we know about.  */
-  for (pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
-    {
-      p.m1 = p.m2 = 0;
-      if (match_pattern (&p, name, optabs[pindex].pattern))
-       {
-         p.op = optabs[pindex].op;
-         p.sort_num = (p.op << 16) | (p.m2 << 8) | p.m1;
-         patterns.safe_push (p);
-         return;
-       }
-    }
+  optab_pattern p;
+  if (find_optab (&p, XSTR (info->def, 0)))
+    patterns.safe_push (p);
 }
 
 static int
 pattern_cmp (const void *va, const void *vb)
 {
-  const pattern *a = (const pattern *)va;
-  const pattern *b = (const pattern *)vb;
+  const optab_pattern *a = (const optab_pattern *)va;
+  const optab_pattern *b = (const optab_pattern *)vb;
   return a->sort_num - b->sort_num;
 }
 
@@ -333,7 +109,7 @@ main (int argc, char **argv)
 {
   FILE *h_file, *s_file;
   unsigned int i, j, n, last_kind[5];
-  pattern *p;
+  optab_pattern *p;
 
   progname = "genopinit";
 
@@ -365,7 +141,7 @@ main (int argc, char **argv)
 
   /* Now that we've handled the "extra" patterns, eliminate them from
      the optabs array.  That way they don't get in the way below.  */
-  n = ARRAY_SIZE (optabs);
+  n = num_optabs;
   for (i = 0; i < n; )
     if (optabs[i].base == NULL)
       optabs[i] = optabs[--n];
index 484ead2f3e700a4695453fcc487ca12f6cf23b49..7969060c117f7d207bb667ef907998513c489ccd 100644 (file)
@@ -3061,3 +3061,161 @@ needs_barrier_p (rtx x)
          && GET_CODE (SET_DEST (x)) == PC
          && GET_CODE (SET_SRC (x)) == LABEL_REF);
 }
+
+#define NS "NULL"
+#define ZS "'\\0'"
+#define OPTAB_CL(o, p, c, b, l)    { #o, p, #b, ZS, #l, o, c, UNKNOWN, 1 },
+#define OPTAB_CX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 1 },
+#define OPTAB_CD(o, p) { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 2 },
+#define OPTAB_NL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, c, 3 },
+#define OPTAB_NC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 3 },
+#define OPTAB_NX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
+#define OPTAB_VL(o, p, c, b, s, l) { #o, p, #b, #s, #l, o, c, UNKNOWN, 3 },
+#define OPTAB_VC(o, p, c)          { #o, p, NS, ZS, NS, o, c, UNKNOWN, 3 },
+#define OPTAB_VX(o, p) { #o, p, NULL, NULL, NULL, o, UNKNOWN, UNKNOWN, 3 },
+#define OPTAB_DC(o, p, c)          { #o, p, NS, ZS, NS, o, c, c, 4 },
+#define OPTAB_D(o, p)  { #o, p, NS, ZS, NS, o, UNKNOWN, UNKNOWN, 4 },
+
+/* An array of all optabs.  Note that the same optab can appear more
+   than once, with a different pattern.  */
+optab_def optabs[] = {
+  { "unknown_optab", NULL, NS, ZS, NS, unknown_optab, UNKNOWN, UNKNOWN, 0 },
+#include "optabs.def"
+};
+
+/* The number of entries in optabs[].  */
+unsigned int num_optabs = ARRAY_SIZE (optabs);
+
+#undef OPTAB_CL
+#undef OPTAB_CX
+#undef OPTAB_CD
+#undef OPTAB_NL
+#undef OPTAB_NC
+#undef OPTAB_NX
+#undef OPTAB_VL
+#undef OPTAB_VC
+#undef OPTAB_VX
+#undef OPTAB_DC
+#undef OPTAB_D
+
+/* Return true if instruction NAME matches pattern PAT, storing information
+   about the match in P if so.  */
+
+static bool
+match_pattern (optab_pattern *p, const char *name, const char *pat)
+{
+  bool force_float = false;
+  bool force_int = false;
+  bool force_partial_int = false;
+  bool force_fixed = false;
+
+  if (pat == NULL)
+    return false;
+  for (; ; ++pat)
+    {
+      if (*pat != '$')
+       {
+         if (*pat != *name++)
+           return false;
+         if (*pat == '\0')
+           return true;
+         continue;
+       }
+      switch (*++pat)
+       {
+       case 'I':
+         force_int = 1;
+         break;
+       case 'P':
+         force_partial_int = 1;
+         break;
+       case 'F':
+         force_float = 1;
+         break;
+       case 'Q':
+         force_fixed = 1;
+         break;
+
+       case 'a':
+       case 'b':
+         {
+           int i;
+
+           /* This loop will stop at the first prefix match, so
+              look through the modes in reverse order, in case
+              there are extra CC modes and CC is a prefix of the
+              CC modes (as it should be).  */
+           for (i = (MAX_MACHINE_MODE) - 1; i >= 0; i--)
+             {
+               const char *p, *q;
+               for (p = GET_MODE_NAME (i), q = name; *p; p++, q++)
+                 if (TOLOWER (*p) != *q)
+                   break;
+               if (*p == 0
+                   && (! force_int || mode_class[i] == MODE_INT
+                       || mode_class[i] == MODE_VECTOR_INT)
+                   && (! force_partial_int
+                       || mode_class[i] == MODE_INT
+                       || mode_class[i] == MODE_PARTIAL_INT
+                       || mode_class[i] == MODE_VECTOR_INT)
+                   && (! force_float
+                       || mode_class[i] == MODE_FLOAT
+                       || mode_class[i] == MODE_DECIMAL_FLOAT
+                       || mode_class[i] == MODE_COMPLEX_FLOAT
+                       || mode_class[i] == MODE_VECTOR_FLOAT)
+                   && (! force_fixed
+                       || mode_class[i] == MODE_FRACT
+                       || mode_class[i] == MODE_UFRACT
+                       || mode_class[i] == MODE_ACCUM
+                       || mode_class[i] == MODE_UACCUM
+                       || mode_class[i] == MODE_VECTOR_FRACT
+                       || mode_class[i] == MODE_VECTOR_UFRACT
+                       || mode_class[i] == MODE_VECTOR_ACCUM
+                       || mode_class[i] == MODE_VECTOR_UACCUM))
+                 break;
+             }
+
+           if (i < 0)
+             return false;
+           name += strlen (GET_MODE_NAME (i));
+           if (*pat == 'a')
+             p->m1 = i;
+           else
+             p->m2 = i;
+
+           force_int = false;
+           force_partial_int = false;
+           force_float = false;
+           force_fixed = false;
+         }
+         break;
+
+       default:
+         gcc_unreachable ();
+       }
+    }
+}
+
+/* Return true if NAME is the name of an optab, describing it in P if so.  */
+
+bool
+find_optab (optab_pattern *p, const char *name)
+{
+  if (*name == 0 || *name == '*')
+    return false;
+
+  /* See if NAME matches one of the patterns we have for the optabs
+     we know about.  */
+  for (unsigned int pindex = 0; pindex < ARRAY_SIZE (optabs); pindex++)
+    {
+      p->m1 = p->m2 = 0;
+      if (match_pattern (p, name, optabs[pindex].pattern))
+       {
+         p->name = name;
+         p->op = optabs[pindex].op;
+         p->sort_num = (p->op << 16) | (p->m2 << 8) | p->m1;
+         return true;
+       }
+    }
+  return false;
+}
index 0199e398034460aaf71bcab17cb2045ec2f89298..456efa0c7d1558113ae1cb8db69d27b71f537073 100644 (file)
@@ -39,6 +39,91 @@ struct md_rtx_info {
   int index;
 };
 
+#define OPTAB_CL(name, pat, c, b, l)           name,
+#define OPTAB_CX(name, pat)
+#define OPTAB_CD(name, pat)                    name,
+#define OPTAB_NL(name, pat, c, b, s, l)                name,
+#define OPTAB_NC(name, pat, c)                 name,
+#define OPTAB_NX(name, pat)
+#define OPTAB_VL(name, pat, c, b, s, l)                name,
+#define OPTAB_VC(name, pat, c)                 name,
+#define OPTAB_VX(name, pat)
+#define OPTAB_DC(name, pat, c)                 name,
+#define OPTAB_D(name, pat)                     name,
+
+/* Enumerates all optabs.  */
+typedef enum optab_tag {
+  unknown_optab,
+#include "optabs.def"
+  NUM_OPTABS
+} optab;
+
+#undef OPTAB_CL
+#undef OPTAB_CX
+#undef OPTAB_CD
+#undef OPTAB_NL
+#undef OPTAB_NC
+#undef OPTAB_NX
+#undef OPTAB_VL
+#undef OPTAB_VC
+#undef OPTAB_VX
+#undef OPTAB_DC
+#undef OPTAB_D
+
+/* Describes one entry in optabs.def.  */
+struct optab_def
+{
+  /* The name of the optab (e.g. "add_optab").  */
+  const char *name;
+
+  /* The pattern that matching define_expands and define_insns have.
+     See the comment at the head of optabs.def for details.  */
+  const char *pattern;
+
+  /* The initializers (in the form of C code) for the libcall_basename,
+     libcall_suffix and libcall_gen fields of (convert_)optab_libcall_d.  */
+  const char *base;
+  const char *suffix;
+  const char *libcall;
+
+  /* The optab's enum value.  */
+  unsigned int op;
+
+  /* The value returned by optab_to_code (OP).  */
+  enum rtx_code fcode;
+
+  /* CODE if code_to_optab (CODE) should return OP, otherwise UNKNOWN.  */
+  enum rtx_code rcode;
+
+  /* 1: conversion optabs with libcall data,
+     2: conversion optabs without libcall data,
+     3: non-conversion optabs with libcall data ("normal" and "overflow"
+        optabs in the optabs.def comment)
+     4: non-conversion optabs without libcall data ("direct" optabs).  */
+  unsigned int kind;
+};
+
+extern optab_def optabs[];
+extern unsigned int num_optabs;
+
+/* Information about an instruction name that matches an optab pattern.  */
+struct optab_pattern
+{
+  /* The name of the instruction.  */
+  const char *name;
+
+  /* The matching optab.  */
+  unsigned int op;
+
+  /* The optab modes.  M2 is only significant for conversion optabs;
+     it is zero otherwise.  */
+  unsigned int m1, m2;
+
+  /* An index that provides a lexicographical sort of (OP, M2, M1).
+     Used by genopinit.c.  */
+  unsigned int sort_num;
+};
+
 extern rtx add_implicit_parallel (rtvec);
 extern bool init_rtx_reader_args_cb (int, char **, bool (*)(const char *));
 extern bool init_rtx_reader_args (int, char **);
@@ -135,5 +220,6 @@ 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);
+extern bool find_optab (optab_pattern *, const char *);
 
 #endif /* GCC_GENSUPPORT_H */
index 20e4225d7332d41d0a32f154444e059ce23d1fb5..8feb3942ac5fa893ac323d5bae216d4108e1fcf9 100644 (file)
@@ -17,8 +17,29 @@ You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
-/* Entries here are categorized C, D, N, V.  See genopinit.c for details
-   on the meaning of the categories and for the pattern dollar codes.  */
+/* The entries in optabs.def are categorized:
+     C: A "conversion" optab, which uses two modes; has libcall data.
+     N: A "normal" optab, which uses one mode; has libcall data.
+     D: A "direct" optab, which uses one mode; does not have libcall data.
+     V: An "oVerflow" optab.  Like N, but does not record its code in
+        code_to_optab.
+
+     CX, NX, VX: An extra pattern entry for a conversion or normal optab.
+
+   These patterns may be present in the MD file with names that contain
+   the mode(s) used and the name of the operation.  This array contains
+   a list of optabs that need to be initialized.  Within each name,
+   $a and $b are used to match a short mode name (the part of the mode
+   name not including `mode' and converted to lower-case).
+
+   $I means that only full integer modes should be considered for the
+   next mode, and $F means that only float modes should be considered.
+   $P means that both full and partial integer modes should be considered.
+   $Q means that only fixed-point modes should be considered.
+
+   The pattern may be NULL if the optab exists only for the libcalls
+   that we plan to attach to it, and there are no named patterns in
+   the md files.  */
 
 /* The extension libcalls are used for float extension.  */
 OPTAB_CL(sext_optab, "extend$b$a2", SIGN_EXTEND, "extend", gen_extend_conv_libfunc)