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