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