Skip to main content

on_stack_fibo/
on_stack_fibo.rs

1extern 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 psm::StackDirection::new() {
10            //     psm::StackDirection::Ascending => if psm::stack_pointer() > stack_limit {
11            //         return None;
12            //     }
13            //     psm::StackDirection::Descending => if psm::stack_pointer() < stack_limit {
14            //         return None;
15            //     }
16            // }
17
18            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}