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