Skip to content

Commit d730ae2

Browse files
committed
Runtime support for arm on iOS
1 parent 9e90a5e commit d730ae2

File tree

4 files changed

+111
-36
lines changed

4 files changed

+111
-36
lines changed

src/librustrt/stack.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,28 @@
2424
//! detection is not guaranteed to continue in the future. Usage of this module
2525
//! is discouraged unless absolutely necessary.
2626
27+
// iOS related notes
28+
//
29+
// It is possible to implement it using idea from
30+
// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
31+
//
32+
// In short: _pthread_{get,set}_specific_direct allows extremely fast
33+
// access, exactly what is required for segmented stack
34+
// There is a pool of reserved slots for Apple internal use (0..119)
35+
// First dynamic allocated pthread key starts with 257 (on iOS7)
36+
// So using slot 149 should be pretty safe ASSUMING space is reserved
37+
// for every key < first dynamic key
38+
//
39+
// There is also an opportunity to steal keys reserved for Garbage Collection
40+
// ranges 80..89 and 110..119, especially considering the fact Garbage Collection
41+
// never supposed to work on iOS. But as everybody knows it - there is a chance
42+
// that those slots will be re-used, like it happened with key 95 (moved from
43+
// JavaScriptCore to CoreText)
44+
//
45+
// Unfortunately Apple rejected patch to LLVM which generated
46+
// corresponding prolog, decision was taken to disable segmented
47+
// stack support on iOS.
48+
2749
pub static RED_ZONE: uint = 20 * 1024;
2850

2951
/// This function is invoked from rust's current __morestack function. Segmented
@@ -193,14 +215,19 @@ pub unsafe fn record_sp_limit(limit: uint) {
193215
// mips, arm - Some brave soul can port these to inline asm, but it's over
194216
// my head personally
195217
#[cfg(target_arch = "mips")]
196-
#[cfg(target_arch = "arm")] #[inline(always)]
218+
#[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
197219
unsafe fn target_record_sp_limit(limit: uint) {
198220
use libc::c_void;
199221
return record_sp_limit(limit as *c_void);
200222
extern {
201223
fn record_sp_limit(limit: *c_void);
202224
}
203225
}
226+
227+
// iOS segmented stack is disabled for now, see related notes
228+
#[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)]
229+
unsafe fn target_record_sp_limit(_: uint) {
230+
}
204231
}
205232

206233
/// The counterpart of the function above, this function will fetch the current
@@ -267,12 +294,20 @@ pub unsafe fn get_sp_limit() -> uint {
267294
// mips, arm - Some brave soul can port these to inline asm, but it's over
268295
// my head personally
269296
#[cfg(target_arch = "mips")]
270-
#[cfg(target_arch = "arm")] #[inline(always)]
297+
#[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)]
271298
unsafe fn target_get_sp_limit() -> uint {
272299
use libc::c_void;
273300
return get_sp_limit() as uint;
274301
extern {
275302
fn get_sp_limit() -> *c_void;
276303
}
277304
}
305+
306+
// iOS doesn't support segmented stacks yet. This function might
307+
// be called by runtime though so it is unsafe to mark it as
308+
// unreachable, let's return a fixed constant.
309+
#[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)]
310+
unsafe fn target_get_sp_limit() -> uint {
311+
1024
312+
}
278313
}

src/rt/arch/arm/_context.S

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,16 @@
1212
.align
1313
#endif
1414

15-
.globl rust_swap_registers
16-
rust_swap_registers:
15+
#if defined(__APPLE__)
16+
#define SWAP_REGISTERS _rust_swap_registers
17+
#define BOOTSTRAP_TASK _rust_bootstrap_green_task
18+
#else
19+
#define SWAP_REGISTERS rust_swap_registers
20+
#define BOOTSTRAP_TASK rust_bootstrap_green_task
21+
#endif
22+
23+
.globl SWAP_REGISTERS
24+
SWAP_REGISTERS:
1725
str r0, [r0, #0]
1826
str r3, [r0, #12]
1927
str r4, [r0, #16]
@@ -53,9 +61,9 @@ rust_swap_registers:
5361
mov pc, lr
5462

5563
// For reasons of this existence, see the comments in x86_64/_context.S
56-
.globl rust_bootstrap_green_task
57-
rust_bootstrap_green_task:
58-
mov r0, r0
59-
mov r1, r3
60-
mov r2, r4
61-
mov pc, r5
64+
.globl BOOTSTRAP_TASK
65+
BOOTSTRAP_TASK:
66+
mov r0, r0
67+
mov r1, r3
68+
mov r2, r4
69+
mov pc, r5

src/rt/arch/arm/morestack.S

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,63 @@
88
.text
99
.code 32
1010
.arm
11+
#if defined(__APPLE__)
12+
.align 2
13+
#else
1114
.align
15+
#endif
16+
17+
#if defined(__APPLE__)
18+
#define MORESTACK ___morestack
19+
#define STACK_EXHAUSTED _rust_stack_exhausted
20+
#else
21+
#define MORESTACK __morestack
22+
#define STACK_EXHAUSTED rust_stack_exhausted
23+
#endif
24+
25+
.global STACK_EXHAUSTED
26+
.global MORESTACK
27+
28+
// Unfortunately LLVM yet doesn't support emitting correct debug
29+
// DWARF information for non-ELF targets so to make it compile
30+
// on iOS all that directives are simply commented out
31+
#if defined(__APPLE__)
32+
#define UNWIND @
33+
#else
34+
#define UNWIND
35+
#endif
1236

13-
.global rust_stack_exhausted
14-
.global __morestack
15-
.hidden __morestack
37+
#if defined(__APPLE__)
38+
.private_extern MORESTACK
39+
#else
40+
.hidden MORESTACK
41+
#endif
42+
43+
#if !defined(__APPLE__)
44+
.type MORESTACK,%function
45+
#endif
1646

1747
// r4 and r5 are scratch registers for __morestack due to llvm
1848
// ARMFrameLowering::adjustForSegmentedStacks() implementation.
19-
.type __morestack,%function
20-
__morestack:
21-
.fnstart
22-
// Save frame pointer and return address
23-
.save {r4, r5}
24-
.save {lr}
25-
.save {r6, fp, lr}
49+
MORESTACK:
50+
UNWIND .fnstart
51+
52+
// Save frame pointer and return address
53+
UNWIND .save {r4, r5}
54+
UNWIND .save {lr}
55+
UNWIND .save {r6, fp, lr}
2656
push {r6, fp, lr}
2757

28-
.movsp r6
29-
mov r6, sp
30-
.setfp fp, sp, #4
31-
add fp, sp, #4
58+
UNWIND .movsp r6
59+
mov r6, sp
60+
UNWIND .setfp fp, sp, #4
61+
add fp, sp, #4
3262

3363
// Save argument registers of the original function
3464
push {r0, r1, r2, r3, lr}
3565

3666
// Create new stack
37-
bl rust_stack_exhausted@plt
67+
bl STACK_EXHAUSTED@plt
3868

3969
// the above function ensures that it never returns
40-
.fnend
70+
UNWIND .fnend

src/rt/arch/arm/record_sp.S

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Do not compile anything here for iOS
2+
#if !defined(__APPLE__)
13
// Mark stack as non-executable
24
#if defined(__linux__) && defined(__ELF__)
35
.section .note.GNU-stack, "", %progbits
@@ -6,16 +8,15 @@
68
.text
79
.code 32
810
.arm
9-
#if defined(__APPLE__)
10-
.align 2
11-
#else
1211
.align
13-
#endif
1412

15-
.globl record_sp_limit
16-
.globl get_sp_limit
13+
#define RECORD_SP_LIMIT record_sp_limit
14+
#define GET_SP_LIMIT get_sp_limit
15+
16+
.globl RECORD_SP_LIMIT
17+
.globl GET_SP_LIMIT
1718

18-
record_sp_limit:
19+
RECORD_SP_LIMIT:
1920
// First, try to read TLS address from coprocessor
2021
mrc p15, #0, r3, c13, c0, #3
2122
cmp r3, #0
@@ -27,12 +28,12 @@ record_sp_limit:
2728
add r3, r3, #252
2829
#elif __linux__
2930
add r3, r3, #4
30-
#endif
31+
#endif // ANDROID
3132

3233
str r0, [r3]
3334
mov pc, lr
3435

35-
get_sp_limit:
36+
GET_SP_LIMIT:
3637
// First, try to read TLS address from coprocessor
3738
mrc p15, #0, r3, c13, c0, #3
3839
cmp r3, #0
@@ -44,7 +45,8 @@ get_sp_limit:
4445
add r3, r3, #252
4546
#elif __linux__
4647
add r3, r3, #4
47-
#endif
48+
#endif // __ANDROID__
4849

4950
ldr r0, [r3]
5051
mov pc, lr
52+
#endif

0 commit comments

Comments
 (0)