diff options
Diffstat (limited to 'gcc/genoutput.cc')
-rw-r--r-- | gcc/genoutput.cc | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/gcc/genoutput.cc b/gcc/genoutput.cc index 25d0b8b..183ffc1 100644 --- a/gcc/genoutput.cc +++ b/gcc/genoutput.cc @@ -200,6 +200,8 @@ static const char indep_constraints[] = ",=+%*?!^$#&g"; static class constraint_data * constraints_by_letter_table[1 << CHAR_BIT]; +static hash_set<free_string_hash> used_reg_names; + static int mdep_constraint_len (const char *, file_location, int); static void note_constraint (md_rtx_info *); @@ -1156,6 +1158,45 @@ main (int argc, const char **argv) output_insn_data (); output_get_insn_name (); + /* Since genoutput has no information about hard register names we cannot + statically verify hard register names in constraints of the machine + description. Therefore, we have to do it at runtime. Although + verification shouldn't be too expensive, restrict it to checking builds. + */ + printf ("\n\n#if CHECKING_P\n"); + if (used_reg_names.is_empty ()) + printf ("void verify_reg_names_in_constraints () { }\n"); + else + { + size_t max_len = 0; + for (auto it = used_reg_names.begin (); it != used_reg_names.end (); ++it) + { + size_t len = strlen (*it); + if (len > max_len) + max_len = len; + } + printf ("void\nverify_reg_names_in_constraints ()\n{\n"); + printf (" static const char hregnames[%zu][%zu] = {\n", + used_reg_names.elements (), max_len + 1); + auto it = used_reg_names.begin (); + while (it != used_reg_names.end ()) + { + printf (" \"%s\"", *it); + ++it; + if (it != used_reg_names.end ()) + printf (","); + printf ("\n"); + } + printf (" };\n"); + printf (" for (size_t i = 0; i < %zu; ++i)\n", + used_reg_names.elements ()); + printf (" if (decode_reg_name (hregnames[i]) < 0)\n"); + printf (" internal_error (\"invalid register %%qs used in " + "constraint of machine description\", hregnames[i]);\n"); + printf ("}\n"); + } + printf ("#endif\n"); + fflush (stdout); return (ferror (stdout) != 0 || have_error ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE); @@ -1284,6 +1325,25 @@ mdep_constraint_len (const char *s, file_location loc, int opno) if (!strncmp (s, p->name, p->namelen)) return p->namelen; + if (*s == '{') + { + const char *end = s + 1; + while (*end != '}' && *end != '"' && *end != '\0') + ++end; + /* Similarly as in decode_hreg_constraint(), consider any hard register + name longer than a few characters as an error. */ + ptrdiff_t len = end - s; + if (*end == '}' && len > 1 && len < 31) + { + char *regname = new char[len]; + memcpy (regname, s + 1, len - 1); + regname[len - 1] = '\0'; + if (used_reg_names.add (regname)) + delete[] regname; + return len + 1; + } + } + error_at (loc, "error: undefined machine-specific constraint " "at this point: \"%s\"", s); message_at (loc, "note: in operand %d", opno); |