mod addr; mod symbol; pub use addr::*; pub use symbol::*; use crate::{arch::Arch, backend::LinkedProgram, io::CompilerMsg}; pub struct Program { pub ro_data: Vec, pub funcs: Vec>, pub entry: Option, sym_count: usize, } pub struct Data { pub bytes: Vec, pub sym: Symbol, } pub struct Func { pub instrs: Vec>, pub sym: Symbol, } pub enum Instr { Set { dst: VarId, src: Vec }, Call { dst: FnId, args: Vec }, Copy { dst: VarId, src: VarId }, Asm(A::Asm), } pub type VarId = usize; pub type FnId = usize; impl Program { pub fn encode_data(&self, data: &mut Vec, sym_tab: &mut SymTable) { for d in &self.ro_data { let addr = A::Addr::from_len(data.len()); data.extend(&d.bytes); sym_tab.insert(d.sym, addr); } } pub fn ro_data(&mut self, bytes: impl Into>) -> Symbol { let bytes = bytes.into(); let sym = self.reserve(); self.ro_data.push(Data { bytes, sym }); sym } pub fn func(&mut self, instrs: impl Into>>) -> Symbol { let instrs = instrs.into(); let sym = self.reserve(); self.funcs.push(Func { instrs, sym }); sym } fn reserve(&mut self) -> Symbol { let res = Symbol(self.sym_count); self.sym_count += 1; res } pub fn compile(&self) -> Result, CompilerMsg> { A::compile(self) } pub fn sym_count(&self) -> usize { self.sym_count } } impl Default for Program { fn default() -> Self { Self { ro_data: Default::default(), funcs: Default::default(), entry: Default::default(), sym_count: Default::default(), } } }