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