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