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