From 505c91a68aaf5ab56325affd4d8581b32b649cf4 Mon Sep 17 00:00:00 2001
From: Robie Basak <robie.basak@canonical.com>
Date: Tue, 14 Oct 2014 13:16:22 +0100
Subject: [PATCH] arm32: force return value from asm

In my case, instead of a simple "mov r0, #0", the optimizer had done
this:

    Between calls to slp_save_state and slp_restore_state, it saved the
    value now guaranteed to be 0 using "str r0, [r7]".

    Now, at the end, it restores that value into r0 using "ldr r3, [r7]"
    and then "mov r0, r3".

It isn't clear to me that intermediate values managed by the compiler,
like this one at [r7], would be preserved in the stack this way,
especially as at this point we're in a "different" stack (unknown to the
optimizer).

Instead, prevent the optimizer from re-using a previous result like this
by forcing it to rely on the inline assembly to produce the result.

This fixes test failures on Ubuntu Utopic using gcc 4.9.1 (-5ubuntu1).

I think even this is still a hack though, and not guaranteed to work.
Ultimately, gcc can even re-order the "__asm__ volatile" functions at
will around the entire function, or just wrap each REGS_TO_SAVE
clobbering call with a simple push/pop, thus not preserving the
registers between stack switches.

The only way I can see of doing this without relying on undefined
compiler behaviour is to write the entire slp_switch function in
assembly for each architecture, instead of inlining it into a C function
for code reuse.

Bug: https://github.com/python-greenlet/greenlet/pull/65
Origin: upstream, https://github.com/python-greenlet/greenlet/commit/f90dbe4c24a9aed261a5fa9f66fb95ebdb8f21cc
Last-Update: 2014-10-15

---
 platform/switch_arm32_gcc.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/platform/switch_arm32_gcc.h b/platform/switch_arm32_gcc.h
index c6e160d..e1cd797 100644
--- a/platform/switch_arm32_gcc.h
+++ b/platform/switch_arm32_gcc.h
@@ -54,6 +54,7 @@ slp_switch(void)
 {
         void *fp;
         register int *stackref, stsizediff;
+        int result;
         __asm__ volatile ("" : : : REGS_TO_SAVE);
         __asm__ volatile ("mov r0," REG_FP "\n\tstr r0,%0" : "=m" (fp) : : "r0");
         __asm__ ("mov %0," REG_SP : "=r" (stackref));
@@ -67,9 +68,9 @@ slp_switch(void)
                     );
                 SLP_RESTORE_STATE();
         }
-        __asm__ volatile ("ldr r0,%0\n\tmov " REG_FP ",r0" : : "m" (fp) : "r0");
+        __asm__ volatile ("ldr r0,%1\n\tmov " REG_FP ",r0\n\tmov %0, #0" : "=r" (result) : "m" (fp) : "r0");
         __asm__ volatile ("" : : : REGS_TO_SAVE);
-        return 0;
+        return result;
 }
 
 #endif
\ No newline at end of file
