1 use cranelift_codegen::ir::*;
2 use cranelift_codegen::isa::{CallConv, OwnedTargetIsa};
3 use cranelift_codegen::settings::{self, Configurable};
4 use cranelift_codegen::{Context, ir::types::I16};
5 use cranelift_entity::EntityRef;
6 use cranelift_frontend::*;
7 use cranelift_jit::*;
8 use cranelift_module::*;
9
isa() -> Option<OwnedTargetIsa>10 fn isa() -> Option<OwnedTargetIsa> {
11 let mut flag_builder = settings::builder();
12 flag_builder.set("use_colocated_libcalls", "false").unwrap();
13 // FIXME set back to true once the x64 backend supports it.
14 flag_builder.set("is_pic", "false").unwrap();
15 let isa_builder = cranelift_native::builder().ok()?;
16 isa_builder.finish(settings::Flags::new(flag_builder)).ok()
17 }
18
19 #[test]
error_on_incompatible_sig_in_declare_function()20 fn error_on_incompatible_sig_in_declare_function() {
21 let Some(isa) = isa() else {
22 return;
23 };
24 let mut module = JITModule::new(JITBuilder::with_isa(isa, default_libcall_names()));
25
26 let mut sig = Signature {
27 params: vec![AbiParam::new(types::I64)],
28 returns: vec![],
29 call_conv: CallConv::SystemV,
30 };
31 module
32 .declare_function("abc", Linkage::Local, &sig)
33 .unwrap();
34 sig.params[0] = AbiParam::new(types::I32);
35 module
36 .declare_function("abc", Linkage::Local, &sig)
37 .err()
38 .unwrap(); // Make sure this is an error
39 }
40
define_simple_function(module: &mut JITModule) -> Result<FuncId, ModuleError>41 fn define_simple_function(module: &mut JITModule) -> Result<FuncId, ModuleError> {
42 let sig = Signature {
43 params: vec![],
44 returns: vec![],
45 call_conv: CallConv::SystemV,
46 };
47
48 let func_id = module.declare_function("abc", Linkage::Local, &sig)?;
49
50 let mut ctx = Context::new();
51 ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
52 let mut func_ctx = FunctionBuilderContext::new();
53 {
54 let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
55 let block = bcx.create_block();
56 bcx.switch_to_block(block);
57 bcx.ins().return_(&[]);
58 }
59
60 module.define_function(func_id, &mut ctx)?;
61
62 Ok(func_id)
63 }
64
65 #[test]
panic_on_define_after_finalize()66 fn panic_on_define_after_finalize() {
67 let Some(isa) = isa() else {
68 return;
69 };
70 let mut module = JITModule::new(JITBuilder::with_isa(isa, default_libcall_names()));
71
72 define_simple_function(&mut module).unwrap();
73 define_simple_function(&mut module).err().unwrap();
74 }
75
76 #[test]
switch_error()77 fn switch_error() {
78 use cranelift_codegen::settings;
79
80 let sig = Signature {
81 params: vec![AbiParam::new(types::I32)],
82 returns: vec![AbiParam::new(types::I32)],
83 call_conv: CallConv::SystemV,
84 };
85
86 let mut func = Function::with_name_signature(UserFuncName::default(), sig);
87
88 let mut func_ctx = FunctionBuilderContext::new();
89 {
90 let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut func, &mut func_ctx);
91 let start = bcx.create_block();
92 let bb0 = bcx.create_block();
93 let bb1 = bcx.create_block();
94 let bb2 = bcx.create_block();
95 let bb3 = bcx.create_block();
96 println!("{start} {bb0} {bb1} {bb2} {bb3}");
97
98 bcx.declare_var(types::I32);
99 bcx.declare_var(types::I32);
100 let in_val = bcx.append_block_param(start, types::I32);
101 bcx.switch_to_block(start);
102 bcx.def_var(Variable::new(0), in_val);
103 bcx.ins().jump(bb0, &[]);
104
105 bcx.switch_to_block(bb0);
106 let discr = bcx.use_var(Variable::new(0));
107 let mut switch = cranelift_frontend::Switch::new();
108 for &(index, bb) in &[
109 (9, bb1),
110 (13, bb1),
111 (10, bb1),
112 (92, bb1),
113 (39, bb1),
114 (34, bb1),
115 ] {
116 switch.set_entry(index, bb);
117 }
118 switch.emit(&mut bcx, discr, bb2);
119
120 bcx.switch_to_block(bb1);
121 let v = bcx.use_var(Variable::new(0));
122 bcx.def_var(Variable::new(1), v);
123 bcx.ins().jump(bb3, &[]);
124
125 bcx.switch_to_block(bb2);
126 let v = bcx.use_var(Variable::new(0));
127 bcx.def_var(Variable::new(1), v);
128 bcx.ins().jump(bb3, &[]);
129
130 bcx.switch_to_block(bb3);
131 let r = bcx.use_var(Variable::new(1));
132 bcx.ins().return_(&[r]);
133
134 bcx.seal_all_blocks();
135 bcx.finalize();
136 }
137
138 let flags = settings::Flags::new(settings::builder());
139 match cranelift_codegen::verify_function(&func, &flags) {
140 Ok(_) => {}
141 Err(err) => {
142 let pretty_error =
143 cranelift_codegen::print_errors::pretty_verifier_error(&func, None, err);
144 panic!("pretty_error:\n{pretty_error}");
145 }
146 }
147 }
148
149 #[test]
libcall_function()150 fn libcall_function() {
151 let Some(isa) = isa() else {
152 return;
153 };
154 let mut module = JITModule::new(JITBuilder::with_isa(isa, default_libcall_names()));
155
156 let sig = Signature {
157 params: vec![],
158 returns: vec![],
159 call_conv: CallConv::SystemV,
160 };
161
162 let func_id = module
163 .declare_function("function", Linkage::Local, &sig)
164 .unwrap();
165
166 let mut ctx = Context::new();
167 ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
168
169 let mut func_ctx = FunctionBuilderContext::new();
170 {
171 let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
172 let block = bcx.create_block();
173 bcx.switch_to_block(block);
174
175 let int = module.target_config().pointer_type();
176 let zero = bcx.ins().iconst(I16, 0);
177 let size = bcx.ins().iconst(int, 10);
178
179 let mut signature = module.make_signature();
180 signature.params.push(AbiParam::new(int));
181 signature.returns.push(AbiParam::new(int));
182 let callee = module
183 .declare_function("malloc", Linkage::Import, &signature)
184 .expect("declare malloc function");
185 let local_callee = module.declare_func_in_func(callee, &mut bcx.func);
186 let argument_exprs = vec![size];
187 let call = bcx.ins().call(local_callee, &argument_exprs);
188 let buffer = bcx.inst_results(call)[0];
189
190 bcx.call_memset(module.target_config(), buffer, zero, size);
191
192 bcx.ins().return_(&[]);
193 }
194
195 module
196 .define_function_with_control_plane(func_id, &mut ctx, &mut Default::default())
197 .unwrap();
198
199 module.finalize_definitions().unwrap();
200 }
201
202 // This used to cause UB. See https://github.com/bytecodealliance/wasmtime/issues/7918.
203 #[test]
empty_data_object()204 fn empty_data_object() {
205 let Some(isa) = isa() else {
206 return;
207 };
208 let mut module = JITModule::new(JITBuilder::with_isa(isa, default_libcall_names()));
209
210 let data_id = module
211 .declare_data("empty", Linkage::Export, false, false)
212 .unwrap();
213
214 let mut data = DataDescription::new();
215 data.define(Box::new([]));
216 module.define_data(data_id, &data).unwrap();
217 }
218