1pub mod llvm;
15
16#[cfg(test)]
17mod test {
18
19 use irvm::{
20 block::{GepIndex, IcmpCond},
21 common::Location,
22 function::Parameter,
23 module::Module,
24 types::{StructType, Type, TypeStorage},
25 value::Operand,
26 };
27
28 use crate::llvm::{JitValue, create_jit_engine, lower_module_to_llvmir};
29
30 #[test]
31 fn test_function_llvm() -> Result<(), Box<dyn std::error::Error>> {
32 let mut module = Module::new("example", Location::unknown());
33 let mut storage = TypeStorage::new();
34 let _bool_ty = storage.add_type(Type::Int(1), Some("bool"));
35 let i32_ty = storage.add_type(Type::Int(32), Some("u32"));
36 let _i64_ty = storage.add_type(Type::Int(64), Some("u64"));
37 let _ptr_ty = storage.add_type(
38 Type::Ptr {
39 pointee: i32_ty,
40 address_space: None,
41 },
42 Some("*i32"),
43 );
44
45 let main_func = module
46 .add_function(
47 "main",
48 &[Parameter::new(i32_ty, Location::Unknown)],
49 Some(i32_ty),
50 Location::Unknown,
51 )
52 .get_id();
53 let test_func = module
54 .add_function(
55 "test",
56 &[Parameter::new(i32_ty, Location::Unknown)],
57 Some(i32_ty),
58 Location::Unknown,
59 )
60 .get_id();
61
62 let test_func_ret_ty = module.get_function(test_func).result_type;
63
64 {
66 let func = module.get_function_mut(main_func);
67 let param = func.param(0)?;
68 let param_dbg = func.create_debug_var_param("argv", i32_ty, 0, &Location::Unknown);
69 let entry_block = func.entry_block;
70
71 let value = func.blocks[entry_block].instr_add(
72 ¶m,
73 &Operand::const_int(4, i32_ty),
74 Location::Unknown,
75 )?;
76
77 func.blocks[entry_block].instr_dbg_value(
78 value.clone(),
79 param_dbg,
80 Location::Unknown,
81 )?;
82
83 let then_block = func.add_block(&[]);
84 let else_block = func.add_block(&[]);
85 let final_block = func.add_block(&[i32_ty]);
86
87 let cond = func.blocks[entry_block].instr_icmp(
88 IcmpCond::Eq,
89 value.clone(),
90 Operand::const_int(6, i32_ty),
91 Location::Unknown,
92 &storage,
93 )?;
94
95 func.blocks[entry_block].instr_cond_jmp(
96 then_block,
97 else_block,
98 &cond,
99 &[],
100 &[],
101 Location::Unknown,
102 );
103
104 {
106 let value = func.blocks[then_block].instr_add(
107 &value,
108 &Operand::const_int(2, i32_ty),
109 Location::Unknown,
110 )?;
111 func.blocks[then_block].instr_jmp(final_block, &[value], Location::Unknown);
112 }
113
114 {
116 let value = func.blocks[else_block].instr_add(
117 &value,
118 &Operand::const_int(6, i32_ty),
119 Location::Unknown,
120 )?;
121 func.blocks[else_block].instr_jmp(final_block, &[value], Location::Unknown);
122 }
123
124 {
126 let param = func.blocks[final_block].arg(0)?;
127 let value = func.blocks[final_block].instr_call(
128 test_func,
129 &[param],
130 test_func_ret_ty.unwrap(),
131 Location::Unknown,
132 )?;
133 func.blocks[final_block].instr_ret(Some(&value), Location::Unknown);
134 }
135 }
136
137 {
139 let func = module.get_function_mut(test_func);
140 let value = func.param(0)?;
141 func.entry_block()
142 .instr_ret(Some(&value), Location::Unknown);
143 }
144
145 let result = test_run_module(
146 &module,
147 &storage,
148 "main",
149 &[JitValue::U32(4)],
150 JitValue::U32(0),
151 )?;
152 assert_eq!(result, JitValue::U32(14));
153
154 Ok(())
155 }
156
157 #[test]
158 fn test_struct() -> Result<(), Box<dyn std::error::Error>> {
159 let mut module = Module::new("example", Location::unknown());
160 let mut storage = TypeStorage::new();
161 let i32_ty = storage.add_type(Type::Int(32), Some("u32"));
162 let ptr_ty = storage.add_type(
163 Type::Ptr {
164 pointee: i32_ty,
165 address_space: None,
166 },
167 Some("*u32"),
168 );
169
170 let strct_type = storage.add_type(
171 Type::Struct(
172 StructType {
173 packed: false,
174 ident: None,
175 fields: vec![ptr_ty, i32_ty],
176 debug_field_names: vec![
177 ("ptr".to_string(), Location::unknown()),
178 ("x".to_string(), Location::unknown()),
179 ],
180 }
181 .into(),
182 ),
183 Some("hello"),
184 );
185
186 let func = module
187 .add_function(
188 "example",
189 &[
190 Parameter::new(i32_ty, Location::Unknown),
191 Parameter::new(strct_type, Location::Unknown),
192 ],
193 None,
194 Location::Unknown,
195 )
196 .get_id();
197
198 let func = module.get_function_mut(func);
199
200 let entry = func.entry_block;
201
202 func.blocks[entry].instr_ret(None, Location::Unknown);
203
204 let ir = lower_module_to_llvmir(&module, &storage)?;
205
206 ir.dump();
207
208 Ok(())
209 }
210
211 #[test]
212 fn test_gep() -> Result<(), Box<dyn std::error::Error>> {
213 let mut module = Module::new("gepexample", Location::unknown());
214 let mut storage = TypeStorage::new();
215 let i32_ty = storage.add_type(Type::Int(32), Some("u32"));
216 let ptr_ty = storage.add_type(
217 Type::Ptr {
218 pointee: i32_ty,
219 address_space: None,
220 },
221 Some("*u32"),
222 );
223
224 let func = module
225 .add_function(
226 "example",
227 &[Parameter::new(i32_ty, Location::Unknown)],
228 Some(i32_ty),
229 Location::Unknown,
230 )
231 .get_id();
232
233 let func = module.get_function_mut(func);
234
235 let entry = func.entry_block;
236
237 let param1 = func.param(0)?;
238
239 let ptr_val =
240 func.blocks[entry].instr_alloca(ptr_ty, 4, None, Location::Unknown, &storage)?;
241 let k1 = Operand::const_int(1, i32_ty);
242 func.blocks[entry].instr_store(
243 ptr_val.clone(),
244 k1.clone(),
245 None,
246 Location::Unknown,
247 &storage,
248 )?;
249
250 let ptr_idx1 = func.blocks[entry].instr_gep(
251 ptr_val,
252 &[GepIndex::Const(1)],
253 ptr_ty,
254 Location::Unknown,
255 &storage,
256 )?;
257 func.blocks[entry].instr_store(
258 ptr_idx1.clone(),
259 param1,
260 None,
261 Location::Unknown,
262 &storage,
263 )?;
264
265 let result = func.blocks[entry].instr_load(ptr_idx1, None, Location::Unknown, &storage)?;
266
267 func.blocks[entry].instr_ret(Some(&result), Location::Unknown);
268
269 let result = test_run_module(
270 &module,
271 &storage,
272 "example",
273 &[JitValue::U32(2)],
274 JitValue::U32(0),
275 )?;
276 assert_eq!(result, JitValue::U32(2));
277
278 Ok(())
279 }
280
281 fn test_run_module(
282 module: &Module,
283 storage: &TypeStorage,
284 name: &str,
285 args: &[JitValue],
286 ret_ty: JitValue,
287 ) -> Result<JitValue, crate::llvm::Error> {
288 let result = lower_module_to_llvmir(module, storage)?;
289 let engine = create_jit_engine(result, 3)?;
290
291 let res = unsafe { engine.execute(name, args, ret_ty)? };
292
293 Ok(res)
294 }
295}