15df5bbbdSbjorn3 use cranelift_codegen::ir::*;
25df5bbbdSbjorn3 use cranelift_codegen::isa::CallConv;
3b803514dSbjorn3 use cranelift_codegen::settings;
490ac295eSAlex Crichton use cranelift_codegen::{Context, ir::types::I16};
55df5bbbdSbjorn3 use cranelift_entity::EntityRef;
65df5bbbdSbjorn3 use cranelift_frontend::*;
75df5bbbdSbjorn3 use cranelift_module::*;
85df5bbbdSbjorn3 use cranelift_object::*;
95df5bbbdSbjorn3 
105df5bbbdSbjorn3 #[test]
error_on_incompatible_sig_in_declare_function()115df5bbbdSbjorn3 fn error_on_incompatible_sig_in_declare_function() {
125df5bbbdSbjorn3     let flag_builder = settings::builder();
135df5bbbdSbjorn3     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
141c014d12SChris Fallin     let isa = isa_builder
151c014d12SChris Fallin         .finish(settings::Flags::new(flag_builder))
161c014d12SChris Fallin         .unwrap();
175df5bbbdSbjorn3     let mut module =
185df5bbbdSbjorn3         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
195df5bbbdSbjorn3     let mut sig = Signature {
205df5bbbdSbjorn3         params: vec![AbiParam::new(types::I64)],
215df5bbbdSbjorn3         returns: vec![],
225df5bbbdSbjorn3         call_conv: CallConv::SystemV,
235df5bbbdSbjorn3     };
245df5bbbdSbjorn3     module
255df5bbbdSbjorn3         .declare_function("abc", Linkage::Local, &sig)
265df5bbbdSbjorn3         .unwrap();
275df5bbbdSbjorn3     sig.params[0] = AbiParam::new(types::I32);
285df5bbbdSbjorn3     module
295df5bbbdSbjorn3         .declare_function("abc", Linkage::Local, &sig)
305df5bbbdSbjorn3         .err()
315df5bbbdSbjorn3         .unwrap(); // Make sure this is an error
325df5bbbdSbjorn3 }
335df5bbbdSbjorn3 
define_simple_function(module: &mut ObjectModule) -> FuncId34e1812b61Sbjorn3 fn define_simple_function(module: &mut ObjectModule) -> FuncId {
355df5bbbdSbjorn3     let sig = Signature {
365df5bbbdSbjorn3         params: vec![],
375df5bbbdSbjorn3         returns: vec![],
385df5bbbdSbjorn3         call_conv: CallConv::SystemV,
395df5bbbdSbjorn3     };
405df5bbbdSbjorn3 
415df5bbbdSbjorn3     let func_id = module
425df5bbbdSbjorn3         .declare_function("abc", Linkage::Local, &sig)
435df5bbbdSbjorn3         .unwrap();
445df5bbbdSbjorn3 
455df5bbbdSbjorn3     let mut ctx = Context::new();
468a9b1a90SBenjamin Bouvier     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
475df5bbbdSbjorn3     let mut func_ctx = FunctionBuilderContext::new();
485df5bbbdSbjorn3     {
495df5bbbdSbjorn3         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
505df5bbbdSbjorn3         let block = bcx.create_block();
515df5bbbdSbjorn3         bcx.switch_to_block(block);
525df5bbbdSbjorn3         bcx.ins().return_(&[]);
535df5bbbdSbjorn3     }
545df5bbbdSbjorn3 
55e1812b61Sbjorn3     module.define_function(func_id, &mut ctx).unwrap();
565df5bbbdSbjorn3 
575df5bbbdSbjorn3     func_id
585df5bbbdSbjorn3 }
595df5bbbdSbjorn3 
605df5bbbdSbjorn3 #[test]
615df5bbbdSbjorn3 #[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")]
panic_on_define_after_finalize()625df5bbbdSbjorn3 fn panic_on_define_after_finalize() {
635df5bbbdSbjorn3     let flag_builder = settings::builder();
645df5bbbdSbjorn3     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
651c014d12SChris Fallin     let isa = isa_builder
661c014d12SChris Fallin         .finish(settings::Flags::new(flag_builder))
671c014d12SChris Fallin         .unwrap();
685df5bbbdSbjorn3     let mut module =
695df5bbbdSbjorn3         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
705df5bbbdSbjorn3 
71e1812b61Sbjorn3     define_simple_function(&mut module);
72e1812b61Sbjorn3     define_simple_function(&mut module);
735df5bbbdSbjorn3 }
745df5bbbdSbjorn3 
755df5bbbdSbjorn3 #[test]
76329aaf78Sbjorn3 #[cfg_attr(not(debug_assertions), ignore = "checks a debug assertion")]
77329aaf78Sbjorn3 #[should_panic(expected = "function \"abc\" with linkage Local must be defined but is not")]
panic_on_declare_without_define()78329aaf78Sbjorn3 fn panic_on_declare_without_define() {
79329aaf78Sbjorn3     let flag_builder = settings::builder();
80329aaf78Sbjorn3     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
81329aaf78Sbjorn3     let isa = isa_builder
82329aaf78Sbjorn3         .finish(settings::Flags::new(flag_builder))
83329aaf78Sbjorn3         .unwrap();
84329aaf78Sbjorn3     let mut module =
85329aaf78Sbjorn3         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
86329aaf78Sbjorn3 
87329aaf78Sbjorn3     module
88329aaf78Sbjorn3         .declare_function("abc", Linkage::Local, &Signature::new(CallConv::SystemV))
89329aaf78Sbjorn3         .unwrap();
90329aaf78Sbjorn3 
91329aaf78Sbjorn3     module.finish();
92329aaf78Sbjorn3 }
93329aaf78Sbjorn3 
94329aaf78Sbjorn3 #[test]
switch_error()955df5bbbdSbjorn3 fn switch_error() {
965df5bbbdSbjorn3     use cranelift_codegen::settings;
975df5bbbdSbjorn3 
985df5bbbdSbjorn3     let sig = Signature {
995df5bbbdSbjorn3         params: vec![AbiParam::new(types::I32)],
1005df5bbbdSbjorn3         returns: vec![AbiParam::new(types::I32)],
1015df5bbbdSbjorn3         call_conv: CallConv::SystemV,
1025df5bbbdSbjorn3     };
1035df5bbbdSbjorn3 
1048a9b1a90SBenjamin Bouvier     let mut func = Function::with_name_signature(UserFuncName::default(), sig);
1055df5bbbdSbjorn3     let mut func_ctx = FunctionBuilderContext::new();
1065df5bbbdSbjorn3     {
1075df5bbbdSbjorn3         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut func, &mut func_ctx);
1085df5bbbdSbjorn3         let start = bcx.create_block();
1095df5bbbdSbjorn3         let bb0 = bcx.create_block();
1105df5bbbdSbjorn3         let bb1 = bcx.create_block();
1115df5bbbdSbjorn3         let bb2 = bcx.create_block();
1125df5bbbdSbjorn3         let bb3 = bcx.create_block();
113a0442ea0SHamir Mahal         println!("{start} {bb0} {bb1} {bb2} {bb3}");
1145df5bbbdSbjorn3 
1158236a075SNick Fitzgerald         bcx.declare_var(types::I32);
1168236a075SNick Fitzgerald         bcx.declare_var(types::I32);
1175df5bbbdSbjorn3         let in_val = bcx.append_block_param(start, types::I32);
1185df5bbbdSbjorn3         bcx.switch_to_block(start);
1195df5bbbdSbjorn3         bcx.def_var(Variable::new(0), in_val);
1205df5bbbdSbjorn3         bcx.ins().jump(bb0, &[]);
1215df5bbbdSbjorn3 
1225df5bbbdSbjorn3         bcx.switch_to_block(bb0);
1235df5bbbdSbjorn3         let discr = bcx.use_var(Variable::new(0));
1245df5bbbdSbjorn3         let mut switch = cranelift_frontend::Switch::new();
1255df5bbbdSbjorn3         for &(index, bb) in &[
1265df5bbbdSbjorn3             (9, bb1),
1275df5bbbdSbjorn3             (13, bb1),
1285df5bbbdSbjorn3             (10, bb1),
1295df5bbbdSbjorn3             (92, bb1),
1305df5bbbdSbjorn3             (39, bb1),
1315df5bbbdSbjorn3             (34, bb1),
1325df5bbbdSbjorn3         ] {
1335df5bbbdSbjorn3             switch.set_entry(index, bb);
1345df5bbbdSbjorn3         }
1355df5bbbdSbjorn3         switch.emit(&mut bcx, discr, bb2);
1365df5bbbdSbjorn3 
1375df5bbbdSbjorn3         bcx.switch_to_block(bb1);
1385df5bbbdSbjorn3         let v = bcx.use_var(Variable::new(0));
1395df5bbbdSbjorn3         bcx.def_var(Variable::new(1), v);
1405df5bbbdSbjorn3         bcx.ins().jump(bb3, &[]);
1415df5bbbdSbjorn3 
1425df5bbbdSbjorn3         bcx.switch_to_block(bb2);
1435df5bbbdSbjorn3         let v = bcx.use_var(Variable::new(0));
1445df5bbbdSbjorn3         bcx.def_var(Variable::new(1), v);
1455df5bbbdSbjorn3         bcx.ins().jump(bb3, &[]);
1465df5bbbdSbjorn3 
1475df5bbbdSbjorn3         bcx.switch_to_block(bb3);
1485df5bbbdSbjorn3         let r = bcx.use_var(Variable::new(1));
1495df5bbbdSbjorn3         bcx.ins().return_(&[r]);
1505df5bbbdSbjorn3 
1515df5bbbdSbjorn3         bcx.seal_all_blocks();
1525df5bbbdSbjorn3         bcx.finalize();
1535df5bbbdSbjorn3     }
1545df5bbbdSbjorn3 
1555df5bbbdSbjorn3     let flags = settings::Flags::new(settings::builder());
1565df5bbbdSbjorn3     match cranelift_codegen::verify_function(&func, &flags) {
1575df5bbbdSbjorn3         Ok(_) => {}
1585df5bbbdSbjorn3         Err(err) => {
1595df5bbbdSbjorn3             let pretty_error =
16043a86f14SBenjamin Bouvier                 cranelift_codegen::print_errors::pretty_verifier_error(&func, None, err);
161a0442ea0SHamir Mahal             panic!("pretty_error:\n{pretty_error}");
1625df5bbbdSbjorn3         }
1635df5bbbdSbjorn3     }
1645df5bbbdSbjorn3 }
1655df5bbbdSbjorn3 
1665df5bbbdSbjorn3 #[test]
libcall_function()1675df5bbbdSbjorn3 fn libcall_function() {
1685df5bbbdSbjorn3     let flag_builder = settings::builder();
1695df5bbbdSbjorn3     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
1701c014d12SChris Fallin     let isa = isa_builder
1711c014d12SChris Fallin         .finish(settings::Flags::new(flag_builder))
1721c014d12SChris Fallin         .unwrap();
1735df5bbbdSbjorn3     let mut module =
1745df5bbbdSbjorn3         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
1755df5bbbdSbjorn3 
1765df5bbbdSbjorn3     let sig = Signature {
1775df5bbbdSbjorn3         params: vec![],
1785df5bbbdSbjorn3         returns: vec![],
1795df5bbbdSbjorn3         call_conv: CallConv::SystemV,
1805df5bbbdSbjorn3     };
1815df5bbbdSbjorn3 
1825df5bbbdSbjorn3     let func_id = module
1835df5bbbdSbjorn3         .declare_function("function", Linkage::Local, &sig)
1845df5bbbdSbjorn3         .unwrap();
1855df5bbbdSbjorn3 
1865df5bbbdSbjorn3     let mut ctx = Context::new();
1878a9b1a90SBenjamin Bouvier     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
1885df5bbbdSbjorn3     let mut func_ctx = FunctionBuilderContext::new();
1895df5bbbdSbjorn3     {
1905df5bbbdSbjorn3         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
1915df5bbbdSbjorn3         let block = bcx.create_block();
1925df5bbbdSbjorn3         bcx.switch_to_block(block);
1935df5bbbdSbjorn3 
1945df5bbbdSbjorn3         let int = module.target_config().pointer_type();
1955df5bbbdSbjorn3         let zero = bcx.ins().iconst(I16, 0);
1965df5bbbdSbjorn3         let size = bcx.ins().iconst(int, 10);
1975df5bbbdSbjorn3 
1985df5bbbdSbjorn3         let mut signature = module.make_signature();
1995df5bbbdSbjorn3         signature.params.push(AbiParam::new(int));
2005df5bbbdSbjorn3         signature.returns.push(AbiParam::new(int));
2015df5bbbdSbjorn3         let callee = module
2025df5bbbdSbjorn3             .declare_function("malloc", Linkage::Import, &signature)
2035df5bbbdSbjorn3             .expect("declare malloc function");
2045df5bbbdSbjorn3         let local_callee = module.declare_func_in_func(callee, &mut bcx.func);
2055df5bbbdSbjorn3         let argument_exprs = vec![size];
2065df5bbbdSbjorn3         let call = bcx.ins().call(local_callee, &argument_exprs);
2075df5bbbdSbjorn3         let buffer = bcx.inst_results(call)[0];
2085df5bbbdSbjorn3 
2095df5bbbdSbjorn3         bcx.call_memset(module.target_config(), buffer, zero, size);
2105df5bbbdSbjorn3 
2115df5bbbdSbjorn3         bcx.ins().return_(&[]);
2125df5bbbdSbjorn3     }
2135df5bbbdSbjorn3 
214e1812b61Sbjorn3     module.define_function(func_id, &mut ctx).unwrap();
2155df5bbbdSbjorn3 
2165df5bbbdSbjorn3     module.finish();
2175df5bbbdSbjorn3 }
21876fb9a08SChris Fallin 
21976fb9a08SChris Fallin #[test]
22044d1dee7SChris Fallin #[should_panic(expected = "has a null byte, which is disallowed")]
reject_nul_byte_symbol_for_func()22176fb9a08SChris Fallin fn reject_nul_byte_symbol_for_func() {
22276fb9a08SChris Fallin     let flag_builder = settings::builder();
22376fb9a08SChris Fallin     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
2241c014d12SChris Fallin     let isa = isa_builder
2251c014d12SChris Fallin         .finish(settings::Flags::new(flag_builder))
2261c014d12SChris Fallin         .unwrap();
22776fb9a08SChris Fallin     let mut module =
22876fb9a08SChris Fallin         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
22976fb9a08SChris Fallin 
23076fb9a08SChris Fallin     let sig = Signature {
23176fb9a08SChris Fallin         params: vec![],
23276fb9a08SChris Fallin         returns: vec![],
23376fb9a08SChris Fallin         call_conv: CallConv::SystemV,
23476fb9a08SChris Fallin     };
23576fb9a08SChris Fallin 
23676fb9a08SChris Fallin     let _ = module
23776fb9a08SChris Fallin         .declare_function("function\u{0}with\u{0}nul\u{0}bytes", Linkage::Local, &sig)
23876fb9a08SChris Fallin         .unwrap();
23976fb9a08SChris Fallin }
24076fb9a08SChris Fallin 
24176fb9a08SChris Fallin #[test]
24244d1dee7SChris Fallin #[should_panic(expected = "has a null byte, which is disallowed")]
reject_nul_byte_symbol_for_data()24376fb9a08SChris Fallin fn reject_nul_byte_symbol_for_data() {
24476fb9a08SChris Fallin     let flag_builder = settings::builder();
24576fb9a08SChris Fallin     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
2461c014d12SChris Fallin     let isa = isa_builder
2471c014d12SChris Fallin         .finish(settings::Flags::new(flag_builder))
2481c014d12SChris Fallin         .unwrap();
24976fb9a08SChris Fallin     let mut module =
25076fb9a08SChris Fallin         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
25176fb9a08SChris Fallin 
25276fb9a08SChris Fallin     let _ = module
25376fb9a08SChris Fallin         .declare_data(
25476fb9a08SChris Fallin             "data\u{0}with\u{0}nul\u{0}bytes",
25576fb9a08SChris Fallin             Linkage::Local,
25676fb9a08SChris Fallin             /* writable = */ true,
25776fb9a08SChris Fallin             /* tls = */ false,
25876fb9a08SChris Fallin         )
25976fb9a08SChris Fallin         .unwrap();
26076fb9a08SChris Fallin }
261*f6dfc89aSLiam Eckert 
262*f6dfc89aSLiam Eckert #[test]
aarch64_colocated_data_symbol_reloc()263*f6dfc89aSLiam Eckert fn aarch64_colocated_data_symbol_reloc() {
264*f6dfc89aSLiam Eckert     let flag_builder = settings::builder();
265*f6dfc89aSLiam Eckert     let isa_builder = cranelift_codegen::isa::lookup_by_name("aarch64-unknown-linux-gnu").unwrap();
266*f6dfc89aSLiam Eckert     let isa = isa_builder
267*f6dfc89aSLiam Eckert         .finish(settings::Flags::new(flag_builder))
268*f6dfc89aSLiam Eckert         .unwrap();
269*f6dfc89aSLiam Eckert     let mut module =
270*f6dfc89aSLiam Eckert         ObjectModule::new(ObjectBuilder::new(isa, "test", default_libcall_names()).unwrap());
271*f6dfc89aSLiam Eckert 
272*f6dfc89aSLiam Eckert     let data_id = module
273*f6dfc89aSLiam Eckert         .declare_data("my_data", Linkage::Local, true, false)
274*f6dfc89aSLiam Eckert         .unwrap();
275*f6dfc89aSLiam Eckert 
276*f6dfc89aSLiam Eckert     let mut data_desc = DataDescription::new();
277*f6dfc89aSLiam Eckert     data_desc.define_zeroinit(64);
278*f6dfc89aSLiam Eckert     module.define_data(data_id, &data_desc).unwrap();
279*f6dfc89aSLiam Eckert 
280*f6dfc89aSLiam Eckert     let sig = Signature {
281*f6dfc89aSLiam Eckert         params: vec![],
282*f6dfc89aSLiam Eckert         returns: vec![AbiParam::new(types::I64)],
283*f6dfc89aSLiam Eckert         call_conv: CallConv::SystemV,
284*f6dfc89aSLiam Eckert     };
285*f6dfc89aSLiam Eckert 
286*f6dfc89aSLiam Eckert     let func_id = module
287*f6dfc89aSLiam Eckert         .declare_function("load_data_addr", Linkage::Local, &sig)
288*f6dfc89aSLiam Eckert         .unwrap();
289*f6dfc89aSLiam Eckert 
290*f6dfc89aSLiam Eckert     let mut ctx = Context::new();
291*f6dfc89aSLiam Eckert     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
292*f6dfc89aSLiam Eckert     let mut func_ctx = FunctionBuilderContext::new();
293*f6dfc89aSLiam Eckert     {
294*f6dfc89aSLiam Eckert         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
295*f6dfc89aSLiam Eckert         let block = bcx.create_block();
296*f6dfc89aSLiam Eckert         bcx.switch_to_block(block);
297*f6dfc89aSLiam Eckert 
298*f6dfc89aSLiam Eckert         let gv = module.declare_data_in_func(data_id, &mut bcx.func);
299*f6dfc89aSLiam Eckert         let ptr = module.target_config().pointer_type();
300*f6dfc89aSLiam Eckert         let addr = bcx.ins().global_value(ptr, gv);
301*f6dfc89aSLiam Eckert         bcx.ins().return_(&[addr]);
302*f6dfc89aSLiam Eckert 
303*f6dfc89aSLiam Eckert         bcx.seal_all_blocks();
304*f6dfc89aSLiam Eckert         bcx.finalize();
305*f6dfc89aSLiam Eckert     }
306*f6dfc89aSLiam Eckert 
307*f6dfc89aSLiam Eckert     module.define_function(func_id, &mut ctx).unwrap();
308*f6dfc89aSLiam Eckert 
309*f6dfc89aSLiam Eckert     let product = module.finish();
310*f6dfc89aSLiam Eckert     product.emit().expect("emit object file");
311*f6dfc89aSLiam Eckert }
312