Runtime support for arm on iOS
This commit is contained in:
parent
9e90a5e72c
commit
d730ae2fb0
4 changed files with 111 additions and 36 deletions
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -8,33 +8,63 @@
|
|||
.text
|
||||
.code 32
|
||||
.arm
|
||||
#if defined(__APPLE__)
|
||||
.align 2
|
||||
#else
|
||||
.align
|
||||
#endif
|
||||
|
||||
.global rust_stack_exhausted
|
||||
.global __morestack
|
||||
.hidden __morestack
|
||||
#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
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
record_sp_limit:
|
||||
.globl RECORD_SP_LIMIT
|
||||
.globl GET_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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue