1use cranelift::prelude::*;
4use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
5use cranelift_codegen::settings::{self, Configurable};
6use cranelift_module::{default_libcall_names, Linkage, Module};
7use cranelift_object::{ObjectBuilder, ObjectModule};
8use flycatcherc::{FlycatcherFrontend, FlycatcherType, VariableType};
9use std::io::prelude::*;
10use std::path::Path;
11pub use target_lexicon::{self, Triple};
12
13pub struct CraneliftBackend {
15
16 pub target: Triple,
18
19 pub out_file: String,
21
22 variables: Vec<String>,
24
25}
26
27impl CraneliftBackend {
28
29 pub fn new(target: Triple, out_file: String) -> Self {
31 Self {
32 target,
33 out_file,
34 variables: vec![]
35 }
36 }
37
38 fn convert_fctype(&self, t: FlycatcherType) -> Type {
40 match t {
41 FlycatcherType::Boolean => types::B1,
42 FlycatcherType::Size => types::I64,
43 FlycatcherType::Float64 => types::F64,
44 _ => panic!("This type is unsupported by the Cranelift backend.")
45 }
46 }
47
48 pub fn compile(&mut
50 self, frontend: FlycatcherFrontend) -> bool {
51 let mut flag_builder = settings::builder();
53 flag_builder.set("use_colocated_libcalls", "false").unwrap();
54 flag_builder.set("is_pic", "false").unwrap();
55
56 let isa = cranelift_codegen::isa::lookup(self.target.clone())
57 .unwrap()
58 .finish(settings::Flags::new(flag_builder));
59
60 let mut module = ObjectModule::new(ObjectBuilder::new(
61 isa,
62 [1, 2, 3, 4, 5, 6, 7, 8],
63 default_libcall_names()
64 ).unwrap());
65
66 let mut ctx = module.make_context();
67 let mut func_ctx = FunctionBuilderContext::new();
68
69 let sig_main = module.make_signature();
70 let func_main = module
71 .declare_function("WinMain", Linkage::Export, &sig_main)
72 .unwrap();
73
74 ctx.func.signature = sig_main;
75 ctx.func.name = ExternalName::user(0, func_main.as_u32());
76
77 {
78 let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);
79
80 for item in frontend.symbols {
82 let v = Variable::new(self.variables.len());
83
84 let fctype = match item.1 {
85 VariableType::Declared(t) => t,
86 VariableType::Defined(t, ..) => t
87 };
88
89 bcx.declare_var(v, self.convert_fctype(fctype));
90 self.variables.push(item.0);
91 }
92
93 let block0 = bcx.create_block();
94 bcx.switch_to_block(block0);
95
96 bcx.ins().return_(&[]);
97 bcx.seal_all_blocks();
98 }
99
100 let mut trap_sink = NullTrapSink {};
101 let mut stack_map_sink = NullStackMapSink {};
102
103 module
104 .define_function(func_main, &mut ctx, &mut trap_sink, &mut stack_map_sink)
105 .unwrap();
106
107 module.clear_context(&mut ctx);
108
109 let o = module.finish();
110 let res = o.emit().unwrap();
111
112 let mut f = std::fs::File::create(self.out_file.clone()).unwrap();
114 f.write_all(&res).unwrap();
115
116 true
117 }
118
119}