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