1 use cranelift_codegen::ir::*;
2 use cranelift_codegen::isa::CallConv;
3 use cranelift_codegen::{binemit::NullTrapSink, 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     let mut trap_sink = NullTrapSink {};
54     module
55         .define_function(func_id, &mut ctx, &mut trap_sink)
56         .unwrap();
57 
58     func_id
59 }
60 
61 #[test]
62 #[should_panic(expected = "Result::unwrap()` on an `Err` value: DuplicateDefinition(\"abc\")")]
63 fn panic_on_define_after_finalize() {
64     let flag_builder = settings::builder();
65     let isa_builder = cranelift_codegen::isa::lookup_by_name("x86_64-unknown-linux-gnu").unwrap();
66     let isa = isa_builder.finish(settings::Flags::new(flag_builder));
67     let mut module =
68         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
69 
70     define_simple_function(&mut module);
71     define_simple_function(&mut module);
72 }
73 
74 #[test]
75 fn switch_error() {
76     use cranelift_codegen::settings;
77 
78     let sig = Signature {
79         params: vec![AbiParam::new(types::I32)],
80         returns: vec![AbiParam::new(types::I32)],
81         call_conv: CallConv::SystemV,
82     };
83 
84     let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
85 
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, 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.finish(settings::Flags::new(flag_builder));
152     let mut module =
153         ObjectModule::new(ObjectBuilder::new(isa, "foo", default_libcall_names()).unwrap());
154 
155     let sig = Signature {
156         params: vec![],
157         returns: vec![],
158         call_conv: CallConv::SystemV,
159     };
160 
161     let func_id = module
162         .declare_function("function", Linkage::Local, &sig)
163         .unwrap();
164 
165     let mut ctx = Context::new();
166     ctx.func = Function::with_name_signature(ExternalName::user(0, func_id.as_u32()), sig);
167     let mut func_ctx = FunctionBuilderContext::new();
168     {
169         let mut bcx: FunctionBuilder = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
170         let block = bcx.create_block();
171         bcx.switch_to_block(block);
172 
173         let int = module.target_config().pointer_type();
174         let zero = bcx.ins().iconst(I16, 0);
175         let size = bcx.ins().iconst(int, 10);
176 
177         let mut signature = module.make_signature();
178         signature.params.push(AbiParam::new(int));
179         signature.returns.push(AbiParam::new(int));
180         let callee = module
181             .declare_function("malloc", Linkage::Import, &signature)
182             .expect("declare malloc function");
183         let local_callee = module.declare_func_in_func(callee, &mut bcx.func);
184         let argument_exprs = vec![size];
185         let call = bcx.ins().call(local_callee, &argument_exprs);
186         let buffer = bcx.inst_results(call)[0];
187 
188         bcx.call_memset(module.target_config(), buffer, zero, size);
189 
190         bcx.ins().return_(&[]);
191     }
192 
193     let mut trap_sink = NullTrapSink {};
194     module
195         .define_function(func_id, &mut ctx, &mut trap_sink)
196         .unwrap();
197 
198     module.finish();
199 }
200