The constraint "S" can only be used with a symbol that binds locally, so
the following does not work for -fpie/-fpic (GOT access is used).
```
namespace ns { extern int var, a[4]; }
void foo() {
  asm(".pushsection .xxx,\"aw\"; .dc.a %0; .popsection" :: "S"(&ns::var));
  asm(".reloc ., BFD_RELOC_NONE, %0" :: "S"(&ns::a[3]));
}
```

This is overly restrictive, as many references like an absolute
relocation in a writable section or a non-SHF_ALLOC section should be
totally fine.  Allow symbols that do not bind locally, similar to
aarch64 "S" and x86-64 "Ws" (commit d7250100381b817114447d91fff4748526d4fb21).

gcc/ChangeLog:

        * config/riscv/constraints.md: Relax the condition for "S".
        * doc/md.texi: Update.

gcc/testsuite/ChangeLog:

        * gcc.target/riscv/asm-raw-symbol.c: New test.
---
 gcc/config/riscv/constraints.md                 |  4 ++--
 gcc/doc/md.texi                                 |  2 +-
 gcc/testsuite/gcc.target/riscv/asm-raw-symbol.c | 17 +++++++++++++++++
 3 files changed, 20 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/asm-raw-symbol.c

diff --git a/gcc/config/riscv/constraints.md b/gcc/config/riscv/constraints.md
index 41acaea04eb..bb012668fcb 100644
--- a/gcc/config/riscv/constraints.md
+++ b/gcc/config/riscv/constraints.md
@@ -121,8 +121,8 @@ (define_memory_constraint "A"
        (match_test "GET_CODE(XEXP(op,0)) == REG")))
 
 (define_constraint "S"
-  "A constraint that matches an absolute symbolic address."
-  (match_operand 0 "absolute_symbolic_operand"))
+  "A symbolic reference or label reference."
+  (match_code "const,symbol_ref,label_ref"))
 
 (define_constraint "U"
   "@internal
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index b0c61925120..c75e5bf259d 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -1947,7 +1947,7 @@ Integer constant that is valid as an immediate operand in 
a 64-bit @code{MOV}
 pseudo instruction
 
 @item S
-An absolute symbolic address or a label reference
+A symbolic reference or label reference.
 
 @item Y
 Floating point constant zero
diff --git a/gcc/testsuite/gcc.target/riscv/asm-raw-symbol.c 
b/gcc/testsuite/gcc.target/riscv/asm-raw-symbol.c
new file mode 100644
index 00000000000..eadf6d23fe1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/asm-raw-symbol.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fpic" } */
+
+extern int var;
+
+void
+func (void)
+{
+label:
+  __asm__ ("@ %0" : : "S" (func));
+  __asm__ ("@ %0" : : "S" (&var + 1));
+  __asm__ ("@ %0" : : "S" (&&label));
+}
+
+/* { dg-final { scan-assembler "@ func" } } */
+/* { dg-final { scan-assembler "@ var\\+4" } } */
+/* { dg-final { scan-assembler "@ .L" } } */
-- 
2.43.0.429.g432eaa2c6b-goog

Reply via email to