84 lines
1.9 KiB
Rust
84 lines
1.9 KiB
Rust
mod addr;
|
|
mod symbol;
|
|
pub use addr::*;
|
|
pub use symbol::*;
|
|
|
|
use crate::{arch::Arch, backend::LinkedProgram, io::CompilerMsg};
|
|
|
|
pub struct Program<A: Arch> {
|
|
pub ro_data: Vec<Data>,
|
|
pub funcs: Vec<Func<A>>,
|
|
pub entry: Option<Symbol>,
|
|
|
|
sym_count: usize,
|
|
}
|
|
|
|
pub struct Data {
|
|
pub bytes: Vec<u8>,
|
|
pub sym: Symbol,
|
|
}
|
|
|
|
pub struct Func<A: Arch> {
|
|
pub instrs: Vec<Instr<A>>,
|
|
pub sym: Symbol,
|
|
}
|
|
|
|
pub enum Instr<A: Arch> {
|
|
Set { dst: VarId, src: Vec<u8> },
|
|
Call { dst: FnId, args: Vec<VarId> },
|
|
Copy { dst: VarId, src: VarId },
|
|
Asm(A::Asm),
|
|
}
|
|
|
|
pub type VarId = usize;
|
|
pub type FnId = usize;
|
|
|
|
impl<A: Arch> Program<A> {
|
|
pub fn encode_data(&self, data: &mut Vec<u8>, sym_tab: &mut SymTable<A::Addr>) {
|
|
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<Vec<u8>>) -> 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<Vec<Instr<A>>>) -> 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<LinkedProgram<A::Addr>, CompilerMsg> {
|
|
A::compile(self)
|
|
}
|
|
|
|
pub fn sym_count(&self) -> usize {
|
|
self.sym_count
|
|
}
|
|
}
|
|
|
|
impl<A: Arch> Default for Program<A> {
|
|
fn default() -> Self {
|
|
Self {
|
|
ro_data: Default::default(),
|
|
funcs: Default::default(),
|
|
entry: Default::default(),
|
|
sym_count: Default::default(),
|
|
}
|
|
}
|
|
}
|