//! 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
// 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);
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
// 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;
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
+ }
}
.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
+// 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
.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
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
add r3, r3, #252
#elif __linux__
add r3, r3, #4
-#endif
+#endif // __ANDROID__
ldr r0, [r3]
mov pc, lr
+#endif