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]
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 
34 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\")")]
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 fn switch_error() {
77     use cranelift_codegen::settings;
78 
79     let sig = Signature {
80         params: vec![AbiParam::new(types::I32)],
81         returns: vec![AbiParam::new(types::I32)],
82         call_conv: CallConv::SystemV,
83     };
84 
85     let mut func = Function::with_name_signature(UserFuncName::default(), sig);
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, 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
152         .finish(settings::Flags::new(flag_builder))
153         .unwrap();
154     let mut module =
155         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
156 
157     let sig = Signature {
158         params: vec![],
159         returns: vec![],
160         call_conv: CallConv::SystemV,
161     };
162 
163     let func_id = module
164         .declare_function("function", Linkage::Local, &sig)
165         .unwrap();
166 
167     let mut ctx = Context::new();
168     ctx.func = Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), sig);
169     let mut func_ctx = FunctionBuilderContext::new();
170     {
171         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
172         let block = bcx.create_block();
173         bcx.switch_to_block(block);
174 
175         let int = module.target_config().pointer_type();
176         let zero = bcx.ins().iconst(I16, 0);
177         let size = bcx.ins().iconst(int, 10);
178 
179         let mut signature = module.make_signature();
180         signature.params.push(AbiParam::new(int));
181         signature.returns.push(AbiParam::new(int));
182         let callee = module
183             .declare_function("malloc", Linkage::Import, &signature)
184             .expect("declare malloc function");
185         let local_callee = module.declare_func_in_func(callee, &mut bcx.func);
186         let argument_exprs = vec![size];
187         let call = bcx.ins().call(local_callee, &argument_exprs);
188         let buffer = bcx.inst_results(call)[0];
189 
190         bcx.call_memset(module.target_config(), buffer, zero, size);
191 
192         bcx.ins().return_(&[]);
193     }
194 
195     module.define_function(func_id, &mut ctx).unwrap();
196 
197     module.finish();
198 }
199 
200 #[test]
201 #[should_panic(expected = "has a null byte, which is disallowed")]
202 fn reject_nul_byte_symbol_for_func() {
203     let flag_builder = settings::builder();
204     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
205     let isa = isa_builder
206         .finish(settings::Flags::new(flag_builder))
207         .unwrap();
208     let mut module =
209         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
210 
211     let sig = Signature {
212         params: vec![],
213         returns: vec![],
214         call_conv: CallConv::SystemV,
215     };
216 
217     let _ = module
218         .declare_function("function\u{0}with\u{0}nul\u{0}bytes", Linkage::Local, &sig)
219         .unwrap();
220 }
221 
222 #[test]
223 #[should_panic(expected = "has a null byte, which is disallowed")]
224 fn reject_nul_byte_symbol_for_data() {
225     let flag_builder = settings::builder();
226     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
227     let isa = isa_builder
228         .finish(settings::Flags::new(flag_builder))
229         .unwrap();
230     let mut module =
231         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
232 
233     let _ = module
234         .declare_data(
235             "data\u{0}with\u{0}nul\u{0}bytes",
236             Linkage::Local,
237             /* writable = */ true,
238             /* tls = */ false,
239         )
240         .unwrap();
241 }
242