Wow, I think I wrote the v850 port back in circa 1997 and this bug has been
latent all this time.  Vlad's IRA changes twiddled register allocation in just
the right way to expose this bug.

I'm not sure what I was thinking, but apparently I made a spectacularly bad
choice for the STATIC_CHAIN_REGNUM in choosing a call-saved register (r20).

It's simply wrong to use a call-saved register for the static chain.  Think
about what the case if we take the address of a nested function.  We actually
get the address of the trampoline.  Then assume we call through that function
pointer at some point deeper in the call stack.  At the call site we have to
express that the static chain register was changed, but there's no way to know
at the call site -- that's the whole point of using the trampoline, it looks
just like a normal indirect call.

The only was I can see to fix this is to fix the static chain register to be a
call clobbered register which is an ABI change.  Thankfully the combination of
v850 and nested functions probably isn't used terribly much.

I've verified this fixed the recent v850 regressions.  Committing to the trunk.

Jeff
commit c7dbc54958321d296ca4e283f26f279f6a5342a7
Author: Jeff Law <l...@redhat.com>
Date:   Sat Feb 29 13:45:37 2020 -0700

    Make STATIC_CHAIN_REGNUM a call used register.
    
            * config/v850/v850.h (STATIC_CHAIN_REGNUM): Change to r19.
            * config/v850/v850.c (v850_asm_trampoline_template): Update
            accordingly.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7d95db8623f..2a69c680a9b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-28  Jeff Law  <l...@redhat.com>
+
+       * config/v850/v850.h (STATIC_CHAIN_REGNUM): Change to r19.
+       * config/v850/v850.c (v850_asm_trampoline_template): Update
+       accordingly.
+
 2020-02-28  Michael Meissner  <meiss...@linux.ibm.com>
 
        PR target/93937
diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c
index 074adf87687..4b0e28c1786 100644
--- a/gcc/config/v850/v850.c
+++ b/gcc/config/v850/v850.c
@@ -2961,7 +2961,7 @@ static void
 v850_asm_trampoline_template (FILE *f)
 {
   fprintf (f, "\tjarl .+4,r12\n");
-  fprintf (f, "\tld.w 12[r12],r20\n");
+  fprintf (f, "\tld.w 12[r12],r19\n");
   fprintf (f, "\tld.w 16[r12],r12\n");
   fprintf (f, "\tjmp [r12]\n");
   fprintf (f, "\tnop\n");
diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h
index 823bc5e17e3..7ae583c7df2 100644
--- a/gcc/config/v850/v850.h
+++ b/gcc/config/v850/v850.h
@@ -438,8 +438,9 @@ enum reg_class
 /* Base register for access to arguments of the function.  */
 #define ARG_POINTER_REGNUM 35
 
-/* Register in which static-chain is passed to a function.  */
-#define STATIC_CHAIN_REGNUM 20
+/* Register in which static-chain is passed to a function.
+   This must be a call used register.  */
+#define STATIC_CHAIN_REGNUM 19
 
 /* If defined, this macro specifies a table of register pairs used to
    eliminate unneeded registers that point into the stack frame.  If

Reply via email to