1 use codegen::ir::UserFuncName;
2 use cranelift::prelude::*;
3 use cranelift_jit::{JITBuilder, JITModule};
4 use cranelift_module::{Linkage, Module, default_libcall_names};
5 use std::mem;
6
main()7 fn main() {
8 let mut flag_builder = settings::builder();
9 flag_builder.set("use_colocated_libcalls", "false").unwrap();
10 // FIXME set back to true once the x64 backend supports it.
11 flag_builder.set("is_pic", "false").unwrap();
12 let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
13 panic!("host machine is not supported: {msg}");
14 });
15 let isa = isa_builder
16 .finish(settings::Flags::new(flag_builder))
17 .unwrap();
18 let mut module = JITModule::new(JITBuilder::with_isa(isa, default_libcall_names()));
19
20 let mut ctx = module.make_context();
21 let mut func_ctx = FunctionBuilderContext::new();
22
23 let mut sig_a = module.make_signature();
24 sig_a.params.push(AbiParam::new(types::I32));
25 sig_a.returns.push(AbiParam::new(types::I32));
26
27 let mut sig_b = module.make_signature();
28 sig_b.returns.push(AbiParam::new(types::I32));
29
30 let func_a = module
31 .declare_function("a", Linkage::Local, &sig_a)
32 .unwrap();
33 let func_b = module
34 .declare_function("b", Linkage::Local, &sig_b)
35 .unwrap();
36
37 ctx.func.signature = sig_a;
38 ctx.func.name = UserFuncName::user(0, func_a.as_u32());
39
40 {
41 let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
42 let block = bcx.create_block();
43
44 bcx.switch_to_block(block);
45 bcx.append_block_params_for_function_params(block);
46 let param = bcx.block_params(block)[0];
47 let cst = bcx.ins().iconst(types::I32, 37);
48 let add = bcx.ins().iadd(cst, param);
49 bcx.ins().return_(&[add]);
50 bcx.seal_all_blocks();
51 bcx.finalize();
52 }
53 module.define_function(func_a, &mut ctx).unwrap();
54 module.clear_context(&mut ctx);
55
56 ctx.func.signature = sig_b;
57 ctx.func.name = UserFuncName::user(0, func_b.as_u32());
58
59 {
60 let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
61 let block = bcx.create_block();
62
63 bcx.switch_to_block(block);
64 let local_func = module.declare_func_in_func(func_a, &mut bcx.func);
65 let arg = bcx.ins().iconst(types::I32, 5);
66 let call = bcx.ins().call(local_func, &[arg]);
67 let value = {
68 let results = bcx.inst_results(call);
69 assert_eq!(results.len(), 1);
70 results[0]
71 };
72 bcx.ins().return_(&[value]);
73 bcx.seal_all_blocks();
74 bcx.finalize();
75 }
76 module.define_function(func_b, &mut ctx).unwrap();
77 module.clear_context(&mut ctx);
78
79 // Perform linking.
80 module.finalize_definitions().unwrap();
81
82 // Get a raw pointer to the generated code.
83 let code_b = module.get_finalized_function(func_b);
84
85 // Cast it to a rust function pointer type.
86 let ptr_b = unsafe { mem::transmute::<_, extern "C" fn() -> u32>(code_b) };
87
88 // Call it!
89 let res = ptr_b();
90
91 assert_eq!(res, 42);
92 }
93