use indexmap::IndexMap;
#[derive(Clone, Default, Debug)]
pub struct Code {
offset: usize,
funcs: IndexMap<ExtFunc, usize>,
}
impl Code {
pub fn new() -> Self {
Self {
offset: 0,
funcs: Default::default(),
}
}
pub fn funcs(&self) -> Vec<ExtFunc> {
self.funcs.keys().cloned().collect()
}
pub fn shift(&mut self, offset: u16) {
tracing::trace!("shift code section by 0x{:x} bytes.", offset);
let offset = offset as usize;
self.offset += offset;
self.funcs.values_mut().for_each(|pc| *pc += offset);
}
pub fn try_add_func(&mut self, func: ExtFunc) {
if self.funcs.contains_key(&func) {
return;
}
let bytecode = func.bytecode.clone();
let len = bytecode.len();
self.funcs.insert(func, self.offset);
self.offset += len;
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn offset_of(&self, func: &ExtFunc) -> Option<u16> {
self.funcs.get(func).and_then(|i| (*i).try_into().ok())
}
pub fn finish(&self) -> Vec<u8> {
let mut code = Vec::new();
for func in self.funcs.keys() {
tracing::trace!("add function to code section: {:?}", func);
code.extend(func.bytecode.clone());
}
code
}
}
#[derive(PartialEq, Eq, Debug, Clone, Hash)]
pub struct ExtFunc {
pub stack_out: u8,
pub stack_in: u8,
pub bytecode: Vec<u8>,
}