On Fri, Nov 22, 2024 at 12:01:21AM +0000, Joseph Myers wrote:
> On Mon, 18 Nov 2024, Jakub Jelinek wrote:
> 
> > +@smallexample
> > +extern void foo (void), bar (void);
> > +int v;
> > +extern int w;
> > +asm (".globl %cc0, %cc2; .text; %cc0: call %cc1; ret; .data; %cc2: .word 
> > %cc3"
> > +     :: ":" (foo), "-s" (&bar), ":" (&w), "-i" (&v));
> > +@end smallexample
> > +
> > +This asm declaration tells the compiler it defines function foo and 
> > variable
> > +w and uses function bar and variable v.  This will compile even with PIC,
> > +but it is up to the user to ensure it will assemble correctly and have the
> > +expected behavior.
> 
> That should be @code{foo}, @code{w}, @code{bar}, @code{v}.
> 
> The C front-end changes in this patch are OK.

Thanks, here is the adjusted patch.

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

        PR c/41045
gcc/
        * stmt.cc (parse_output_constraint, parse_input_constraint): Handle
        - modifier.
        * recog.h (raw_constraint_p): Declare.
        * recog.cc (raw_constraint_p): New variable.
        (asm_operand_ok, constrain_operands): Handle - modifier.
        * common.md (i, s, n): For raw_constraint_p don't require
        LEGITIMATE_PIC_OPERAND_P.
        * doc/md.texi: Document - constraint modifier.
gcc/c/
        * c-typeck.cc (build_asm_expr): Reject - constraint modifier inside
        of a function.
gcc/cp/
        * semantics.cc (finish_asm_stmt): Reject - constraint modifier inside
        of a function.
gcc/testsuite/
        * c-c++-common/toplevel-asm-4.c: Add missing %cc2 use in template, add
        bar, x, &y operands with "-i" and "-s" constraints.
        (x, y): New variables.
        (bar): Declare.
        * c-c++-common/toplevel-asm-7.c: New test.
        * c-c++-common/toplevel-asm-8.c: New test.

--- gcc/stmt.cc.jj      2024-11-17 21:07:06.712510933 -1100
+++ gcc/stmt.cc 2024-11-17 21:45:30.201294501 -1100
@@ -269,7 +269,7 @@ parse_output_constraint (const char **co
        case 'E':  case 'F':  case 'G':  case 'H':
        case 's':  case 'i':  case 'n':
        case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
-       case 'N':  case 'O':  case 'P':  case ',':
+       case 'N':  case 'O':  case 'P':  case ',':  case '-':
          break;
 
        case '0':  case '1':  case '2':  case '3':  case '4':
@@ -364,7 +364,7 @@ parse_input_constraint (const char **con
       case 'E':  case 'F':  case 'G':  case 'H':
       case 's':  case 'i':  case 'n':
       case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
-      case 'N':  case 'O':  case 'P':  case ',':
+      case 'N':  case 'O':  case 'P':  case ',':  case '-':
        break;
 
       case ':':
--- gcc/recog.h.jj      2024-08-15 09:23:26.981012468 -1100
+++ gcc/recog.h 2024-11-17 22:26:47.190602347 -1100
@@ -335,6 +335,9 @@ private:
    matched.  */
 extern int which_alternative;
 
+/* True for inline asm operands with - constraint modifier.  */
+extern bool raw_constraint_p;
+
 /* The following vectors hold the results from insn_extract.  */
 
 struct recog_data_d
--- gcc/recog.cc.jj     2024-10-24 21:00:29.511767242 -1100
+++ gcc/recog.cc        2024-11-17 23:16:00.654874432 -1100
@@ -86,6 +86,9 @@ static operand_alternative asm_op_alt[MA
 
 int which_alternative;
 
+/* True for inline asm operands with - constraint modifier.  */
+bool raw_constraint_p;
+
 /* Nonzero after end of reload pass.
    Set to 1 or 0 by toplev.cc.
    Controls the significance of (SUBREG (MEM)).  */
@@ -2300,6 +2303,7 @@ asm_operand_ok (rtx op, const char *cons
       switch (c)
        {
        case ',':
+         raw_constraint_p = false;
          constraint++;
          continue;
 
@@ -2350,6 +2354,11 @@ asm_operand_ok (rtx op, const char *cons
            result = 1;
          break;
 
+       case '-':
+         raw_constraint_p = true;
+         constraint++;
+         continue;
+
        case '<':
        case '>':
          /* ??? Before auto-inc-dec, auto inc/dec insns are not supposed
@@ -2407,8 +2416,12 @@ asm_operand_ok (rtx op, const char *cons
        constraint++;
       while (--len && *constraint && *constraint != ',');
       if (len)
-       return 0;
+       {
+         raw_constraint_p = false;
+         return 0;
+       }
     }
+  raw_constraint_p = false;
 
   /* For operands without < or > constraints reject side-effects.  */
   if (AUTO_INC_DEC && !incdec_ok && result && MEM_P (op))
@@ -3202,6 +3215,9 @@ constrain_operands (int strict, alternat
              case ',':
                c = '\0';
                break;
+             case '-':
+               raw_constraint_p = true;
+               break;
 
              case '#':
                /* Ignore rest of this alternative as far as
@@ -3357,6 +3373,7 @@ constrain_operands (int strict, alternat
              }
          while (p += len, c);
 
+         raw_constraint_p = false;
          constraints[opno] = p;
          /* If this operand did not win somehow,
             this alternative loses.  */
--- gcc/common.md.jj    2024-11-17 21:07:06.712510933 -1100
+++ gcc/common.md       2024-11-17 22:33:23.805858947 -1100
@@ -92,13 +92,13 @@ (define_address_constraint "p"
 (define_constraint "i"
   "Matches a general integer constant."
   (and (match_test "CONSTANT_P (op)")
-       (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+       (match_test "!flag_pic || raw_constraint_p || LEGITIMATE_PIC_OPERAND_P 
(op)")))
 
 (define_constraint "s"
   "Matches a symbolic integer constant."
   (and (match_test "CONSTANT_P (op)")
        (match_test "!CONST_SCALAR_INT_P (op)")
-       (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+       (match_test "!flag_pic || raw_constraint_p || LEGITIMATE_PIC_OPERAND_P 
(op)")))
 
 (define_constraint ":"
   "Defines a symbol."
@@ -108,7 +108,7 @@ (define_constraint ":"
 (define_constraint "n"
   "Matches a non-symbolic integer constant."
   (and (match_test "CONST_SCALAR_INT_P (op)")
-       (match_test "!flag_pic || LEGITIMATE_PIC_OPERAND_P (op)")))
+       (match_test "!flag_pic || raw_constraint_p || LEGITIMATE_PIC_OPERAND_P 
(op)")))
 
 (define_constraint "E"
   "Matches a floating-point constant."
--- gcc/doc/md.texi.jj  2024-11-17 21:07:19.843326980 -1100
+++ gcc/doc/md.texi     2024-11-17 23:43:12.301073998 -1100
@@ -1889,6 +1889,28 @@ (define_insn "extendhisi2"
   @dots{})
 @end smallexample
 @end ifset
+
+@cindex @samp{-} in constraint
+@item -
+Says that the selected following constraints within the same alternative
+should be matched differently.  Normally in PIC code symbolic operands
+in constraints like @samp{i}, @samp{s} or @samp{n} are not allowed at all
+or severely restricted.  The @samp{-} modifier, which is only allowed
+outside of functions, allows symbolic operands even in PIC code.  This
+modifier is usually used together with the @code{cc} operand modifier.
+
+@smallexample
+extern void foo (void), bar (void);
+int v;
+extern int w;
+asm (".globl %cc0, %cc2; .text; %cc0: call %cc1; ret; .data; %cc2: .word %cc3"
+     :: ":" (foo), "-s" (&bar), ":" (&w), "-i" (&v));
+@end smallexample
+
+This asm declaration tells the compiler it defines function @code{foo} and
+variable @code{w} and uses function @code{bar} and variable @code{v}.  This
+will compile even with PIC, but it is up to the user to ensure it will
+assemble correctly and have the expected behavior.
 @end table
 
 @node Machine Constraints
--- gcc/c/c-typeck.cc.jj        2024-11-17 21:07:06.000000000 -1100
+++ gcc/c/c-typeck.cc   2024-11-17 22:17:13.935708652 -1100
@@ -12281,6 +12281,11 @@ build_asm_expr (location_t loc, tree str
                }
            }
        }
+      else if (output != error_mark_node && strstr (constraint, "-"))
+       {
+         error_at (loc, "%<-%> modifier used inside of a function");
+         output = error_mark_node;
+       }
 
       TREE_VALUE (tail) = output;
     }
@@ -12365,6 +12370,11 @@ build_asm_expr (location_t loc, tree str
                }
            }
        }
+      else if (input != error_mark_node && strstr (constraint, "-"))
+       {
+         error_at (loc, "%<-%> modifier used inside of a function");
+         input = error_mark_node;
+       }
 
       TREE_VALUE (tail) = input;
     }
--- gcc/cp/semantics.cc.jj      2024-11-17 21:07:06.718510849 -1100
+++ gcc/cp/semantics.cc 2024-11-17 22:24:24.469669093 -1100
@@ -2255,6 +2255,11 @@ finish_asm_stmt (location_t loc, int vol
                    }
                }
            }
+         else if (operand != error_mark_node && strstr (constraint, "-"))
+           {
+             error_at (loc, "%<-%> modifier used inside of a function");
+             operand = error_mark_node;
+           }
 
          TREE_VALUE (t) = operand;
        }
@@ -2382,6 +2387,11 @@ finish_asm_stmt (location_t loc, int vol
                    }
                }
            }
+         else if (operand != error_mark_node && strstr (constraint, "-"))
+           {
+             error_at (loc, "%<-%> modifier used inside of a function");
+             operand = error_mark_node;
+           }
 
          TREE_VALUE (t) = operand;
        }
--- gcc/testsuite/c-c++-common/toplevel-asm-4.c.jj      2024-11-17 
21:07:19.844326965 -1100
+++ gcc/testsuite/c-c++-common/toplevel-asm-4.c 2024-11-17 23:41:10.340778042 
-1100
@@ -3,6 +3,8 @@
 /* { dg-options "-O0" } */
 
 extern int v[42], w;
+int x[42], y;
 void foo (void);
+void bar (void) {}
 
-asm ("# %cc0: %cc1:" :: ":" (foo), ":" (v), ":" (&w));
+asm ("# %cc0: %cc1: %cc2: %cc3 %cc4 %cc5" :: ":" (foo), ":" (v), ":" (&w), 
"-i" (bar), "-s" (x), "-s" (&y));
--- gcc/testsuite/c-c++-common/toplevel-asm-7.c.jj      2024-11-17 
23:37:58.518458202 -1100
+++ gcc/testsuite/c-c++-common/toplevel-asm-7.c 2024-11-17 23:39:01.531577774 
-1100
@@ -0,0 +1,16 @@
+/* PR c/41045 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+/* { dg-additional-options "-fpic" { target fpic } } */
+
+struct S { char a; long long b; int c; };
+enum E { E0, E1 = sizeof (struct S) + 15 };
+int v[42];
+void foo (void) {}
+
+asm ("# %0 %1 %2 %cc3 %cc4 %% %="
+     :: "i" (sizeof (struct S)),
+       "i" (__builtin_offsetof (struct S, c)),
+       "i" (E1),
+       "-s" (foo),
+       "-i" (v));
--- gcc/testsuite/c-c++-common/toplevel-asm-8.c.jj      2024-11-17 
23:39:39.794043169 -1100
+++ gcc/testsuite/c-c++-common/toplevel-asm-8.c 2024-11-17 23:51:53.656789127 
-1100
@@ -0,0 +1,13 @@
+/* PR c/41045 */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+
+void
+foo (void)
+{
+  int m;
+  asm ("" : "=-m" (m));                /* { dg-error "'-' modifier used inside 
of a function" } */
+  asm ("" : : "-m" (m));       /* { dg-error "'-' modifier used inside of a 
function" } */
+  asm ("" : : "-i" (32));      /* { dg-error "'-' modifier used inside of a 
function" } */
+  asm ("" : : "-s" (foo));     /* { dg-error "'-' modifier used inside of a 
function" } */
+}


        Jakub

Reply via email to