@@ -10909,10 +10909,12 @@ A port might need to generate this pattern for a variable
ways of doing this. The first is to build the rtx for the pattern
directly from C++ code; this is a valid technique and avoids any risk
of combinatorial explosion. The second is to prefix the instruction
-name with the special character @samp{@@}. This tells GCC to generate
-the four additional functions below, where @var{name} is the name of
-the instruction without the @samp{@@} and without the @samp{<@dots{}>}
-placeholders.
+name with the special character @samp{@@}, which tells GCC to generate
+the four additional functions below. In each case, @var{name} is the
+name of the instruction without the leading @samp{@@} character,
+without the @samp{<@dots{}>} placeholders, and with any underscore
+before a @samp{<@dots{}>} placeholder removed if keeping it would
+lead to a double or trailing underscore.
@table @samp
@item insn_code maybe_code_for_@var{name} (@var{i1}, @var{i2}, @dots{})
@@ -46,29 +46,6 @@ gen_insn (md_rtx_info *info)
}
}
-/* Declare the maybe_code_for_* function for ONAME, and provide
- an inline definition of the assserting code_for_* wrapper. */
-
-static void
-handle_overloaded_code_for (overloaded_name *oname)
-{
- printf ("\nextern insn_code maybe_code_for_%s (", oname->name);
- for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
- printf ("%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
- printf (");\n");
-
- printf ("inline insn_code\ncode_for_%s (", oname->name);
- for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
- printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
- printf (")\n{\n 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"
- " gcc_assert (code != CODE_FOR_nothing);\n"
- " return code;\n"
- "}\n");
-}
-
int
main (int argc, const char **argv)
{
@@ -108,13 +85,8 @@ enum insn_code {\n\
printf ("\n};\n\
\n\
-const unsigned int NUM_INSN_CODES = %d;\n", get_num_insn_codes ());
-
- for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
- oname; oname = oname->next)
- handle_overloaded_code_for (oname);
-
- printf ("\n#endif /* GCC_INSN_CODES_H */\n");
+const unsigned int NUM_INSN_CODES = %d;\n\
+#endif /* GCC_INSN_CODES_H */\n", get_num_insn_codes ());
if (ferror (stdout) || fflush (stdout) || fclose (stdout))
return FATAL_EXIT_CODE;
@@ -761,7 +761,7 @@ print_overload_arguments (overloaded_name *oname)
printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
}
-/* Print code to test whether INSTANCE should be chosne, given that
+/* Print code to test whether INSTANCE should be chosen, given that
argument N of the overload is available as "arg<N>". */
static void
@@ -197,37 +197,6 @@ gen_insn (md_rtx_info *info)
obstack_grow (&obstack, &insn, sizeof (rtx));
}
-/* Declare the maybe_gen_* function for ONAME, and provide
- an inline definition of the assserting gen_* wrapper. */
-
-static void
-emit_overloaded_gen_proto (overloaded_name *oname)
-{
- unsigned int num_ops = num_operands (oname->first_instance->insn);
-
- printf ("\nextern rtx maybe_gen_%s (", oname->name);
- for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
- printf ("%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
- for (unsigned int i = 0; i < num_ops; ++i)
- printf (", rtx");
- printf (");\n");
-
- printf ("inline rtx\ngen_%s (", oname->name);
- for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
- printf ("%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
- for (unsigned int i = 0; i < num_ops; ++i)
- printf (", rtx x%d", i);
- printf (")\n{\n rtx res = maybe_gen_%s (", oname->name);
- for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
- printf ("%sarg%d", i == 0 ? "" : ", ", i);
- for (unsigned int i = 0; i < num_ops; ++i)
- printf (", x%d", i);
- printf (");\n"
- " gcc_assert (res);\n"
- " return res;\n"
- "}\n");
-}
-
int
main (int argc, const char **argv)
{
@@ -273,10 +242,6 @@ main (int argc, const char **argv)
for (insn_ptr = insns; *insn_ptr; insn_ptr++)
gen_proto (*insn_ptr);
- for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
- oname; oname = oname->next)
- emit_overloaded_gen_proto (oname);
-
puts ("\n#endif /* GCC_INSN_FLAGS_H */");
if (have_error || ferror (stdout) || fflush (stdout) || fclose (stdout))
@@ -104,6 +104,63 @@ open_outfile (const char *file_name)
return f;
}
+/* Declare the maybe_code_for_* function for ONAME, and provide
+ an inline definition of the assserting code_for_* wrapper. */
+
+static void
+handle_overloaded_code_for (FILE *file, overloaded_name *oname)
+{
+ fprintf (file, "\nextern insn_code maybe_code_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
+ fprintf (file, ");\n");
+
+ fprintf (file, "inline insn_code\ncode_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
+ fprintf (file, ")\n{\n insn_code code = maybe_code_for_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
+ fprintf (file,
+ ");\n"
+ " gcc_assert (code != CODE_FOR_nothing);\n"
+ " return code;\n"
+ "}\n");
+}
+
+/* Declare the maybe_gen_* function for ONAME, and provide
+ an inline definition of the assserting gen_* wrapper. */
+
+static void
+handle_overloaded_gen (FILE *file, overloaded_name *oname)
+{
+ pattern_stats stats;
+ get_pattern_stats (&stats, XVEC (oname->first_instance->insn, 1));
+
+ fprintf (file, "\nextern rtx maybe_gen_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s", i == 0 ? "" : ", ", oname->arg_types[i]);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ fprintf (file, ", rtx");
+ fprintf (file, ");\n");
+
+ fprintf (file, "inline rtx\ngen_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%s%s arg%d", i == 0 ? "" : ", ", oname->arg_types[i], i);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ fprintf (file, ", rtx x%d", i);
+ fprintf (file, ")\n{\n rtx res = maybe_gen_%s (", oname->name);
+ for (unsigned int i = 0; i < oname->arg_types.length (); ++i)
+ fprintf (file, "%sarg%d", i == 0 ? "" : ", ", i);
+ for (int i = 0; i < stats.num_generator_args; ++i)
+ fprintf (file, ", x%d", i);
+ fprintf (file,
+ ");\n"
+ " gcc_assert (res);\n"
+ " return res;\n"
+ "}\n");
+}
+
int
main (int argc, const char **argv)
{
@@ -220,7 +277,16 @@ main (int argc, const char **argv)
"optab_to_code (optab op)\n"
"{\n"
" return optab_to_code_[op];\n"
- "}\n"
+ "}\n");
+
+ for (overloaded_name *oname = rtx_reader_ptr->get_overloads ();
+ oname; oname = oname->next)
+ {
+ handle_overloaded_code_for (h_file, oname);
+ handle_overloaded_gen (h_file, oname);
+ }
+
+ fprintf (h_file,
"#endif\n"
"\n"
"extern const struct convert_optab_libcall_d convlib_def[NUM_CONVLIB_OPTABS];\n"
@@ -651,6 +651,7 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
char *base = copy, *start, *end;
overloaded_name tmp_oname;
tmp_oname.arg_types.create (current_iterators.length ());
+ bool pending_underscore_p = false;
while ((start = strchr (base, '<')) && (end = strchr (start, '>')))
{
*end = 0;
@@ -659,11 +660,28 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
fatal_with_file_and_line ("unknown iterator `%s'", start + 1);
*end = '>';
- /* Add the text between either the last '>' or the start of the string
- and this '<'. */
+ /* Remove a trailing underscore, so that we don't end a name
+ with "_" or turn "_<...>_" into "__". */
+ if (start != base && start[-1] == '_')
+ {
+ start -= 1;
+ pending_underscore_p = true;
+ }
+
+ /* Add the text between either the last '>' or the start of
+ the string and this '<'. */
obstack_grow (&m_string_obstack, base, start - base);
base = end + 1;
+ /* If there's a character we need to keep after the '>', check
+ whether we should prefix it with a previously-dropped '_'. */
+ if (base[0] != 0 && base[0] != '<')
+ {
+ if (pending_underscore_p && base[0] != '_')
+ obstack_1grow (&m_string_obstack, '_');
+ pending_underscore_p = false;
+ }
+
/* Record an argument for ITERATOR. */
iterators->safe_push (iterator);
tmp_oname.arg_types.safe_push (iterator->group->type);
@@ -671,6 +689,10 @@ md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators)
if (base == copy)
fatal_with_file_and_line ("no iterator attributes in name `%s'", name);
+ size_t length = obstack_object_size (&m_string_obstack);
+ if (length == 0)
+ fatal_with_file_and_line ("`%s' only contains iterator attributes", name);
+
/* Get the completed name. */
obstack_grow (&m_string_obstack, base, strlen (base) + 1);
char *new_name = XOBFINISH (&m_string_obstack, char *);