lightning_sys/
jit.rs

1#![allow(clippy::mutex_atomic)] // Avoid clippy warning about JITS_MADE
2#![allow(clippy::new_without_default)] // Avoid clippy warning about Jit::new
3
4use std::os::raw;
5use std::ptr;
6use std::sync::Mutex;
7
8use crate::bindings;
9use crate::JitState;
10
11use std::marker::PhantomData;
12
13#[derive(Debug)]
14pub struct Jit<'a>(PhantomData<&'a ()>);
15
16lazy_static! {
17    static ref JITS_MADE: Mutex<usize> = Mutex::new(0);
18}
19
20impl<'a> Jit<'a> {
21    pub fn new() -> Jit<'a> {
22        let mut m = JITS_MADE.lock().unwrap();
23
24        if *m == 0 {
25            unsafe {
26                //TODO: figure out how to get ptr to argv[0]
27                bindings::init_jit(ptr::null::<raw::c_char>());
28            }
29        }
30
31        *m += 1;
32        Jit(PhantomData)
33    }
34
35    // This takes &mut self instead of &self because the unsafe operations wrapped herein are
36    // inherently mutating.
37    pub fn new_state(&mut self) -> JitState {
38        JitState {
39            state: unsafe {
40                bindings::jit_new_state()
41            },
42            phantom: PhantomData,
43        }
44    }
45
46    pub fn r_num(&self) -> bindings::jit_gpr_t {
47        unsafe {
48            bindings::lgsys_JIT_R_NUM()
49        }
50    }
51
52    pub fn v_num(&self) -> bindings::jit_gpr_t {
53        unsafe {
54            bindings::lgsys_JIT_V_NUM()
55        }
56    }
57
58    pub fn f_num(&self) -> bindings::jit_gpr_t {
59        unsafe {
60            bindings::lgsys_JIT_F_NUM()
61        }
62    }
63
64}
65
66impl<'a> Drop for Jit<'a> {
67    fn drop(&mut self) {
68        let mut m = JITS_MADE.lock().unwrap();
69        *m -= 1;
70
71        if *m == 0 {
72            unsafe {
73                bindings::finish_jit();
74            }
75        }
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use crate::Jit;
82    use crate::Reg;
83    use crate::types::ToFFI;
84
85    #[test]
86    fn test_jit() {
87        {
88            let _jit = Jit::new();
89            Jit::new();
90        }
91
92        {
93            let _jit = Jit::new();
94            Jit::new();
95        }
96
97    }
98
99    #[test]
100    fn test_reg_num() {
101        let jit = Jit::new();
102        assert!(jit.r_num() >= 3);
103        assert!(jit.v_num() >= 3);
104        assert!(jit.f_num() >= 6);
105    }
106
107    #[test]
108    fn test_to_ffi() {
109        let jit = Jit::new();
110
111        assert!(std::panic::catch_unwind(|| Reg::R(jit.r_num()).to_ffi()).is_err());
112        Reg::R(jit.r_num()-1).to_ffi();
113        Reg::R(0).to_ffi();
114
115        assert!(std::panic::catch_unwind(|| Reg::V(jit.v_num()).to_ffi()).is_err());
116        Reg::V(jit.v_num()-1).to_ffi();
117        Reg::V(0).to_ffi();
118
119        assert!(std::panic::catch_unwind(|| Reg::F(jit.f_num()).to_ffi()).is_err());
120        Reg::F(jit.f_num()-1).to_ffi();
121        Reg::F(0).to_ffi();
122    }
123}