On Fri, 22 Nov 2024, Jakub Jelinek wrote:

> On Thu, Nov 21, 2024 at 11:57:13PM +0000, Joseph Myers wrote:
> > On Wed, 6 Nov 2024, Jakub Jelinek wrote:
> > 
> > > +           error_at (loc, "%<:%> constraint operand is not address "
> > > +                          "of a function or non-automatic variable");
> > 
> > I think a testcase for this error is needed.
> 
> Here is an updated patch with the additional test coverage.

The middle-end changes are OK.

Richard.

> 2024-11-21  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-22 
> 10:28:42.873355264 +0100
> @@ -0,0 +1,28 @@
> +/* 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" } */
> +asm ("" : : ":" (0));                        /* { dg-error "constraint 
> operand is not address of a function or non-automatic variable" } */
> +
> +void
> +foo (int x)
> +{
> +  int y;
> +  l:;
> +  asm ("" : : ":" (&x));             /* { dg-error "constraint operand is 
> not address of a function or non-automatic variable" } */
> +  asm ("" : : ":" (&&l));            /* { dg-error "constraint operand is 
> not address of a function or non-automatic variable" } */
> +  asm ("" : : ":" (&y));             /* { dg-error "constraint operand is 
> not address of a function or non-automatic variable" } */
> +  asm ("" : : ":" (0));                      /* { dg-error "constraint 
> operand is not address of a function or non-automatic variable" } */
> +}
> 
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to