diff options
Diffstat (limited to 'gcc/gentarget-def.c')
-rw-r--r-- | gcc/gentarget-def.c | 106 |
1 files changed, 84 insertions, 22 deletions
diff --git a/gcc/gentarget-def.c b/gcc/gentarget-def.c index e5e291ecfd7..9c8a2503ee2 100644 --- a/gcc/gentarget-def.c +++ b/gcc/gentarget-def.c @@ -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"); |