On Wed, Nov 06, 2024 at 09:08:10AM +0100, Richard Biener wrote:
> It would probably be cleanest to have a separate print modifier for
> "symbol for assembler label definition" or so, but given this feature

See the patch I'll post next.

> targets existing uses those already know how to emit the definition
> without any operand or print modifier - something that should continue
> to work.  So maybe we should document that there isn't any print
> modifier and users need to arrange for mangling for themselves?
> 
> Otherwise I expected a symbol definition to be an asm output,
> not an input, but that's probably a bikeshedding minor detail.

I've considered that, but it would be much harder internally (output
operands generally need an lvalue, so this would need to be an exception
everywhere) and the operand argument is address of something (especially
so that one can just use function names in the operand and having another
exception to avoid function to function-pointer or array to pointer
promotions given specific constraints would be a nightmare), so that
certainly isn't modified.

Anyway, testing showed that @ isn't a good character, while the generic
code doesn't mention @ anywhere, some targets use @ in the output
constraints for the =@cc<something> syntax of testing flags;
while the @ I was proposing was an input constraint and in theory I could
just remove that
+       case '@':
+         error ("%<@%> constraint used for output operand");
+         return false;
hunk from the patch, if @ means something different in output
vs. input constraints, it would just confuse people.

So, here is the patch reworked to use : instead of @.
Mnemotechnically, : is better, the : character is what is used
in many assemblers after the symbol names for the symbol definitions.

2024-11-06  Jakub Jelinek  <ja...@redhat.com>

gcc/
        * genpreds.cc (mangle): Add ':' mangling.
        (add_constraint): Allow : constraint.
        * common.md (:): New define_constraint.
        * stmt.cc (parse_output_constraint): Diagnose "=:".
        (parse_input_constraint): Handle ":" and diagnose invalid
        uses.
        * doc/md.texi (Simple Constraints): Document ":" constraint.
gcc/c/
        * c-typeck.cc (build_asm_expr): Diagnose invalid ":" constraint
        uses.
gcc/cp/
        * semantics.cc (finish_asm_stmt): Diagnose invalid ":" constraint
        uses.
gcc/testsuite/
        * c-c++-common/toplevel-asm-4.c: New test.
        * c-c++-common/toplevel-asm-5.c: New test.

--- gcc/genpreds.cc.jj  2024-02-10 11:25:10.404468273 +0100
+++ gcc/genpreds.cc     2024-11-05 14:57:14.193060528 +0100
@@ -753,6 +753,7 @@ mangle (const char *name)
       case '_': obstack_grow (rtl_obstack, "__", 2); break;
       case '<':        obstack_grow (rtl_obstack, "_l", 2); break;
       case '>':        obstack_grow (rtl_obstack, "_g", 2); break;
+      case ':': obstack_grow (rtl_obstack, "_c", 2); break;
       default: obstack_1grow (rtl_obstack, *name); break;
       }
 
@@ -797,12 +798,13 @@ add_constraint (const char *name, const
   for (p = name; *p; p++)
     if (!ISALNUM (*p))
       {
-       if (*p == '<' || *p == '>' || *p == '_')
+       if (*p == '<' || *p == '>' || *p == '_' || *p == ':')
          need_mangled_name = true;
        else
          {
            error_at (loc, "constraint name '%s' must be composed of letters,"
-                     " digits, underscores, and angle brackets", name);
+                     " digits, underscores, colon and angle brackets",
+                     name);
            return;
          }
       }
--- gcc/common.md.jj    2024-01-03 11:51:24.519828508 +0100
+++ gcc/common.md       2024-11-05 14:51:29.098989927 +0100
@@ -100,6 +100,11 @@ (define_constraint "s"
        (match_test "!CONST_SCALAR_INT_P (op)")
        (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
 
+(define_constraint ":"
+  "Defines a symbol."
+  (and (match_test "CONSTANT_P (op)")
+       (match_test "!CONST_SCALAR_INT_P (op)")))
+
 (define_constraint "n"
   "Matches a non-symbolic integer constant."
   (and (match_test "CONST_SCALAR_INT_P (op)")
--- gcc/stmt.cc.jj      2024-10-25 10:00:29.523767070 +0200
+++ gcc/stmt.cc 2024-11-05 18:31:11.518948252 +0100
@@ -278,6 +278,10 @@ parse_output_constraint (const char **co
          error ("matching constraint not valid in output operand");
          return false;
 
+       case ':':
+         error ("%<:%> constraint used for output operand");
+         return false;
+
        case '<':  case '>':
          /* ??? Before flow, auto inc/dec insns are not supposed to exist,
             excepting those that expand_call created.  So match memory
@@ -325,6 +329,7 @@ parse_input_constraint (const char **con
   size_t c_len = strlen (constraint);
   size_t j;
   bool saw_match = false;
+  bool at_checked = false;
 
   /* Assume the constraint doesn't allow the use of either
      a register or memory.  */
@@ -362,6 +367,21 @@ parse_input_constraint (const char **con
       case 'N':  case 'O':  case 'P':  case ',':
        break;
 
+      case ':':
+       /* Verify that if : is used, it is just ":" or say ":,:" but not
+          mixed with other constraints or say ",:,," etc.  */
+       if (!at_checked)
+         {
+           for (size_t k = 0; k < c_len; ++k)
+             if (constraint[k] != ((k & 1) ? ',' : ':') || (c_len & 1) == 0)
+               {
+                 error ("%<:%> constraint mixed with other constraints");
+                 return false;
+               } 
+           at_checked = true;
+         }
+       break;
+
        /* Whether or not a numeric constraint allows a register is
           decided by the matching constraint, and so there is no need
           to do anything special with them.  We must handle them in
--- gcc/doc/md.texi.jj  2024-10-16 14:41:45.553757783 +0200
+++ gcc/doc/md.texi     2024-11-05 18:46:30.795896301 +0100
@@ -1504,6 +1504,13 @@ as the predicate in the @code{match_oper
 the mode specified in the @code{match_operand} as the mode of the memory
 reference for which the address would be valid.
 
+@cindex @samp{:} in constraint
+@item @samp{:}
+This constraint, allowed only in input operands, says the inline @code{asm}
+pattern defines specific function or variable symbol.  The constraint
+shouldn't be mixed with other constraints on the same operand and
+the operand should be address of a function or non-automatic variable.
+
 @cindex other register constraints
 @cindex extensible constraints
 @item @var{other-letters}
--- gcc/c/c-typeck.cc.jj        2024-11-05 14:44:35.904892730 +0100
+++ gcc/c/c-typeck.cc   2024-11-05 18:25:34.837723892 +0100
@@ -12246,6 +12246,20 @@ build_asm_expr (location_t loc, tree str
              error_at (loc, "invalid constraint outside of a function");
              input = error_mark_node;
            }
+         if (constraint[0] == ':' && input != error_mark_node)
+           {
+             tree t = input;
+             STRIP_NOPS (t);
+             if (TREE_CODE (t) != ADDR_EXPR
+                 || !(TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
+                      || (VAR_P (TREE_OPERAND (t, 0))
+                          && is_global_var (TREE_OPERAND (t, 0)))))
+               {
+                 error_at (loc, "%<:%> constraint operand is not address "
+                                "of a function or non-automatic variable");
+                 input = error_mark_node;
+               }
+           }
        }
       else
        input = error_mark_node;
--- gcc/cp/semantics.cc.jj      2024-11-05 14:44:35.911892630 +0100
+++ gcc/cp/semantics.cc 2024-11-05 18:27:05.162442682 +0100
@@ -2325,6 +2325,20 @@ finish_asm_stmt (location_t loc, int vol
                  error_at (loc, "invalid constraint outside of a function");
                  operand = error_mark_node;
                }
+             if (constraint[0] == ':' && operand != error_mark_node)
+               {
+                 tree t = operand;
+                 STRIP_NOPS (t);
+                 if (TREE_CODE (t) != ADDR_EXPR
+                     || !(TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
+                          || (VAR_P (TREE_OPERAND (t, 0))
+                              && is_global_var (TREE_OPERAND (t, 0)))))
+                   {
+                     error_at (loc, "%<:%> constraint operand is not address "
+                               "of a function or non-automatic variable");
+                     operand = error_mark_node;
+                   }
+               }
            }
          else
            operand = error_mark_node;
--- gcc/testsuite/c-c++-common/toplevel-asm-4.c.jj      2024-11-05 
18:13:20.062136936 +0100
+++ gcc/testsuite/c-c++-common/toplevel-asm-4.c 2024-11-05 18:36:26.800476151 
+0100
@@ -0,0 +1,9 @@
+/* PR c/41045 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-fno-pie" { target pie } } */
+
+int v[42], w;
+void foo (void);
+
+asm ("# %c0: %c1:" :: ":" (foo), ":" (v), ":" (&w));
--- gcc/testsuite/c-c++-common/toplevel-asm-5.c.jj      2024-11-05 
18:14:44.449941185 +0100
+++ gcc/testsuite/c-c++-common/toplevel-asm-5.c 2024-11-05 18:36:57.873035404 
+0100
@@ -0,0 +1,16 @@
+/* PR c/41045 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-fno-pie" { target pie } } */
+
+extern int v[42];
+
+asm ("# %0" : "=:" (32));              /* { dg-error "lvalue required in 'asm' 
statement" } */
+                                       /* { dg-error "':' constraint used for 
output operand" "" { target *-*-* } .-1 } */
+asm ("# %0" : "=:" (v));               /* { dg-error "':' constraint used for 
output operand" } */
+asm ("# %0" : : "i:" (v));             /* { dg-error "':' constraint mixed 
with other constraints" } */
+asm ("# %0" : : ":i" (v));             /* { dg-error "':' constraint mixed 
with other constraints" } */
+asm ("# %0" : : ",:" (v));             /* { dg-error "':' constraint mixed 
with other constraints" } */
+asm ("# %0" : : ":,:" (v));
+asm ("# %0" : : ":," (v));             /* { dg-error "':' constraint mixed 
with other constraints" } */
+asm ("# %0" : : ":,,:" (v));           /* { dg-error "':' constraint mixed 
with other constraints" } */

        Jakub

Reply via email to