Hi,

(I’m not going to defend the status quo here, it seems a bit prone
 to confusing a user [different interposition behaviour between the
 inlined and non-inlined cases] however, this is what the platform
 compilers implement).

----

We allow public functions defined in a TU to bind locally for PIC
code (the default) on 64bit Mach-O.

If such functions are not inlined, we cannot tell at compile-time if
they might be called via the lazy symbol resolver (this can depend on
options given at link-time).  Therefore, we must assume that the lazy
resolver could be used which clobbers R11 and R10.

The solution here is similar in form to the one used for veneer regs
on Arm (but I’m open to alternate suggestions).

tested on X86_64-darwin, linux
OK for master?
Iain

Signed-off-by: Iain Sandoe <i...@sandoe.co.uk>

PR target/100152 - [10/11/12 Regression] used caller-saved register not 
preserved across a call.

        PR target/100152

gcc/ChangeLog:

        * config/i386/i386-expand.c (ix86_expand_call): If a call is
        to a non-local-binding, or local but to a public symbol, then
        assume that it might be indirected via the lazy symbol binder.
        Mark R10 and R10 as clobbered in that case.
---
 gcc/config/i386/i386-expand.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index b37642e35ee..1b860e027b0 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -8380,6 +8380,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
     pop = NULL;
   gcc_assert (!TARGET_64BIT || !pop);
 
+  rtx addr = XEXP (fnaddr, 0);
   if (TARGET_MACHO && !TARGET_64BIT)
     {
 #if TARGET_MACHO
@@ -8392,7 +8393,6 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
       /* Static functions and indirect calls don't need the pic register.  
Also,
         check if PLT was explicitly avoided via no-plt or "noplt" attribute, 
making
         it an indirect call.  */
-      rtx addr = XEXP (fnaddr, 0);
       if (flag_pic
          && GET_CODE (addr) == SYMBOL_REF
          && !SYMBOL_REF_LOCAL_P (addr))
@@ -8555,6 +8555,20 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
        }
     }
 
+  if (TARGET_MACHO && TARGET_64BIT && !sibcall
+      && ((GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (addr))
+         || !fndecl || TREE_PUBLIC (fndecl)))
+    {
+      /* We allow public functions defined in a TU to bind locally for PIC
+        code (the default) on 64bit Mach-O.
+        If such functions are not inlined, we cannot tell at compile-time if
+        they will be called via the lazy symbol resolver (this can depend on
+        options given at link-time).  Therefore, we must assume that the lazy
+        resolver could be used which clobbers R11 and R10.  */
+      clobber_reg (&use, gen_rtx_REG (DImode, R11_REG));
+      clobber_reg (&use, gen_rtx_REG (DImode, R10_REG));
+    }
+
   if (vec_len > 1)
     call = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (vec_len, vec));
   rtx_insn *call_insn = emit_call_insn (call);
-- 
2.24.1

Reply via email to