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