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