1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
extern crate psm;
psm::psm_stack_manipulation! {
yes {
use std::alloc;
#[inline(never)]
fn fib(n: usize, stack_limit: *mut u8) -> Option<u64> {
// match psm::StackDirection::new() {
// psm::StackDirection::Ascending => if psm::stack_pointer() > stack_limit {
// return None;
// }
// psm::StackDirection::Descending => if psm::stack_pointer() < stack_limit {
// return None;
// }
// }
match n {
0 => Some(0),
1 => Some(1),
_ => fib(n - 1, stack_limit).and_then(|x| fib(n - 2, stack_limit).map(|y| x + y)),
}
}
const STACK_ALIGN: usize = 4096;
const STACK_REDLINE: usize = 512;
const FIB_COUNTS: [(usize, u64); 3] = [
(8, 21),
(16, 987),
(32, 2178309),
];
fn main() {
let mut stack_size = 1024 * 128;
unsafe {
for &(n, expected) in FIB_COUNTS.iter() {
loop {
println!("fib({}) with {} bytes of stack", n, stack_size - STACK_REDLINE);
let layout = alloc::Layout::from_size_align(stack_size, STACK_ALIGN).unwrap();
let new_stack = alloc::alloc(layout);
assert!(!new_stack.is_null(), "allocations must succeed!");
let max_stack = match psm::StackDirection::new() {
psm::StackDirection::Ascending =>
new_stack.offset((stack_size - STACK_REDLINE) as isize),
psm::StackDirection::Descending =>
new_stack.offset(STACK_REDLINE as isize),
};
let result = psm::on_stack(new_stack, stack_size, || {
fib(n, max_stack)
});
alloc::dealloc(new_stack, layout);
if let Some(res) = result {
assert_eq!(res, expected);
println!("fib({}) = {}", n, res);
break;
} else {
println!("Stack not large enough!");
stack_size *= 2;
}
}
}
}
}
}
no {
fn main() {
eprintln!("Stack manipulation not supported by this target");
}
}
}
#[test]
fn run_example() {
main()
}
|