about summary refs log tree commit diff
diff options
context:
space:
mode:
authorValerii Hiora <valerii.hiora@gmail.com>2014-05-05 10:08:34 +0300
committerValerii Hiora <valerii.hiora@gmail.com>2014-06-12 20:24:08 +0300
commitd730ae2fb0c455775fb1962454537c79e54f817e (patch)
treec8c6c744b50b0e2de0b444807cfbaaaec124bac1
parent9e90a5e72c760cee268b714aced54ed30d04fa3c (diff)
downloadrust-d730ae2fb0c455775fb1962454537c79e54f817e.tar.gz
rust-d730ae2fb0c455775fb1962454537c79e54f817e.zip
Runtime support for arm on iOS
-rw-r--r--src/librustrt/stack.rs39
-rw-r--r--src/rt/arch/arm/_context.S24
-rw-r--r--src/rt/arch/arm/morestack.S62
-rw-r--r--src/rt/arch/arm/record_sp.S22
4 files changed, 111 insertions, 36 deletions
diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs
index 148d93adc84..aac773f6f85 100644
--- a/src/librustrt/stack.rs
+++ b/src/librustrt/stack.rs
@@ -24,6 +24,28 @@
 //! 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 @@ pub unsafe fn 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 @@ pub unsafe fn 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 @@ pub unsafe fn 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 @@ pub unsafe fn 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
+    }
 }
diff --git a/src/rt/arch/arm/_context.S b/src/rt/arch/arm/_context.S
index fb6db57414a..38fc4827f58 100644
--- a/src/rt/arch/arm/_context.S
+++ b/src/rt/arch/arm/_context.S
@@ -12,8 +12,16 @@
 .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
diff --git a/src/rt/arch/arm/morestack.S b/src/rt/arch/arm/morestack.S
index 219f0962d77..0b9012cc2a8 100644
--- a/src/rt/arch/arm/morestack.S
+++ b/src/rt/arch/arm/morestack.S
@@ -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
diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S
index cce14ed5a3e..94cfcff039e 100644
--- a/src/rt/arch/arm/record_sp.S
+++ b/src/rt/arch/arm/record_sp.S
@@ -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