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