On Fri, 22 Nov 2024, Jakub Jelinek wrote:
> 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.
The middle-end changes are OK.
Richard.
> 2024-11-21 Jakub Jelinek <[email protected]>
>
> 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
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)