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