1 use cranelift_codegen::ir::*;
2 use cranelift_codegen::isa::CallConv;
3 use cranelift_codegen::settings;
4 use cranelift_codegen::{Context, ir::types::I16};
5 use cranelift_entity::EntityRef;
6 use cranelift_frontend::*;
7 use cranelift_module::*;
8 use cranelift_object::*;
9 
10 #[test]
error_on_incompatible_sig_in_declare_function()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
15         .finish(settings::Flags::new(flag_builder))
16         .unwrap();
17     let mut module =
18         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
19     let mut sig = Signature {
20         params: vec![AbiParam::new(types::I64)],
21         returns: vec![],
22         call_conv: CallConv::SystemV,
23     };
24     module
25         .declare_function("abc", Linkage::Local, &sig)
26         .unwrap();
27     sig.params[0] = AbiParam::new(types::I32);
28     module
29         .declare_function("abc", Linkage::Local, &sig)
30         .err()
31         .unwrap(); // Make sure this is an error
32 }
33 
define_simple_function(module: &mut ObjectModule) -> FuncId34 fn define_simple_function(module: &mut ObjectModule) -> FuncId {
35     let sig = Signature {
36         params: vec![],
37         returns: vec![],
38         call_conv: CallConv::SystemV,
39     };
40 
41     let func_id = module
42         .declare_function("abc", Linkage::Local, &sig)
43         .unwrap();
44 
45     let mut ctx = Context::new();
46     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
47     let mut func_ctx = FunctionBuilderContext::new();
48     {
49         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
50         let block = bcx.create_block();
51         bcx.switch_to_block(block);
52         bcx.ins().return_(&[]);
53     }
54 
55     module.define_function(func_id, &mut ctx).unwrap();
56 
57     func_id
58 }
59 
60 #[test]
61 #[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")]
panic_on_define_after_finalize()62 fn panic_on_define_after_finalize() {
63     let flag_builder = settings::builder();
64     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
65     let isa = isa_builder
66         .finish(settings::Flags::new(flag_builder))
67         .unwrap();
68     let mut module =
69         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
70 
71     define_simple_function(&mut module);
72     define_simple_function(&mut module);
73 }
74 
75 #[test]
76 #[cfg_attr(not(debug_assertions), ignore = "checks a debug assertion")]
77 #[should_panic(expected = "function \"abc\" with linkage Local must be defined but is not")]
panic_on_declare_without_define()78 fn panic_on_declare_without_define() {
79     let flag_builder = settings::builder();
80     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
81     let isa = isa_builder
82         .finish(settings::Flags::new(flag_builder))
83         .unwrap();
84     let mut module =
85         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
86 
87     module
88         .declare_function("abc", Linkage::Local, &Signature::new(CallConv::SystemV))
89         .unwrap();
90 
91     module.finish();
92 }
93 
94 #[test]
switch_error()95 fn switch_error() {
96     use cranelift_codegen::settings;
97 
98     let sig = Signature {
99         params: vec![AbiParam::new(types::I32)],
100         returns: vec![AbiParam::new(types::I32)],
101         call_conv: CallConv::SystemV,
102     };
103 
104     let mut func = Function::with_name_signature(UserFuncName::default(), sig);
105     let mut func_ctx = FunctionBuilderContext::new();
106     {
107         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut func, &mut func_ctx);
108         let start = bcx.create_block();
109         let bb0 = bcx.create_block();
110         let bb1 = bcx.create_block();
111         let bb2 = bcx.create_block();
112         let bb3 = bcx.create_block();
113         println!("{start} {bb0} {bb1} {bb2} {bb3}");
114 
115         bcx.declare_var(types::I32);
116         bcx.declare_var(types::I32);
117         let in_val = bcx.append_block_param(start, types::I32);
118         bcx.switch_to_block(start);
119         bcx.def_var(Variable::new(0), in_val);
120         bcx.ins().jump(bb0, &[]);
121 
122         bcx.switch_to_block(bb0);
123         let discr = bcx.use_var(Variable::new(0));
124         let mut switch = cranelift_frontend::Switch::new();
125         for &(index, bb) in &[
126             (9, bb1),
127             (13, bb1),
128             (10, bb1),
129             (92, bb1),
130             (39, bb1),
131             (34, bb1),
132         ] {
133             switch.set_entry(index, bb);
134         }
135         switch.emit(&mut bcx, discr, bb2);
136 
137         bcx.switch_to_block(bb1);
138         let v = bcx.use_var(Variable::new(0));
139         bcx.def_var(Variable::new(1), v);
140         bcx.ins().jump(bb3, &[]);
141 
142         bcx.switch_to_block(bb2);
143         let v = bcx.use_var(Variable::new(0));
144         bcx.def_var(Variable::new(1), v);
145         bcx.ins().jump(bb3, &[]);
146 
147         bcx.switch_to_block(bb3);
148         let r = bcx.use_var(Variable::new(1));
149         bcx.ins().return_(&[r]);
150 
151         bcx.seal_all_blocks();
152         bcx.finalize();
153     }
154 
155     let flags = settings::Flags::new(settings::builder());
156     match cranelift_codegen::verify_function(&func, &flags) {
157         Ok(_) => {}
158         Err(err) => {
159             let pretty_error =
160                 cranelift_codegen::print_errors::pretty_verifier_error(&func, None, err);
161             panic!("pretty_error:\n{pretty_error}");
162         }
163     }
164 }
165 
166 #[test]
libcall_function()167 fn libcall_function() {
168     let flag_builder = settings::builder();
169     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
170     let isa = isa_builder
171         .finish(settings::Flags::new(flag_builder))
172         .unwrap();
173     let mut module =
174         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
175 
176     let sig = Signature {
177         params: vec![],
178         returns: vec![],
179         call_conv: CallConv::SystemV,
180     };
181 
182     let func_id = module
183         .declare_function("function", Linkage::Local, &sig)
184         .unwrap();
185 
186     let mut ctx = Context::new();
187     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
188     let mut func_ctx = FunctionBuilderContext::new();
189     {
190         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
191         let block = bcx.create_block();
192         bcx.switch_to_block(block);
193 
194         let int = module.target_config().pointer_type();
195         let zero = bcx.ins().iconst(I16, 0);
196         let size = bcx.ins().iconst(int, 10);
197 
198         let mut signature = module.make_signature();
199         signature.params.push(AbiParam::new(int));
200         signature.returns.push(AbiParam::new(int));
201         let callee = module
202             .declare_function("malloc", Linkage::Import, &signature)
203             .expect("declare malloc function");
204         let local_callee = module.declare_func_in_func(callee, &mut bcx.func);
205         let argument_exprs = vec![size];
206         let call = bcx.ins().call(local_callee, &argument_exprs);
207         let buffer = bcx.inst_results(call)[0];
208 
209         bcx.call_memset(module.target_config(), buffer, zero, size);
210 
211         bcx.ins().return_(&[]);
212     }
213 
214     module.define_function(func_id, &mut ctx).unwrap();
215 
216     module.finish();
217 }
218 
219 #[test]
220 #[should_panic(expected = "has a null byte, which is disallowed")]
reject_nul_byte_symbol_for_func()221 fn reject_nul_byte_symbol_for_func() {
222     let flag_builder = settings::builder();
223     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
224     let isa = isa_builder
225         .finish(settings::Flags::new(flag_builder))
226         .unwrap();
227     let mut module =
228         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
229 
230     let sig = Signature {
231         params: vec![],
232         returns: vec![],
233         call_conv: CallConv::SystemV,
234     };
235 
236     let _ = module
237         .declare_function("function\u{0}with\u{0}nul\u{0}bytes", Linkage::Local, &sig)
238         .unwrap();
239 }
240 
241 #[test]
242 #[should_panic(expected = "has a null byte, which is disallowed")]
reject_nul_byte_symbol_for_data()243 fn reject_nul_byte_symbol_for_data() {
244     let flag_builder = settings::builder();
245     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
246     let isa = isa_builder
247         .finish(settings::Flags::new(flag_builder))
248         .unwrap();
249     let mut module =
250         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
251 
252     let _ = module
253         .declare_data(
254             "data\u{0}with\u{0}nul\u{0}bytes",
255             Linkage::Local,
256             /* writable = */ true,
257             /* tls = */ false,
258         )
259         .unwrap();
260 }
261 
262 #[test]
aarch64_colocated_data_symbol_reloc()263 fn aarch64_colocated_data_symbol_reloc() {
264     let flag_builder = settings::builder();
265     let isa_builder = cranelift_codegen::isa::lookup_by_name("aarch64-unknown-linux-gnu").unwrap();
266     let isa = isa_builder
267         .finish(settings::Flags::new(flag_builder))
268         .unwrap();
269     let mut module =
270         ObjectModule::new(ObjectBuilder::new(isa, "test", default_libcall_names()).unwrap());
271 
272     let data_id = module
273         .declare_data("my_data", Linkage::Local, true, false)
274         .unwrap();
275 
276     let mut data_desc = DataDescription::new();
277     data_desc.define_zeroinit(64);
278     module.define_data(data_id, &data_desc).unwrap();
279 
280     let sig = Signature {
281         params: vec![],
282         returns: vec![AbiParam::new(types::I64)],
283         call_conv: CallConv::SystemV,
284     };
285 
286     let func_id = module
287         .declare_function("load_data_addr", Linkage::Local, &sig)
288         .unwrap();
289 
290     let mut ctx = Context::new();
291     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
292     let mut func_ctx = FunctionBuilderContext::new();
293     {
294         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
295         let block = bcx.create_block();
296         bcx.switch_to_block(block);
297 
298         let gv = module.declare_data_in_func(data_id, &mut bcx.func);
299         let ptr = module.target_config().pointer_type();
300         let addr = bcx.ins().global_value(ptr, gv);
301         bcx.ins().return_(&[addr]);
302 
303         bcx.seal_all_blocks();
304         bcx.finalize();
305     }
306 
307     module.define_function(func_id, &mut ctx).unwrap();
308 
309     let product = module.finish();
310     product.emit().expect("emit object file");
311 }
312