For hotpatching it might be required to introduce new .text parts
while keep using the existing .data/.bss sections.  To make this work
the backend needs to be prevented from using relative addressing
between code and data.
This only works when already building PIC
since the addressing will then be handling via GOT.

Bootstrapped and regression tested on s390x.

Committed to mainline.

Bye,

-Andreas-

gcc/testsuite/ChangeLog:

2017-06-28  Andreas Krebbel  <kreb...@linux.vnet.ibm.com>

        * gcc.target/s390/nodatarel-1.c: New test.

gcc/ChangeLog:

2017-06-28  Andreas Krebbel  <kreb...@linux.vnet.ibm.com>

        * config/s390/predicates.md: Use s390_rel_address_ok_p.
        * config/s390/s390-protos.h: Add prototype of
        s390_rel_address_ok_p.
        * config/s390/s390.c (s390_got_symbol): New function.
        (s390_rel_address_ok_p): New function.
        (legitimize_pic_address): Use s390_rel_address_ok_p.
        (s390_load_got): Use s390_got_symbol.
        (s390_option_override): Issue error if
        -mno-pic-data-is-text-relative is used without -fpic/-fPIC.
        * config/s390/s390.h (TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE):
        New macro.
        * config/s390/s390.opt: New option mpic-data-is-text-relative.
---
 gcc/config/s390/predicates.md               |  9 ++--
 gcc/config/s390/s390-protos.h               |  1 +
 gcc/config/s390/s390.c                      | 53 ++++++++++++++----
 gcc/config/s390/s390.h                      |  4 ++
 gcc/config/s390/s390.opt                    |  4 ++
 gcc/testsuite/gcc.target/s390/nodatarel-1.c | 83 +++++++++++++++++++++++++++++
 6 files changed, 140 insertions(+), 14 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/nodatarel-1.c

diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 34a7ea2..fc151ac 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -131,10 +131,10 @@
   /* Allow labels and local symbols.  */
   if (GET_CODE (op) == LABEL_REF)
     return true;
-  if (GET_CODE (op) == SYMBOL_REF)
+  if (SYMBOL_REF_P (op))
     return (!SYMBOL_FLAG_NOTALIGN2_P (op)
            && SYMBOL_REF_TLS_MODEL (op) == 0
-           && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+           && s390_rel_address_ok_p (op));
 
   /* Everything else must have a CONST, so strip it.  */
   if (GET_CODE (op) != CONST)
@@ -156,10 +156,11 @@
   /* Labels and local symbols allowed here as well.  */
   if (GET_CODE (op) == LABEL_REF)
     return true;
-  if (GET_CODE (op) == SYMBOL_REF)
+  if (SYMBOL_REF_P (op))
     return (!SYMBOL_FLAG_NOTALIGN2_P (op)
            && SYMBOL_REF_TLS_MODEL (op) == 0
-           && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+           && s390_rel_address_ok_p (op));
+
 
   /* Now we must have a @GOTENT offset or @PLT stub
      or an @INDNTPOFF TLS offset.  */
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index 3fdb320..6df37ef 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -79,6 +79,7 @@ extern bool s390_bytemask_vector_p (rtx, unsigned *);
 extern bool s390_split_ok_p (rtx, rtx, machine_mode, int);
 extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT);
 extern bool s390_offset_p (rtx, rtx, rtx);
+extern bool s390_rel_address_ok_p (rtx);
 extern int tls_symbolic_operand (rtx);
 
 extern bool s390_match_ccmode (rtx_insn *, machine_mode);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index eb94237..bfc38db 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -1179,6 +1179,23 @@ s390_label_align (rtx_insn *label)
   return align_labels_log;
 }
 
+static GTY(()) rtx got_symbol;
+
+/* Return the GOT table symbol.  The symbol will be created when the
+   function is invoked for the first time.  */
+
+static rtx
+s390_got_symbol (void)
+{
+  if (!got_symbol)
+    {
+      got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+      SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
+    }
+
+  return got_symbol;
+}
+
 static machine_mode
 s390_libgcc_cmp_return_mode (void)
 {
@@ -4496,6 +4513,26 @@ s390_load_address (rtx dst, rtx src)
     emit_insn (gen_force_la_31 (dst, src));
 }
 
+/* Return true if it ok to use SYMBOL_REF in a relative address.  */
+
+bool
+s390_rel_address_ok_p (rtx symbol_ref)
+{
+  tree decl;
+
+  if (symbol_ref == s390_got_symbol () || CONSTANT_POOL_ADDRESS_P (symbol_ref))
+    return true;
+
+  decl = SYMBOL_REF_DECL (symbol_ref);
+
+  if (!flag_pic || SYMBOL_REF_LOCAL_P (symbol_ref))
+    return (s390_pic_data_is_text_relative
+           || (decl
+               && TREE_CODE (decl) == FUNCTION_DECL));
+
+  return false;
+}
+
 /* Return a legitimate reference for ORIG (an address) using the
    register REG.  If REG is 0, a new pseudo is generated.
 
@@ -4533,7 +4570,7 @@ legitimize_pic_address (rtx orig, rtx reg)
     }
 
   if ((GET_CODE (addr) == LABEL_REF
-       || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr))
+       || (SYMBOL_REF_P (addr) && s390_rel_address_ok_p (addr))
        || (GET_CODE (addr) == UNSPEC &&
           (XINT (addr, 1) == UNSPEC_GOTENT
            || (TARGET_CPU_ZARCH && XINT (addr, 1) == UNSPEC_PLT))))
@@ -10791,7 +10828,6 @@ restore_gprs (rtx base, int offset, int first, int last)
 
 /* Return insn sequence to load the GOT register.  */
 
-static GTY(()) rtx got_symbol;
 rtx_insn *
 s390_load_got (void)
 {
@@ -10803,23 +10839,17 @@ s390_load_got (void)
      aren't usable.  */
   rtx got_rtx = gen_rtx_REG (Pmode, 12);
 
-  if (!got_symbol)
-    {
-      got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
-      SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
-    }
-
   start_sequence ();
 
   if (TARGET_CPU_ZARCH)
     {
-      emit_move_insn (got_rtx, got_symbol);
+      emit_move_insn (got_rtx, s390_got_symbol ());
     }
   else
     {
       rtx offset;
 
-      offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
+      offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, s390_got_symbol ()),
                               UNSPEC_LTREL_OFFSET);
       offset = gen_rtx_CONST (Pmode, offset);
       offset = force_const_mem (Pmode, offset);
@@ -14911,6 +14941,9 @@ s390_option_override (void)
   if (flag_prefetch_loop_arrays < 0 && HAVE_prefetch && optimize >= 3)
     flag_prefetch_loop_arrays = 1;
 
+  if (!s390_pic_data_is_text_relative && !flag_pic)
+    error ("-mno-pic-data-is-text-relative cannot be used without 
-fpic/-fPIC");
+
   if (TARGET_TPF)
     {
       /* Don't emit DWARF3/4 unless specifically selected.  The TPF
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index a372981..7847047 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -946,6 +946,10 @@ CUMULATIVE_ARGS;
 
 #define LEGITIMATE_PIC_OPERAND_P(X)  legitimate_pic_operand_p (X)
 
+#ifndef TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE
+#define TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE 1
+#endif
+
 
 /* Assembler file format.  */
 
diff --git a/gcc/config/s390/s390.opt b/gcc/config/s390/s390.opt
index d0a0d46..f277ac5 100644
--- a/gcc/config/s390/s390.opt
+++ b/gcc/config/s390/s390.opt
@@ -226,3 +226,7 @@ values are small, non-negative integers.  The default 
branch cost is
 mlra
 Target Report Var(s390_lra_flag) Init(1) Save
 Use LRA instead of reload.
+
+mpic-data-is-text-relative
+Target Report Var(s390_pic_data_is_text_relative) 
Init(TARGET_DEFAULT_PIC_DATA_IS_TEXT_RELATIVE)
+Assume data segments are relative to text segment.
diff --git a/gcc/testsuite/gcc.target/s390/nodatarel-1.c 
b/gcc/testsuite/gcc.target/s390/nodatarel-1.c
new file mode 100644
index 0000000..1d589a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/nodatarel-1.c
@@ -0,0 +1,83 @@
+/* Test -mno-pic-data-is-text-relative option.  No relative addressing
+   of elements in .data and .bss are allowed with that option.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-optimize-sibling-calls -fpic 
-mno-pic-data-is-text-relative -march=z10 -mtune=z9-109 -mzarch" } */
+
+static int a = 3;
+
+/* With -mno-pic-data-is-text-relative these must be addressed via
+   GOT.  */
+
+int __attribute__((noinline,noclone))
+foo ()
+{
+  return a;
+}
+
+static int __attribute__((noinline,noclone))
+foostatic (void)
+{
+  return a;
+}
+
+/* Just to make a potentially modified.  */
+
+void
+bar (int b)
+{
+  a = b;
+}
+
+/* { dg-final { scan-assembler-times "a@GOTENT" 3 } } */
+
+/* The exrl target is a label_ref which should not be affected at
+   all.  */
+
+void
+mymemcpy (char *dst, char *src, long size)
+{
+  __builtin_memcpy (dst, src, size);
+}
+
+/* { dg-final { scan-assembler "exrl" } } */
+
+
+/* PLT slots can still be addressed relatively.  */
+
+int
+callfoo ()
+{
+  return foo ();
+}
+
+/* { dg-final { scan-assembler-times "foo@PLT" 1 } } */
+
+
+/* GOT entries can still be addressed relatively.  */
+
+void *
+fooptr ()
+{
+  return &foo;
+}
+
+/* { dg-final { scan-assembler-times "foo@GOTENT" 1 } } */
+
+
+/* A static function can be addressed relatively.  */
+
+int
+callfoostatic ()
+{
+  return foostatic ();
+}
+
+void *
+foostaticptr ()
+{
+  return &foostatic;
+}
+
+
+/* { dg-final { scan-assembler-not "foostatic@" } } */
-- 
2.9.1

Reply via email to