1 use cranelift_codegen::ir::*;
2 use cranelift_codegen::isa::CallConv;
3 use cranelift_codegen::{
4     binemit::{NullStackMapSink, NullTrapSink},
5     settings,
6 };
7 use cranelift_codegen::{ir::types::I16, Context};
8 use cranelift_entity::EntityRef;
9 use cranelift_frontend::*;
10 use cranelift_module::*;
11 use cranelift_object::*;
12 
13 #[test]
14 fn error_on_incompatible_sig_in_declare_function() {
15     let flag_builder = settings::builder();
16     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
17     let isa = isa_builder.finish(settings::Flags::new(flag_builder));
18     let mut module =
19         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
20     let mut sig = Signature {
21         params: vec![AbiParam::new(types::I64)],
22         returns: vec![],
23         call_conv: CallConv::SystemV,
24     };
25     module
26         .declare_function("abc", Linkage::Local, &sig)
27         .unwrap();
28     sig.params[0] = AbiParam::new(types::I32);
29     module
30         .declare_function("abc", Linkage::Local, &sig)
31         .err()
32         .unwrap(); // Make sure this is an error
33 }
34 
35 fn define_simple_function(module: &mut ObjectModule) -> FuncId {
36     let sig = Signature {
37         params: vec![],
38         returns: vec![],
39         call_conv: CallConv::SystemV,
40     };
41 
42     let func_id = module
43         .declare_function("abc", Linkage::Local, &sig)
44         .unwrap();
45 
46     let mut ctx = Context::new();
47     ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig);
48     let mut func_ctx = FunctionBuilderContext::new();
49     {
50         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
51         let block = bcx.create_block();
52         bcx.switch_to_block(block);
53         bcx.ins().return_(&[]);
54     }
55 
56     let mut trap_sink = NullTrapSink {};
57     let mut stack_map_sink = NullStackMapSink {};
58     module
59         .define_function(func_id, &mut ctx, &mut trap_sink, &mut stack_map_sink)
60         .unwrap();
61 
62     func_id
63 }
64 
65 #[test]
66 #[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")]
67 fn panic_on_define_after_finalize() {
68     let flag_builder = settings::builder();
69     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
70     let isa = isa_builder.finish(settings::Flags::new(flag_builder));
71     let mut module =
72         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
73 
74     define_simple_function(&mut module);
75     define_simple_function(&mut module);
76 }
77 
78 #[test]
79 fn switch_error() {
80     use cranelift_codegen::settings;
81 
82     let sig = Signature {
83         params: vec![AbiParam::new(types::I32)],
84         returns: vec![AbiParam::new(types::I32)],
85         call_conv: CallConv::SystemV,
86     };
87 
88     let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
89 
90     let mut func_ctx = FunctionBuilderContext::new();
91     {
92         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut func, &mut func_ctx);
93         let start = bcx.create_block();
94         let bb0 = bcx.create_block();
95         let bb1 = bcx.create_block();
96         let bb2 = bcx.create_block();
97         let bb3 = bcx.create_block();
98         println!("{} {} {} {} {}", start, bb0, bb1, bb2, bb3);
99 
100         bcx.declare_var(Variable::new(0), types::I32);
101         bcx.declare_var(Variable::new(1), types::I32);
102         let in_val = bcx.append_block_param(start, types::I32);
103         bcx.switch_to_block(start);
104         bcx.def_var(Variable::new(0), in_val);
105         bcx.ins().jump(bb0, &[]);
106 
107         bcx.switch_to_block(bb0);
108         let discr = bcx.use_var(Variable::new(0));
109         let mut switch = cranelift_frontend::Switch::new();
110         for &(index, bb) in &[
111             (9, bb1),
112             (13, bb1),
113             (10, bb1),
114             (92, bb1),
115             (39, bb1),
116             (34, bb1),
117         ] {
118             switch.set_entry(index, bb);
119         }
120         switch.emit(&mut bcx, discr, bb2);
121 
122         bcx.switch_to_block(bb1);
123         let v = bcx.use_var(Variable::new(0));
124         bcx.def_var(Variable::new(1), v);
125         bcx.ins().jump(bb3, &[]);
126 
127         bcx.switch_to_block(bb2);
128         let v = bcx.use_var(Variable::new(0));
129         bcx.def_var(Variable::new(1), v);
130         bcx.ins().jump(bb3, &[]);
131 
132         bcx.switch_to_block(bb3);
133         let r = bcx.use_var(Variable::new(1));
134         bcx.ins().return_(&[r]);
135 
136         bcx.seal_all_blocks();
137         bcx.finalize();
138     }
139 
140     let flags = settings::Flags::new(settings::builder());
141     match cranelift_codegen::verify_function(&func, &flags) {
142         Ok(_) => {}
143         Err(err) => {
144             let pretty_error =
145                 cranelift_codegen::print_errors::pretty_verifier_error(&func, None, None, err);
146             panic!("pretty_error:\n{}", pretty_error);
147         }
148     }
149 }
150 
151 #[test]
152 fn libcall_function() {
153     let flag_builder = settings::builder();
154     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
155     let isa = isa_builder.finish(settings::Flags::new(flag_builder));
156     let mut module =
157         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
158 
159     let sig = Signature {
160         params: vec![],
161         returns: vec![],
162         call_conv: CallConv::SystemV,
163     };
164 
165     let func_id = module
166         .declare_function("function", Linkage::Local, &sig)
167         .unwrap();
168 
169     let mut ctx = Context::new();
170     ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig);
171     let mut func_ctx = FunctionBuilderContext::new();
172     {
173         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
174         let block = bcx.create_block();
175         bcx.switch_to_block(block);
176 
177         let int = module.target_config().pointer_type();
178         let zero = bcx.ins().iconst(I16, 0);
179         let size = bcx.ins().iconst(int, 10);
180 
181         let mut signature = module.make_signature();
182         signature.params.push(AbiParam::new(int));
183         signature.returns.push(AbiParam::new(int));
184         let callee = module
185             .declare_function("malloc", Linkage::Import, &signature)
186             .expect("declare malloc function");
187         let local_callee = module.declare_func_in_func(callee, &mut bcx.func);
188         let argument_exprs = vec![size];
189         let call = bcx.ins().call(local_callee, &argument_exprs);
190         let buffer = bcx.inst_results(call)[0];
191 
192         bcx.call_memset(module.target_config(), buffer, zero, size);
193 
194         bcx.ins().return_(&[]);
195     }
196 
197     let mut trap_sink = NullTrapSink {};
198     let mut stack_map_sink = NullStackMapSink {};
199     module
200         .define_function(func_id, &mut ctx, &mut trap_sink, &mut stack_map_sink)
201         .unwrap();
202 
203     module.finish();
204 }
205 
206 #[test]
207 #[should_panic(
208     expected = "Result::unwrap()` on an `Err` value: Backend(Symbol \"function\\u{0}with\\u{0}nul\\u{0}bytes\" has a null byte, which is disallowed"
209 )]
210 fn reject_nul_byte_symbol_for_func() {
211     let flag_builder = settings::builder();
212     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
213     let isa = isa_builder.finish(settings::Flags::new(flag_builder));
214     let mut module =
215         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
216 
217     let sig = Signature {
218         params: vec![],
219         returns: vec![],
220         call_conv: CallConv::SystemV,
221     };
222 
223     let _ = module
224         .declare_function("function\u{0}with\u{0}nul\u{0}bytes", Linkage::Local, &sig)
225         .unwrap();
226 }
227 
228 #[test]
229 #[should_panic(
230     expected = "Result::unwrap()` on an `Err` value: Backend(Symbol \"data\\u{0}with\\u{0}nul\\u{0}bytes\" has a null byte, which is disallowed"
231 )]
232 fn reject_nul_byte_symbol_for_data() {
233     let flag_builder = settings::builder();
234     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
235     let isa = isa_builder.finish(settings::Flags::new(flag_builder));
236     let mut module =
237         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
238 
239     let _ = module
240         .declare_data(
241             "data\u{0}with\u{0}nul\u{0}bytes",
242             Linkage::Local,
243             /* writable = */ true,
244             /* tls = */ false,
245         )
246         .unwrap();
247 }
248