aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-12-18 11:50:26 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2024-12-18 11:50:26 +0100
commit35c4a383d6d8f7a9a094d364201daf0d098e4f42 (patch)
tree3effd0285aae9c24528c30ce4712c70536220968 /gcc
parent74d6a676034b3ab20c387f12f19f5597e4f1c9fa (diff)
downloadgcc-35c4a383d6d8f7a9a094d364201daf0d098e4f42.zip
gcc-35c4a383d6d8f7a9a094d364201daf0d098e4f42.tar.gz
gcc-35c4a383d6d8f7a9a094d364201daf0d098e4f42.tar.bz2
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 <jakub@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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c/c-typeck.cc10
-rw-r--r--gcc/common.md6
-rw-r--r--gcc/cp/semantics.cc10
-rw-r--r--gcc/doc/md.texi22
-rw-r--r--gcc/recog.cc19
-rw-r--r--gcc/recog.h3
-rw-r--r--gcc/stmt.cc4
-rw-r--r--gcc/testsuite/c-c++-common/toplevel-asm-4.c4
-rw-r--r--gcc/testsuite/c-c++-common/toplevel-asm-7.c16
-rw-r--r--gcc/testsuite/c-c++-common/toplevel-asm-8.c13
10 files changed, 100 insertions, 7 deletions
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 7be645f..9756eda 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 6a2d453..3cefa93 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 948eb89..9912c5e 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 0ed1bc1..0457bb5 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 d1811f3..f4f1a6b 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 17ccdb6..b37af08 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 6789eee..8ee4333 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 2f100a6..392eef5 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 0000000..ed2603f
--- /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 0000000..3b8f471
--- /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" } */
+}