Hi,

This patch adds a constraint "Ws" to allow absolute symbolic address for either
function or variable. This also works under -mcmodel=large.

Bootstrapped/regtested on x86_64-pc-linux-gnu{-m32,}

Ok for master?

gcc/ChangeLog:

        PR target/105576
        * config/i386/constraints.md (Ws): New constraint.
        * config/i386/i386-protos.h (ix86_symbolic_address_p):
        New proto type.
        * config/i386/i386.cc (ix86_symbolic_address_p):
        New function to ensure a rtx is a symbolic address.

gcc/testsuite/ChangeLog:

        PR target/105576
        * gcc.target/i386/pr105576.c: New test.
---
 gcc/config/i386/constraints.md           |  4 ++++
 gcc/config/i386/i386-protos.h            |  1 +
 gcc/config/i386/i386.cc                  |  7 +++++++
 gcc/testsuite/gcc.target/i386/pr105576.c | 11 +++++++++++
 4 files changed, 23 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/i386/pr105576.c

diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 7361687632f..ec0702be368 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -348,6 +348,10 @@ (define_constraint "Z"
    instructions)."
   (match_operand 0 "x86_64_zext_immediate_operand"))
 
+(define_constraint "Ws"
+ "A constraint that matches an absolute symbolic address."
+ (match_test "ix86_symbolic_address_p (op)"))
+
 ;; T prefix is used for different address constraints
 ;;   v - VSIB address
 ;;   s - address with no segment register
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 3596ce81ecf..2b8d063850f 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -337,6 +337,7 @@ extern void x86_output_aligned_bss (FILE *, tree, const 
char *,
                                    unsigned HOST_WIDE_INT, unsigned);
 extern void x86_elf_aligned_decl_common (FILE *, tree, const char *,
                                         unsigned HOST_WIDE_INT, unsigned);
+extern bool ix86_symbolic_address_p (rtx x);
 
 #ifdef RTX_CODE
 extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 86752a6516a..76728d10c8d 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -23956,6 +23956,13 @@ ix86_push_rounding (poly_int64 bytes)
   return ROUND_UP (bytes, UNITS_PER_WORD);
 }
 
+bool ix86_symbolic_address_p (rtx x)
+{
+  poly_int64 offset;
+  x = strip_offset (x, &offset);
+  return SYMBOL_REF_P (x) || LABEL_REF_P (x);
+}
+
 /* Target-specific selftests.  */
 
 #if CHECKING_P
diff --git a/gcc/testsuite/gcc.target/i386/pr105576.c 
b/gcc/testsuite/gcc.target/i386/pr105576.c
new file mode 100644
index 00000000000..06dd860d3f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr105576.c
@@ -0,0 +1,11 @@
+/* PR target/105576 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=large" } */
+
+extern int var;
+void *addr(void) { return &var; }
+void addr_via_asm(void)
+{
+  asm (".pushsection .xxx,\"aw\"\n\t .dc.a %0\n\t .popsection" :: "Ws"(addr));
+  asm (".pushsection .xxx,\"aw\"\n\t .dc.a %0\n\t .popsection" :: "Ws"(&var));
+}
-- 
2.18.1

Reply via email to