]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gensupport: validate compact constraint modifiers
authorRichard Earnshaw <rearnsha@arm.com>
Mon, 14 Apr 2025 14:46:54 +0000 (15:46 +0100)
committerRichard Earnshaw <rearnsha@arm.com>
Thu, 8 May 2025 12:22:35 +0000 (13:22 +0100)
For constraints there are operand modifiers and constraint qualifiers.
Operand modifiers apply to all alternatives and must appear, in
traditional syntax before the first alternative.  Constraint
qualifiers, on the other hand must appear in each alternative to which
they apply.

There's no easy way to validate the distinction in the traditional md
format, but when using the new compact format we can enforce some
semantic checking of these characters to avoid some potentially
surprising code generation.

gcc/

* gensupport.cc (conlist::conlist): Pass a location to the constructor.
Only allow skipping of non-alpha-numeric characters when parsing a
number and only allow '=', '+' or '%'.  Add some error checking when
parsing an operand number.
(parse_section_layout): Pass the location to the conlist constructor.
(parse_section): Allow an optional list of forbidden characters.
If specified, reject strings containing them.
(convert_syntax): Reject '=', '+' or '%' in an alternative.

gcc/gensupport.cc

index 80f1976faf1d7ffa714fdb61b8595774e43234ce..ac0132860a98289ae36023008c507dccab0952d7 100644 (file)
@@ -656,7 +656,7 @@ public:
      i.e. if rtx is the relevant match_operand or match_scratch then
      [ns..ns + len) should equal itoa (XINT (rtx, 0)), and if set_attr then
      [ns..ns + len) should equal XSTR (rtx, 0).  */
-  conlist (const char *ns, unsigned int len, bool numeric)
+  conlist (const char *ns, unsigned int len, bool numeric, file_location loc)
   {
     /* Trim leading whitespaces.  */
     while (len > 0 && ISBLANK (*ns))
@@ -670,16 +670,26 @@ public:
       if (!ISBLANK (ns[i]))
        break;
 
-    /* Parse off any modifiers.  */
-    while (len > 0 && !ISALNUM (*ns))
-      {
-       con += *(ns++);
-       len--;
-      }
+    /* Only numeric values can have modifiers.  */
+    if (numeric)
+      /* Parse off any modifiers.  */
+      while (len > 0 && !ISALNUM (*ns))
+       {
+         if (*ns != '=' && *ns != '+' && *ns != '%')
+           error_at (loc, "`%c` is not a valid operand modifier", *ns);
+         con += *(ns++);
+         len--;
+       }
 
     name.assign (ns, len);
     if (numeric)
-      idx = strtol (name.c_str (), (char **)NULL, 10);
+      {
+       char *endstr;
+       /* There should only be a numeric value now... */
+       idx = strtol (name.c_str (), &endstr, 10);
+       if (*endstr != '\0')
+         error_at (loc, "operand number expected, found %s", name.c_str ());
+      }
   }
 
   /* Adds a character to the end of the string.  */
@@ -832,7 +842,7 @@ parse_section_layout (file_location loc, const char **templ, const char *label,
          *templ += len;
          if (val == ',')
            (*templ)++;
-         list.push_back (conlist (name_start, len, numeric));
+         list.push_back (conlist (name_start, len, numeric, loc));
        }
     }
 }
@@ -845,7 +855,8 @@ parse_section_layout (file_location loc, const char **templ, const char *label,
 
 static void
 parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no,
-              vec_conlist &list, file_location loc, const char *name)
+              vec_conlist &list, file_location loc, const char *name,
+              const char *invalid_chars = NULL)
 {
   unsigned int i;
 
@@ -856,6 +867,10 @@ parse_section (const char **templ, unsigned int n_elems, unsigned int alt_no,
       {
        if (**templ == 0 || **templ == '\n')
          fatal_at (loc, "missing ']'");
+       if (invalid_chars
+           && strchr (invalid_chars, **templ))
+         error_at (loc, "'%c' is not permitted in an alternative for a %s",
+                   **templ, name);
        list[i].add (**templ);
        if (**templ == ',')
          {
@@ -981,7 +996,7 @@ convert_syntax (rtx x, file_location loc)
          /* Parse the constraint list, then the attribute list.  */
          if (tconvec.size () > 0)
            parse_section (&templ, tconvec.size (), alt_no, tconvec, loc,
-                          "constraint");
+                          "constraint", "=+%");
 
          if (attrvec.size () > 0)
            {