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