]> git.lizzy.rs Git - rust.git/commitdiff
Runtime support for arm on iOS
authorValerii Hiora <valerii.hiora@gmail.com>
Mon, 5 May 2014 07:08:34 +0000 (10:08 +0300)
committerValerii Hiora <valerii.hiora@gmail.com>
Thu, 12 Jun 2014 17:24:08 +0000 (20:24 +0300)
src/librustrt/stack.rs
src/rt/arch/arm/_context.S
src/rt/arch/arm/morestack.S
src/rt/arch/arm/record_sp.S

index 148d93adc8485583c3a58f53bf7a4a87357e549a..aac773f6f859e685763b24b1ce63d1bb07142d83 100644 (file)
 //! detection is not guaranteed to continue in the future. Usage of this module
 //! is discouraged unless absolutely necessary.
 
+// iOS related notes
+//
+// It is possible to implement it using idea from
+// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
+//
+// In short: _pthread_{get,set}_specific_direct allows extremely fast
+// access, exactly what is required for segmented stack
+// There is a pool of reserved slots for Apple internal use (0..119)
+// First dynamic allocated pthread key starts with 257 (on iOS7)
+// So using slot 149 should be pretty safe ASSUMING space is reserved
+// for every key < first dynamic key
+//
+// There is also an opportunity to steal keys reserved for Garbage Collection
+// ranges 80..89 and 110..119, especially considering the fact Garbage Collection
+// never supposed to work on iOS. But as everybody knows it - there is a chance
+// that those slots will be re-used, like it happened with key 95 (moved from
+// JavaScriptCore to CoreText)
+//
+// Unfortunately Apple rejected patch to LLVM which generated
+// corresponding prolog, decision was taken to disable segmented
+// stack support on iOS.
+
 pub static RED_ZONE: uint = 20 * 1024;
 
 /// This function is invoked from rust's current __morestack function. Segmented
@@ -193,7 +215,7 @@ unsafe fn target_record_sp_limit(limit: uint) {
     // mips, arm - Some brave soul can port these to inline asm, but it's over
     //             my head personally
     #[cfg(target_arch = "mips")]
-    #[cfg(target_arch = "arm")] #[inline(always)]
+    #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
     unsafe fn target_record_sp_limit(limit: uint) {
         use libc::c_void;
         return record_sp_limit(limit as *c_void);
@@ -201,6 +223,11 @@ unsafe fn target_record_sp_limit(limit: uint) {
             fn record_sp_limit(limit: *c_void);
         }
     }
+
+    // iOS segmented stack is disabled for now, see related notes
+    #[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
 }
 
 /// The counterpart of the function above, this function will fetch the current
@@ -267,7 +294,7 @@ unsafe fn target_get_sp_limit() -> uint {
     // mips, arm - Some brave soul can port these to inline asm, but it's over
     //             my head personally
     #[cfg(target_arch = "mips")]
-    #[cfg(target_arch = "arm")] #[inline(always)]
+    #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
     unsafe fn target_get_sp_limit() -> uint {
         use libc::c_void;
         return get_sp_limit() as uint;
@@ -275,4 +302,12 @@ unsafe fn target_get_sp_limit() -> uint {
             fn get_sp_limit() -> *c_void;
         }
     }
+
+    // iOS doesn't support segmented stacks yet. This function might
+    // be called by runtime though so it is unsafe to mark it as
+    // unreachable, let's return a fixed constant.
+    #[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
 }
index fb6db57414a564ac7894835a6100674dd7617e78..38fc4827f5861e811ded6db100301a08f6af6b09 100644 (file)
 .align
 #endif
 
-.globl rust_swap_registers
-rust_swap_registers:
+#if defined(__APPLE__)
+  #define SWAP_REGISTERS  _rust_swap_registers
+  #define BOOTSTRAP_TASK  _rust_bootstrap_green_task
+#else
+  #define SWAP_REGISTERS  rust_swap_registers
+  #define BOOTSTRAP_TASK  rust_bootstrap_green_task
+#endif
+        
+.globl SWAP_REGISTERS
+SWAP_REGISTERS:
        str r0, [r0, #0]
        str r3, [r0, #12]
        str r4, [r0, #16]
@@ -53,9 +61,9 @@ rust_swap_registers:
        mov pc, lr
 
 // For reasons of this existence, see the comments in x86_64/_context.S
-.globl rust_bootstrap_green_task
-rust_bootstrap_green_task:
-        mov r0, r0
-        mov r1, r3
-        mov r2, r4
-        mov pc, r5
+.globl BOOTSTRAP_TASK
+BOOTSTRAP_TASK:
+    mov r0, r0
+    mov r1, r3
+    mov r2, r4
+    mov pc, r5
index 219f0962d771c000edd75e7f90604b171b55af39..0b9012cc2a80a27a48cc7fd4b6d0531aae349196 100644 (file)
@@ -8,33 +8,63 @@
 .text
 .code 32
 .arm
+#if defined(__APPLE__)
+.align 2
+#else
 .align
+#endif
+
+#if defined(__APPLE__)
+#define MORESTACK ___morestack
+#define STACK_EXHAUSTED _rust_stack_exhausted
+#else
+#define MORESTACK __morestack
+#define STACK_EXHAUSTED rust_stack_exhausted
+#endif
+
+.global STACK_EXHAUSTED
+.global MORESTACK
+
+// Unfortunately LLVM yet doesn't support emitting correct debug
+// DWARF information for non-ELF targets so to make it compile
+// on iOS all that directives are simply commented out
+#if defined(__APPLE__)
+#define UNWIND @
+#else
+#define UNWIND
+#endif
 
-.global rust_stack_exhausted
-.global __morestack
-.hidden __morestack
+#if defined(__APPLE__)
+.private_extern MORESTACK
+#else
+.hidden MORESTACK
+#endif
+
+#if !defined(__APPLE__)
+   .type MORESTACK,%function
+#endif
 
 // r4 and r5 are scratch registers for __morestack due to llvm
 // ARMFrameLowering::adjustForSegmentedStacks() implementation.
- .type __morestack,%function
-__morestack:
-       .fnstart
-       // Save frame pointer and return address
-       .save {r4, r5}
-       .save {lr}
-       .save {r6, fp, lr}
+MORESTACK:
+    UNWIND .fnstart
+
+    // Save frame pointer and return address
+    UNWIND .save {r4, r5}
+    UNWIND .save {lr}
+    UNWIND .save {r6, fp, lr}
     push {r6, fp, lr}
 
-       .movsp r6
-       mov r6, sp
-       .setfp fp, sp, #4
-       add fp, sp, #4
+    UNWIND .movsp r6
+    mov r6, sp
+    UNWIND .setfp fp, sp, #4
+    add fp, sp, #4
 
     // Save argument registers of the original function
     push {r0, r1, r2, r3, lr}
 
     // Create new stack
-    bl rust_stack_exhausted@plt
+    bl STACK_EXHAUSTED@plt
 
     // the above function ensures that it never returns
-    .fnend
+    UNWIND  .fnend
index cce14ed5a3ecf09f01ba2c2a1e9290d674a7a01d..94cfcff039e4a3f50d86686c7a42d577d0894030 100644 (file)
@@ -1,3 +1,5 @@
+// Do not compile anything here for iOS
+#if !defined(__APPLE__)
 // Mark stack as non-executable
 #if defined(__linux__) && defined(__ELF__)
 .section       .note.GNU-stack, "", %progbits
@@ -6,16 +8,15 @@
 .text
 .code 32
 .arm
-#if defined(__APPLE__)
-.align 2
-#else
 .align
-#endif
 
-.globl record_sp_limit
-.globl get_sp_limit
+#define RECORD_SP_LIMIT record_sp_limit
+#define GET_SP_LIMIT    get_sp_limit
+
+.globl         RECORD_SP_LIMIT
+.globl GET_SP_LIMIT
 
-record_sp_limit:
+RECORD_SP_LIMIT:
        // First, try to read TLS address from coprocessor
        mrc p15, #0, r3, c13, c0, #3
        cmp r3, #0
@@ -27,12 +28,12 @@ record_sp_limit:
        add r3, r3, #252
 #elif __linux__
        add r3, r3, #4
-#endif
+#endif // ANDROID
 
        str r0, [r3]
        mov pc, lr
 
-get_sp_limit:
+GET_SP_LIMIT:
        // First, try to read TLS address from coprocessor
        mrc p15, #0, r3, c13, c0, #3
        cmp r3, #0
@@ -44,7 +45,8 @@ get_sp_limit:
        add r3, r3, #252
 #elif __linux__
        add r3, r3, #4
-#endif
+#endif  // __ANDROID__
 
        ldr r0, [r3]
        mov pc, lr
+#endif