1use crate::ir::{Module, Function, FunctionValue};
4use crate::entities::{Symbol};
5use crate::instruction::{InstructionData, Opcode};
6use std::collections::HashMap;
7use vermilion_object::{Artifact};
8
9pub struct Binemit {
11
12 pub module: Module,
14
15 artifact: Artifact,
17
18 offset: usize,
20
21 symbols: HashMap<String, i64>,
23
24}
25
26impl Binemit {
27
28 pub fn new(module: Module) -> Self {
31 Binemit {
32 module,
33 artifact: Artifact::new(),
34 offset: 0,
35 symbols: HashMap::new()
36 }
37 }
38
39 fn opcode_byte(opcode: Opcode) -> u8 {
41 match opcode {
43 Opcode::Pop => 0x05,
44 Opcode::Clone => 0x06,
45 Opcode::Clear => 0x07,
46 Opcode::Trap => 0x0a,
47 Opcode::BooleanAdd => 0x0e,
48 Opcode::BooleanSubtract => 0x0f,
49 Opcode::ByteAdd => 0x10,
50 Opcode::ByteSubtract => 0x11,
51 Opcode::ByteMultiply => 0x12,
52 Opcode::ByteDivide => 0x13,
53 Opcode::ByteRemainder => 0x14,
54 Opcode::IntegerAdd => 0x15,
55 Opcode::IntegerSubtract => 0x16,
56 Opcode::IntegerMultiply => 0x17,
57 Opcode::IntegerDivide => 0x18,
58 Opcode::IntegerRemainder => 0x19,
59 Opcode::FloatAdd => 0x1a,
60 Opcode::FloatSubtract => 0x1b,
61 Opcode::FloatMultiply => 0x1c,
62 Opcode::FloatDivide => 0x1d,
63 Opcode::FloatRemainder => 0x1e,
64 Opcode::CastBoolean => 0x1f,
65 Opcode::CastByte => 0x20,
66 Opcode::CastInteger => 0x21,
67 Opcode::CastFloat => 0x22,
68 Opcode::NegateBoolean => 0x23,
69 Opcode::NegateByte => 0x0, Opcode::NegateInteger => 0x24,
71 Opcode::NegateFloat => 0x25,
72 Opcode::Load => 0x26,
73 Opcode::Store => 0x27,
74 Opcode::Realloc => 0x28,
75 Opcode::HeapSize => 0x29,
76 Opcode::Alloc => 0x2a,
77 Opcode::ReallocSection => 0x2b,
78 Opcode::SectionAddr => 0x2c,
79 Opcode::SectionShiftLeft => 0x2d,
80 Opcode::SectionShiftRight => 0x2e,
81 Opcode::Free => 0x2f,
82 Opcode::FreeAndShift => 0x30,
83 Opcode::Branch => 0x31,
84 Opcode::BranchIfZero => 0x32,
85 Opcode::BranchIfNotZero => 0x33,
86 Opcode::Equal => 0x34,
87 Opcode::GreaterThan => 0x35,
88 Opcode::LessThan => 0x36,
89 Opcode::GreaterThanOrEqual => 0x37,
90 Opcode::LessThanOrEqual => 0x38,
91 Opcode::Call => 0x39,
92 Opcode::Return => 0x3a
93 }
94 }
95
96 fn get_instruction_size(&self, func: &Function, inst: &InstructionData) -> i64 {
97 let mut size = 0;
98 for item in &inst.args {
99 size += self.get_size(func, func.values.get(item.0 as usize).unwrap());
100 }
101 size += 1;
102
103 size
104 }
105
106 pub fn get_size(&self, func: &Function, value: &FunctionValue) -> i64 {
108 let size: i64;
109
110 match value {
111 FunctionValue::Block(_) => {
112 size = 9;
113 },
114 FunctionValue::Boolean(_) => {
115 size = 2;
116 },
117 FunctionValue::Byte(_) => {
118 size = 2;
119 },
120 FunctionValue::Integer(_) => {
121 size = 9;
122 },
123 FunctionValue::Float(_) => {
124 size = 9;
125 },
126 FunctionValue::Symbol(_) => {
127 size = 9;
128 },
129 FunctionValue::Instruction(data) => {
130 size = self.get_instruction_size(func, data);
131 }
132 }
133
134 size
135 }
136
137 fn compile_instruction(&self, func: &Function, blocks: &Vec<usize>, inst: &InstructionData) -> Vec<u8> {
138 let mut val = Vec::new();
139
140 for arg in &inst.args {
141 val.append(&mut self.compile_value(func, blocks, &func.values[arg.0 as usize]));
142 }
143
144 val.push(Binemit::opcode_byte(inst.opcode.clone()));
145
146 val
147 }
148
149 fn compile_value(&self, func: &Function, blocks: &Vec<usize>, value: &FunctionValue) -> Vec<u8> {
151 let mut val = Vec::new();
152 match value {
153 FunctionValue::Block(bl) => {
154 val.push(3);
157
158 let mut addr = (bl.0 as i64).to_le_bytes().to_vec();
159 val.append(&mut addr);
160 },
161 FunctionValue::Boolean(r) => {
162 val.push(1);
163 if *r {
164 val.push(1);
165 } else {
166 val.push(0);
167 }
168 },
170 FunctionValue::Byte(r) => {
171 val.push(2);
172 val.push(*r);
173 },
174 FunctionValue::Integer(r) => {
175 val.push(3);
176
177 let mut addr = r.to_le_bytes().to_vec();
178 val.append(&mut addr);
179 },
180 FunctionValue::Float(r) => {
181 val.push(4);
182
183 let mut addr = r.to_le_bytes().to_vec();
184 val.append(&mut addr);
185 },
186 FunctionValue::Symbol(r) => {
187 val.push(3);
188
189 let mut addr = self.symbols.get(r).unwrap().to_le_bytes().to_vec();
190 val.append(&mut addr);
191 },
192 FunctionValue::Instruction(data) => {
193 val = self.compile_instruction(func, blocks, &data);
194 }
195 }
196 val
197 }
198
199 fn calc_addresses(&self, func: &Function) -> Vec<usize> {
201 let mut blocks = Vec::new();
202 let mut end = self.offset;
203
204 for block in &func.blocks {
205 let insts = &block.instructions;
206 let mut size = 0;
207
208 for inst in insts {
209 size += self.get_instruction_size(&func, &inst);
210 }
211
212 blocks.push(end);
213 end += size as usize;
214 }
215
216 blocks
217 }
218
219 fn compile_function(&self, func: &Function) -> Vec<u8> {
221 let mut bytes = Vec::new();
222
223 let blocks = self.calc_addresses(&func);
224
225 for block in &func.blocks {
226 for inst in &block.instructions {
227 bytes.append(&mut self.compile_instruction(func, &blocks, &inst))
228 }
229 }
230
231 bytes
232 }
233
234 pub fn emit(&mut self) -> Artifact {
236 let mut artifact = self.artifact.clone();
237 let mut bytes = Vec::new();
238
239 let mut id = 0;
241 for symbol in &self.module.symbols {
242 self.symbols.insert(symbol.0.to_string(), id);
243 id += 1;
244 }
245
246 for symbol in &self.module.symbols {
247 match symbol.1 {
248 Symbol::Local(func) => {
249 artifact.symbols.insert(self.symbols[&symbol.0.clone()], vermilion_object::Symbol::Local(symbol.0.to_string(), self.offset));
250 bytes.append(&mut self.compile_function(&func));
251 },
252 Symbol::External => {
253 artifact.declare_function(self.symbols[&symbol.0.clone()], symbol.0.to_string());
254 }
255 }
256 }
257
258 artifact.program = bytes;
259
260 artifact
261 }
262
263}