1#![cfg_attr(not(test), no_std)]
2#![allow(non_upper_case_globals)]
3#![allow(non_camel_case_types)]
4#![allow(non_snake_case)]
5
6use core::{ffi::CStr, ptr::null_mut, str::Utf8Error};
7
8use const_default::ConstDefault;
9use derive_more::From;
10use typed_builder::TypedBuilder;
11
12include!("./wrapper.rs");
13
14#[inline(always)]
15pub fn has_cpu_feature(feature_type: sljit_s32) -> sljit_s32 {
16 unsafe { sljit_has_cpu_feature(feature_type) }
17}
18
19#[inline(always)]
20pub fn cmp_info(type_: sljit_s32) -> sljit_s32 {
21 unsafe { sljit_cmp_info(type_) }
22}
23
24#[inline(always)]
25pub fn set_jump_addr(addr: sljit_uw, new_target: sljit_uw, executable_offset: sljit_sw) {
26 unsafe { sljit_set_jump_addr(addr, new_target, executable_offset) }
27}
28
29#[inline(always)]
30pub fn set_const(
31 addr: sljit_uw,
32 op: sljit_s32,
33 new_constant: sljit_sw,
34 executable_offset: sljit_sw,
35) {
36 unsafe { sljit_set_const(addr, op, new_constant, executable_offset) }
37}
38
39#[inline(always)]
40pub fn get_register_index(type_: sljit_s32, reg: sljit_s32) -> sljit_s32 {
41 unsafe { sljit_get_register_index(type_, reg) }
42}
43
44#[inline(always)]
45pub fn get_platform_name() -> Result<&'static str, Utf8Error> {
46 unsafe { CStr::from_ptr(sljit_get_platform_name()).to_str() }
47}
48
49#[repr(transparent)]
50#[derive(From)]
51pub struct Constant(*mut sljit_const);
52
53impl Constant {
54 #[inline(always)]
55 pub fn addr(&self) -> sljit_uw {
56 unsafe { sljit_get_const_addr(self.0) }
57 }
58}
59
60#[repr(transparent)]
61#[derive(From)]
62pub struct Label(*mut sljit_label);
63
64impl Label {
65 #[inline(always)]
66 pub fn addr(&self) -> sljit_uw {
67 unsafe { sljit_get_label_addr(self.0) }
68 }
69}
70
71#[repr(transparent)]
72#[derive(From)]
73pub struct Jump(*mut sljit_jump);
74
75impl Jump {
76 #[inline(always)]
77 pub fn set_label(&mut self, label: &Label) {
78 unsafe { sljit_set_label(self.0, label.0) }
79 }
80
81 #[inline(always)]
82 pub fn set_target(&mut self, target: sljit_uw) {
83 unsafe { sljit_set_target(self.0, target) }
84 }
85
86 #[inline(always)]
87 pub fn addr(&self) -> sljit_uw {
88 unsafe { sljit_get_jump_addr(self.0) }
89 }
90}
91
92#[repr(transparent)]
93#[derive(From)]
94pub struct GeneratedCode(*mut ::core::ffi::c_void);
95
96impl GeneratedCode {
97 #[inline(always)]
98 pub fn get(&self) -> *const ::core::ffi::c_void {
99 self.0
100 }
101}
102
103impl Drop for GeneratedCode {
104 #[inline(always)]
105 fn drop(&mut self) {
106 unsafe {
107 sljit_free_code(self.0, null_mut());
108 }
109 }
110}
111
112#[repr(transparent)]
113#[derive(From)]
114pub struct Compiler(*mut sljit_compiler);
115
116impl Default for Compiler {
117 #[inline(always)]
118 fn default() -> Self {
119 Self::new()
120 }
121}
122
123impl Compiler {
124 #[inline(always)]
125 pub fn new() -> Self {
126 Self(unsafe { sljit_create_compiler(null_mut()) })
127 }
128}
129
130impl Compiler {
131 #[inline(always)]
132 pub fn generate_code(self) -> GeneratedCode {
133 let code = unsafe { sljit_generate_code(self.0, 0, null_mut()) };
134 drop(self);
135 GeneratedCode(code)
136 }
137}
138
139impl Drop for Compiler {
140 #[inline(always)]
141 fn drop(&mut self) {
142 unsafe {
143 sljit_free_compiler(self.0);
144 }
145 }
146}
147
148include!("./generated.mid.rs");
149
150#[cfg(test)]
151mod integration_tests {
152 use core::{ffi::c_int, mem::transmute};
153
154 use super::*;
155
156 #[test]
157 fn test_add3() {
158 unsafe {
159 let mut compiler = Compiler::new();
160 compiler.emit_enter(
161 0,
162 SLJIT_ARG_TYPE_W
163 | (SLJIT_ARG_TYPE_W << 4)
164 | (SLJIT_ARG_TYPE_W << (2 * 4))
165 | (SLJIT_ARG_TYPE_W << (3 * 4)),
166 1,
167 3,
168 0,
169 );
170 compiler.emit_op1(SLJIT_MOV, SLJIT_R0, 0, SLJIT_S0, 0);
171
172 compiler.emit_op2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S1, 0);
174
175 compiler.emit_op2(SLJIT_ADD, SLJIT_R0, 0, SLJIT_R0, 0, SLJIT_S2, 0);
177
178 compiler.emit_return(SLJIT_MOV, SLJIT_R0, 0);
181
182 let code = compiler.generate_code();
183 let func: fn(c_int, c_int, c_int) -> c_int = transmute(code.get());
184 assert_eq!(func(4, 5, 6), 4 + 5 + 6);
185 }
186 }
187
188 #[test]
189 fn test_array_access() {
190 extern "C" fn print_num(a: isize) {
191 println!("num = {a}");
192 }
193
194 unsafe {
195 let arr: &[isize] = &[3, -10, 4, 6, 8, 12, 2000, 0];
196 let mut compiler = Compiler::new();
197 compiler.emit_enter(
198 0,
199 SLJIT_ARG_TYPE_W
200 | (SLJIT_ARG_TYPE_P << 4)
201 | (SLJIT_ARG_TYPE_W << (2 * 4))
202 | (SLJIT_ARG_TYPE_W << (3 * 4)),
203 4,
204 3,
205 0,
206 );
207
208 compiler.emit_op2(SLJIT_XOR, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_S2, 0);
210
211 compiler.emit_op1(
213 SLJIT_MOV,
214 SLJIT_S1,
215 0,
216 SLJIT_IMM,
217 arr.len().try_into().unwrap(),
218 );
219
220 let loop_start = compiler.emit_label();
222
223 let mut out = compiler.emit_cmp(SLJIT_GREATER_EQUAL, SLJIT_S2, 0, SLJIT_S1, 0);
225
226 compiler.emit_op1(
228 SLJIT_MOV,
229 SLJIT_R0,
230 0,
231 SLJIT_MEM | SLJIT_S0 | (SLJIT_S2 << 8),
232 SLJIT_WORD_SHIFT.into(),
233 );
234
235 compiler.emit_icall(
237 SLJIT_CALL,
238 SLJIT_ARG_TYPE_RET_VOID | (SLJIT_ARG_TYPE_W << 4),
239 SLJIT_IMM,
240 print_num as _,
241 );
242 compiler.emit_op2(SLJIT_ADD, SLJIT_S2, 0, SLJIT_S2, 0, SLJIT_IMM, 1);
244 compiler.emit_jump(SLJIT_JUMP).set_label(&loop_start);
246 out.set_label(&compiler.emit_label());
248 compiler.emit_return(SLJIT_MOV, SLJIT_S1, 0);
250
251 let code = compiler.generate_code();
252 let func: fn(*const isize, isize, isize) -> isize = transmute(code.get());
253
254 assert_eq!(
255 func(arr.as_ptr(), arr.len().try_into().unwrap(), 0),
256 arr.len().try_into().unwrap()
257 );
258 }
259 }
260}