1use std::ffi::CString;
2use std::os::raw::c_uint;
3use gnu_libjit_sys::{jit_function_compile, jit_insn_pow, jit_insn_acos, jit_insn_asin, jit_insn_atan, jit_insn_cos, jit_insn_cosh, jit_insn_log, jit_insn_log10, jit_insn_sin, jit_insn_sinh, jit_insn_sqrt, jit_insn_tan, jit_insn_tanh, jit_value_create_float64_constant, jit_insn_not, jit_insn_ge, jit_insn_le, jit_insn_gt, jit_insn_lt, jit_insn_ne, jit_insn_and, jit_insn_or, jit_insn_xor, jit_function_t, jit_value_create_long_constant, jit_value_create_float32_constant, jit_value_create_nint_constant, jit_value_create, jit_type_float32, jit_insn_eq, jit_type_nint, jit_type_int, jit_type_uint, jit_type_ushort, jit_type_short, jit_insn_add, jit_insn_div, jit_insn_sub, jit_insn_call_native, jit_insn_mul, jit_insn_return, jit_type_create_signature, jit_type_void, jit_value_get_param, jit_dump_function, jit_abi_t, jit_function_to_closure, jit_insn_branch_if, jit_label_t, jit_insn_label, jit_insn_branch_if_not, jit_type_long, jit_type_ulong, jit_type_sbyte, jit_type_float64, jit_type_ubyte, jit_type_void_ptr, jit_insn_alloca, jit_insn_load, jit_insn_store, jit_insn_branch, jit_insn_load_relative, jit_insn_call, jit_value_t, jit_type_t, jit_insn_rem, jit_insn_exp, jit_float32_rint, jit_insn_ceil, jit_insn_floor, jit_insn_rint, jit_insn_round, jit_insn_trunc, jit_insn_load_elem_address};
4use libc::{c_char, c_void};
5use crate::context::Exception;
6use crate::{Abi, JitType};
7use crate::label::Label;
8use crate::util::dump;
9use crate::value::Value;
10
11macro_rules! op {
12 ($fn_name:ident, $jit_op:ident) => {
13 pub fn $fn_name(&mut self, left: &Value, right: &Value) -> Value {
14 unsafe {
15 let v = $jit_op(self.function, left.value, right.value);
16 Value::new(v)
17 }
18 }
19 }
20}
21
22macro_rules! ret_op {
23 ($fn_name:ident, $jit_op:ident) => {
24 pub fn $fn_name(&mut self, value:& Value) {
25 unsafe {
26 $jit_op(self.function, value.value);
27 }
28 }
29 }
30}
31
32macro_rules! unary_op {
33 ($fn_name:ident, $jit_op:ident) => {
34 pub fn $fn_name(&mut self, value: &Value) -> Value {
35 unsafe {
36 let v =$jit_op(self.function, value.value);
37 Value::new(v)
38 }
39 }
40 }
41}
42
43#[derive(Clone)]
44pub struct Function {
45 params: Vec<JitType>,
46 function: jit_function_t,
47 signature: jit_type_t,
48}
49
50macro_rules! constant_fn {
51 ($fn_name:ident, $const_ty:ty, $typ: expr, $creator:expr) => {
52 pub fn $fn_name(&mut self, constant_value: $const_ty) -> Value {
53 let val = unsafe {
54 $creator(self.function, $typ, constant_value)
55 };
56 Value::new(val)
57
58 }
59 }
60}
61
62macro_rules! constant_fn_long {
63 ($fn_name:ident, $const_ty:ty, $typ: expr, $creator:expr) => {
64 pub fn $fn_name(&mut self, constant_value: $const_ty) -> Value {
65 let val = unsafe {
66 $creator(self.function, $typ, constant_value as ::std::os::raw::c_long)
67 };
68 Value::new(val)
69
70 }
71 }
72}
73
74
75impl Function {
76 pub(crate) fn new(function: jit_function_t, signature: jit_type_t, params: Vec<JitType>) -> Function {
78 Function { function, params, signature }
79 }
80
81 pub fn compile(&self) {
82 unsafe {
83 if jit_function_compile(self.function) == 0 {
84 panic!("Failed to compile function");
85 }
86 }
87 }
88
89 pub fn alloca(&self, size: ::std::os::raw::c_long) -> Value {
90 unsafe {
91 let bytes = jit_value_create_nint_constant(self.function, jit_type_ubyte, size);
92 Value::new(jit_insn_alloca(self.function, bytes))
93 }
94 }
95
96 pub fn dump(&self) -> Result<String, std::fmt::Error> {
97 dump(|fd| unsafe {
98 jit_dump_function(std::mem::transmute(fd), self.function, "no-name-func".as_ptr() as *const ::std::os::raw::c_char);
99 })
100 }
101
102 pub fn to_closure<T>(&self) -> T {
105 unsafe {
106 let void_ptr = jit_function_to_closure(self.function);
107 std::mem::transmute_copy::<*mut c_void, T>(&void_ptr)
108 }
109 }
110
111 pub fn insn_call_native(&self, native_func: *mut ::std::os::raw::c_void, params: Vec<Value>, return_type: Option<JitType>) -> Value {
113 let c_str = CString::new("native-func").unwrap();
114 let c_str_ptr = c_str.as_ptr();
115 let mut sig_args = vec![];
116 let mut args = vec![];
117 for param in params.iter() {
118 sig_args.push(param.value_type().inner);
119 args.push(param.value);
120 }
121 unsafe {
122 let signature = jit_type_create_signature(
123 Abi::Cdecl as jit_abi_t,
124 if let Some(jtype) = return_type { jtype.inner } else { jit_type_void },
125 sig_args.as_mut_ptr(),
126 params.len() as c_uint,
127 1,
128 );
129 Value::new(jit_insn_call_native(self.function,
130 c_str_ptr,
131 native_func,
132 signature,
133 args.as_mut_ptr(),
134 params.len() as c_uint,
135 0,
136 ))
137 }
138 }
139
140 pub fn arg(&self, idx: i32) -> Result<Value, Exception> {
142 let _arg_type = match self.params.get(idx as usize) {
143 Some(arg_type) => arg_type,
144 None => {
145 return Err(Exception::ArgIndexTooLarge(format!("Function has {} args but you requested index {}", self.params.len(), idx)));
146 }
147 };
148 let value = unsafe {
149 jit_value_get_param(self.function, idx as c_uint)
150 };
151 Ok(Value::new(value))
152 }
153
154 op!(insn_mult, jit_insn_mul);
155 op!(insn_add, jit_insn_add);
156 op!(insn_pow, jit_insn_pow);
157 op!(insn_rem, jit_insn_rem);
158 op!(insn_div, jit_insn_div);
159 op!(insn_sub, jit_insn_sub);
160 op!(insn_eq, jit_insn_eq);
161 op!(insn_and, jit_insn_and);
162 op!(insn_or, jit_insn_or);
163 op!(insn_xor, jit_insn_xor);
164 op!(insn_le, jit_insn_le);
165 op!(insn_lt, jit_insn_lt);
166 op!(insn_ge, jit_insn_ge);
167 op!(insn_gt, jit_insn_gt);
168 op!(insn_ne, jit_insn_ne);
169
170 unary_op!(insn_acos, jit_insn_acos);
171 unary_op!(insn_asin, jit_insn_asin);
172 unary_op!(insn_atan, jit_insn_atan);
173 unary_op!(insn_cos, jit_insn_cos);
174 unary_op!(insn_cosh, jit_insn_cosh);
175 unary_op!(insn_exp, jit_insn_exp);
176 unary_op!(insn_log, jit_insn_log);
177 unary_op!(insn_log10, jit_insn_log10);
178 unary_op!(insn_sin, jit_insn_sin);
179 unary_op!(insn_sinh, jit_insn_sinh);
180 unary_op!(insn_sqrt, jit_insn_sqrt);
181 unary_op!(insn_tan, jit_insn_tan);
182 unary_op!(insn_tanh, jit_insn_tanh);
183
184 ret_op!(insn_return, jit_insn_return);
185
186 unary_op!(insn_not, jit_insn_not);
187
188 pub fn insn_branch(&self, label: &mut Label) {
189 unsafe { jit_insn_branch(self.function, &mut label.inner as *mut jit_label_t); }
190 }
191
192 pub fn insn_branch_if(&self, value: &Value, label: &mut Label) {
193 unsafe { jit_insn_branch_if(self.function, value.value, &mut label.inner as *mut jit_label_t); }
194 }
195
196 pub fn insn_branch_if_not(&self, value: &Value, label: &mut Label) {
197 unsafe { jit_insn_branch_if_not(self.function, value.value, &mut label.inner as *mut jit_label_t); }
198 }
199
200 pub fn insn_load(&mut self, ptr: &Value) -> Value {
201 unsafe {
202 let value = jit_insn_load(self.function, ptr.value);
203 Value::new(value)
205 }
206 }
207
208 pub fn insn_store(&mut self, ptr: &Value, value: &Value) {
209 unsafe {
210 jit_insn_store(self.function, ptr.value, value.value);
211 }
212 }
213
214 pub fn insn_call(&mut self, function: &Function, args: Vec<Value>) -> Value {
215 let mut values: Vec<jit_value_t> = args.iter().map(|arg| arg.value.clone()).collect();
216 let val = unsafe {
217 jit_insn_call(self.function, "-no-name-".as_ptr() as *mut c_char, function.function, function.signature, values.as_mut_ptr(), args.len() as c_uint, 0)
218 };
219 Value::new(val)
220 }
221
222 pub fn insn_load_relative(&mut self, base_ptr: &Value, offset_bytes: ::std::os::raw::c_long, typ: &JitType) -> Value {
223 let res = unsafe {
224 jit_insn_load_relative(self.function, base_ptr.value, offset_bytes, typ.inner)
225 };
226 Value::new(res)
227 }
228
229 pub fn create_value_int(&mut self) -> Value {
230 Value::new(unsafe {
231 jit_value_create(self.function, jit_type_int)
232 })
233 }
234
235 pub fn create_value_void_ptr(&mut self) -> Value {
236 Value::new(unsafe {
237 jit_value_create(self.function, jit_type_void_ptr)
238 })
239 }
240 pub fn create_value_float32(&mut self) -> Value {
241 Value::new(unsafe {
242 jit_value_create(self.function, jit_type_float32)
243 })
244 }
245 pub fn create_value_float64(&mut self) -> Value {
246 Value::new(unsafe {
247 jit_value_create(self.function, jit_type_float64)
248 })
249 }
250
251 pub fn insn_label(&self, label: &mut Label) {
252 let lbl_ptr = (&mut label.inner) as *mut jit_label_t;
253 unsafe { jit_insn_label(self.function, lbl_ptr); }
254 }
255
256 pub fn insn_ceil(&self, value: &Value) -> Value {
258 Value::new(unsafe { jit_insn_ceil(self.function, value.value) })
259 }
260
261 pub fn insn_floor(&self, value: &Value) -> Value {
263 Value::new(unsafe { jit_insn_floor(self.function, value.value) })
264 }
265
266 pub fn insn_rint(&self, value: &Value) -> Value {
268 Value::new(unsafe { jit_insn_rint(self.function, value.value) })
269 }
270
271 pub fn insn_round(&self, value: &Value) -> Value {
273 Value::new(unsafe { jit_insn_round(self.function, value.value) })
274 }
275
276 pub fn insn_trunc(&self, value: &Value) -> Value {
278 Value::new(unsafe { jit_insn_trunc(self.function, value.value) })
279 }
280
281 pub fn insn_load_elem_address(&self, base_addr: &Value, index: &Value, elem_type: &JitType) -> Value {
285 Value::new(unsafe { jit_insn_load_elem_address(self.function, base_addr.value, index.value, elem_type.inner) })
286 }
287
288 constant_fn!(create_float32_constant, ::std::os::raw::c_float, jit_type_float32, jit_value_create_float32_constant);
289 constant_fn!(create_float64_constant, ::std::os::raw::c_double, jit_type_float64, jit_value_create_float64_constant);
290 constant_fn!(create_long_constant, ::std::os::raw::c_long, jit_type_long, jit_value_create_long_constant);
291
292 constant_fn_long!(create_sbyte_constant, ::std::os::raw::c_char, jit_type_sbyte, jit_value_create_long_constant);
293 constant_fn_long!(create_ubyte_constant, ::std::os::raw::c_uchar, jit_type_ubyte, jit_value_create_long_constant);
294 constant_fn_long!(create_short_constant, ::std::os::raw::c_long, jit_type_short, jit_value_create_long_constant);
295 constant_fn_long!(create_ushort_constant, ::std::os::raw::c_ulong, jit_type_ushort, jit_value_create_long_constant);
296 constant_fn_long!(create_int_constant, ::std::os::raw::c_int, jit_type_int, jit_value_create_long_constant);
297 constant_fn_long!(create_ulong_constant, ::std::os::raw::c_ulong, jit_type_ulong, jit_value_create_long_constant);
298 constant_fn_long!(create_uint_constant, ::std::os::raw::c_uint, jit_type_uint, jit_value_create_long_constant);
299 constant_fn_long!(create_nint_constant, ::std::os::raw::c_int, jit_type_nint, jit_value_create_long_constant);
300 constant_fn_long!(create_nuint_constant, ::std::os::raw::c_int, jit_type_nint, jit_value_create_long_constant);
301 constant_fn_long!(create_void_ptr_constant, *mut ::std::os::raw::c_void, jit_type_void_ptr, jit_value_create_long_constant);
302}
303