https://gcc.gnu.org/g:35c4a383d6d8f7a9a094d364201daf0d098e4f42

commit r15-6327-g35c4a383d6d8f7a9a094d364201daf0d098e4f42
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Wed Dec 18 11:50:26 2024 +0100

    inline-asm: Add - constraint modifier support for toplevel extended asm 
[PR41045]
    
    The following patch adds - constraint modifier support (only in toplevel 
asms),
    which one can use to allow i, s and n constraint to accept SYMBOL_REFs
    even with -fpic.
    So, the recommended way mark toplevel asm as defining some symbol
    would be ":" constraint (usually with cc modifier in the pattern), while
    to mark toplevel asm as using some symbol (again, either function or
    variable), one would use "-s" constraint again with address of that function
    or variable.
    
    2024-12-18  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.

Diff:
---
 gcc/c/c-typeck.cc                           | 10 ++++++++++
 gcc/common.md                               |  6 +++---
 gcc/cp/semantics.cc                         | 10 ++++++++++
 gcc/doc/md.texi                             | 22 ++++++++++++++++++++++
 gcc/recog.cc                                | 19 ++++++++++++++++++-
 gcc/recog.h                                 |  3 +++
 gcc/stmt.cc                                 |  4 ++--
 gcc/testsuite/c-c++-common/toplevel-asm-4.c |  4 +++-
 gcc/testsuite/c-c++-common/toplevel-asm-7.c | 16 ++++++++++++++++
 gcc/testsuite/c-c++-common/toplevel-asm-8.c | 13 +++++++++++++
 10 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 7be645fdf198..9756edaae084 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -12332,6 +12332,11 @@ build_asm_expr (location_t loc, tree string, tree 
outputs, tree inputs,
                }
            }
        }
+      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;
     }
@@ -12417,6 +12422,11 @@ build_asm_expr (location_t loc, tree string, tree 
outputs, tree inputs,
                }
            }
        }
+      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;
     }
diff --git a/gcc/common.md b/gcc/common.md
index 6a2d453eeb1d..3cefa93cb813 100644
--- a/gcc/common.md
+++ b/gcc/common.md
@@ -92,13 +92,13 @@
 (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 "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."
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 948eb8996786..9912c5e50c49 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2255,6 +2255,11 @@ finish_asm_stmt (location_t loc, int volatile_p, tree 
string,
                    }
                }
            }
+         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;
        }
@@ -2383,6 +2388,11 @@ finish_asm_stmt (location_t loc, int volatile_p, tree 
string,
                    }
                }
            }
+         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;
        }
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 0ed1bc121438..0457bb56dcd0 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1889,6 +1889,28 @@ register preferences.
   @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
diff --git a/gcc/recog.cc b/gcc/recog.cc
index d1811f3618d2..f4f1a6b6a90a 100644
--- a/gcc/recog.cc
+++ b/gcc/recog.cc
@@ -86,6 +86,9 @@ static operand_alternative asm_op_alt[MAX_RECOG_OPERANDS
 
 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)).  */
@@ -2287,6 +2290,7 @@ asm_operand_ok (rtx op, const char *constraint, const 
char **constraints)
       switch (c)
        {
        case ',':
+         raw_constraint_p = false;
          constraint++;
          continue;
 
@@ -2337,6 +2341,11 @@ asm_operand_ok (rtx op, const char *constraint, const 
char **constraints)
            result = 1;
          break;
 
+       case '-':
+         raw_constraint_p = true;
+         constraint++;
+         continue;
+
        case '<':
        case '>':
          /* ??? Before auto-inc-dec, auto inc/dec insns are not supposed
@@ -2394,8 +2403,12 @@ asm_operand_ok (rtx op, const char *constraint, const 
char **constraints)
        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))
@@ -3189,6 +3202,9 @@ constrain_operands (int strict, alternative_mask 
alternatives)
              case ',':
                c = '\0';
                break;
+             case '-':
+               raw_constraint_p = true;
+               break;
 
              case '#':
                /* Ignore rest of this alternative as far as
@@ -3344,6 +3360,7 @@ constrain_operands (int strict, alternative_mask 
alternatives)
              }
          while (p += len, c);
 
+         raw_constraint_p = false;
          constraints[opno] = p;
          /* If this operand did not win somehow,
             this alternative loses.  */
diff --git a/gcc/recog.h b/gcc/recog.h
index 17ccdb6296be..b37af086570d 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -362,6 +362,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
diff --git a/gcc/stmt.cc b/gcc/stmt.cc
index 6789eeeea2dc..8ee4333a50b1 100644
--- a/gcc/stmt.cc
+++ b/gcc/stmt.cc
@@ -268,7 +268,7 @@ parse_output_constraint (const char **constraint_p, int 
operand_num,
        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':
@@ -363,7 +363,7 @@ parse_input_constraint (const char **constraint_p, int 
input_num,
       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 ':':
diff --git a/gcc/testsuite/c-c++-common/toplevel-asm-4.c 
b/gcc/testsuite/c-c++-common/toplevel-asm-4.c
index 2f100a65f426..392eef5e4788 100644
--- a/gcc/testsuite/c-c++-common/toplevel-asm-4.c
+++ b/gcc/testsuite/c-c++-common/toplevel-asm-4.c
@@ -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));
diff --git a/gcc/testsuite/c-c++-common/toplevel-asm-7.c 
b/gcc/testsuite/c-c++-common/toplevel-asm-7.c
new file mode 100644
index 000000000000..ed2603ffef0f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/toplevel-asm-7.c
@@ -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));
diff --git a/gcc/testsuite/c-c++-common/toplevel-asm-8.c 
b/gcc/testsuite/c-c++-common/toplevel-asm-8.c
new file mode 100644
index 000000000000..3b8f471fc2cd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/toplevel-asm-8.c
@@ -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" } */
+}

Reply via email to