1use std::collections;
3use std::fmt;
4use std::mem;
5use std::ops;
6
7use cranelift_module;
8use cranelift_simplejit;
9
10pub struct Module {
12 compiled: cranelift_module::Module<cranelift_simplejit::SimpleJITBackend>,
13 function_ids: collections::HashMap<String, cranelift_module::FuncId>,
14}
15
16pub trait Function {
18 unsafe fn from_ptr(ptr: *const u8) -> Self;
25}
26
27macro_rules! define_function {
28 ($name:ident, $doc:expr, $ret:ident) => { define_function!($name, $doc, $ret,); };
29 ($name:ident, $doc:expr, $ret:ident, $($arg:ident),*) => {
30 #[doc=$doc]
31 pub struct $name<$ret, $($arg),*>(extern "C" fn($($arg),*) -> $ret);
32
33 impl<$ret, $($arg),*> ops::Deref for $name<$ret, $($arg),*> {
34 type Target = extern "C" fn($($arg),*) -> $ret;
35
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39 }
40
41 impl<$ret, $($arg),*> Function for $name<$ret, $($arg),*> {
42 unsafe fn from_ptr(ptr: *const u8) -> Self {
43 $name(mem::transmute(ptr))
44 }
45 }
46
47 impl<$ret, $($arg),*> fmt::Debug for $name<$ret, $($arg),*> {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 f.debug_struct(stringify!($name)).finish()
50 }
51 }
52 };
53}
54
55define_function!(Function0, "A function taking 0 arguments", R);
56define_function!(Function1, "A function taking 1 arguments", R, A1);
57define_function!(Function2, "A function taking 2 arguments", R, A1, A2);
58define_function!(Function3, "A function taking 3 arguments", R, A1, A2, A3);
59define_function!(
60 Function4,
61 "A function taking 4 arguments",
62 R,
63 A1,
64 A2,
65 A3,
66 A4
67);
68define_function!(
69 Function5,
70 "A function taking 5 arguments",
71 R,
72 A1,
73 A2,
74 A3,
75 A4,
76 A5
77);
78define_function!(
79 Function6,
80 "A function taking 6 arguments",
81 R,
82 A1,
83 A2,
84 A3,
85 A4,
86 A5,
87 A6
88);
89
90impl Module {
91 pub(crate) fn new(
92 compiled: cranelift_module::Module<cranelift_simplejit::SimpleJITBackend>,
93 function_ids: collections::HashMap<String, cranelift_module::FuncId>,
94 ) -> Self {
95 Module {
96 compiled,
97 function_ids,
98 }
99 }
100
101 pub fn function<F>(&mut self, name: &str) -> Option<F>
105 where
106 F: Function,
107 {
108 if let Some(id) = self.function_ids.get(name) {
109 Some(unsafe { F::from_ptr(self.compiled.get_finalized_function(*id)) })
111 } else {
112 None
113 }
114 }
115}
116
117impl fmt::Debug for Module {
118 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
119 f.debug_struct("Module").finish()
120 }
121}