]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
genoutput: Verify hard register constraints
authorStefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
Mon, 21 Jul 2025 11:05:26 +0000 (13:05 +0200)
committerStefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
Mon, 21 Jul 2025 11:05:26 +0000 (13:05 +0200)
Since genoutput has no information about hard register names we cannot
statically verify those 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.  This should be
sufficient since hard register constraints in machine descriptions
probably change rarely, and each commit should be tested with checking
anyway, or at the very least before a release is taken.

gcc/ChangeLog:

* genoutput.cc (main): Emit function
verify_reg_names_in_constraints() for run-time validation.
(mdep_constraint_len): Deal with hard register constraints.
* output.h (verify_reg_names_in_constraints): New function
declaration.
* toplev.cc (backend_init): If checking is enabled, call into
verify_reg_names_in_constraints().

gcc/genoutput.cc
gcc/output.h
gcc/toplev.cc

index 1157f820cf4b955b784d36b5fc245927f02eeb44..183ffc1470adf6f2c712884f587274c80d9d8a77 100644 (file)
@@ -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 *);
 \f
@@ -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);
@@ -1294,6 +1335,11 @@ mdep_constraint_len (const char *s, file_location loc, int opno)
       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;
        }
     }
index 372d63c5f5c752dd328e19b2027df220cd42875b..0c329ffac3cd3185f95d955a46c0268c1fc6b36c 100644 (file)
@@ -639,4 +639,6 @@ extern int default_address_cost (rtx, machine_mode, addr_space_t, bool);
 /* Stack usage.  */
 extern void output_stack_usage (void);
 
+extern void verify_reg_names_in_constraints ();
+
 #endif /* ! GCC_OUTPUT_H */
index 00a8ccb7a6924afe45cf47db1b9f5163c4c6459f..931466ca6324e75fd89496bd1de22e44484622df 100644 (file)
@@ -1815,6 +1815,10 @@ backend_init_target (void)
 static void
 backend_init (void)
 {
+#if CHECKING_P
+  verify_reg_names_in_constraints ();
+#endif
+
   init_emit_once ();
 
   init_rtlanal ();