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