From bf6b0dfba91ff0c36bdb5280d7ecb9e1686ee314 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Mon, 17 Feb 2020 16:17:55 -0500 Subject: [PATCH] Remove vm::obj::assemble mod Signed-off-by: Alek Ratzloff --- src/vm/obj/assemble/error.rs | 16 -- src/vm/obj/assemble/flatten.rs | 0 src/vm/obj/assemble/mod.rs | 358 --------------------------------- 3 files changed, 374 deletions(-) delete mode 100644 src/vm/obj/assemble/error.rs delete mode 100644 src/vm/obj/assemble/flatten.rs delete mode 100644 src/vm/obj/assemble/mod.rs diff --git a/src/vm/obj/assemble/error.rs b/src/vm/obj/assemble/error.rs deleted file mode 100644 index 605b9b1..0000000 --- a/src/vm/obj/assemble/error.rs +++ /dev/null @@ -1,16 +0,0 @@ -use snafu::Snafu; -use std::{fmt::Debug, io}; - -#[derive(Debug, Snafu)] -pub enum AssembleError { - #[snafu(display("IO error: {}", source))] - Io { source: io::Error }, - - #[snafu(display("duplicate symbol name: {}", name))] - DuplicateSymbol { name: String }, - - #[snafu(display("duplicate exported symbol name: {}", name))] - DuplicateExportSymbol { name: String }, -} - -pub type Result = std::result::Result; diff --git a/src/vm/obj/assemble/flatten.rs b/src/vm/obj/assemble/flatten.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/vm/obj/assemble/mod.rs b/src/vm/obj/assemble/mod.rs deleted file mode 100644 index a03abba..0000000 --- a/src/vm/obj/assemble/mod.rs +++ /dev/null @@ -1,358 +0,0 @@ -pub mod error; - -use crate::vm::{ - inst::*, - obj::{assemble::error::*, obj::*, syn::ast::*}, - reg::Reg, -}; -use byteorder::{WriteBytesExt, LE}; -use std::{ - collections::{HashMap, HashSet}, - convert::TryFrom, - io::Cursor, - mem, -}; - -pub const LAYOUT_VERSION: u32 = 0; - -impl TryFrom<&'_ Vec> for Object { - type Error = AssembleError; - - fn try_from(other: &Vec) -> Result { - // Assemble an AST to an object - Assemble::new(&other).assemble() - } -} - -pub struct Assemble<'a> { - ast: &'a Vec, - symbols: SymbolTable, -} - -impl<'a> Assemble<'a> { - pub fn new(ast: &'a Vec) -> Self { - Assemble { - ast, - symbols: Default::default(), - } - } - - pub fn assemble(&mut self) -> Result { - let mut sections = Vec::new(); - - // gather global symbols - for block in self.ast.iter() { - let exports = Self::gather_symbols(block, true)?; - // check if there are any duplicated exports - { - let export_keys = exports.keys().collect::>(); - let global_keys = self.symbols.globals().keys().collect::>(); - if let Some(key) = export_keys.intersection(&global_keys).next() { - return Err(AssembleError::DuplicateExportSymbol { - name: key.to_string(), - }); - } - } - self.symbols.globals_mut().extend(exports); - } - - for block in self.ast.iter() { - let locals = Self::gather_symbols(block, false)?; - self.symbols.replace_locals(locals); - match block { - SectionBlock::Data { org, body } | SectionBlock::Code { org, body } => { - let mut bytes = Vec::new(); - for line in body { - match line { - Line::Inst(inst) => { - bytes.extend(self.assemble_inst(inst)); - } - Line::LabelDef(_) => { /* no-op */ } - Line::ValueDecl(decl) => { - bytes.extend(decl.to_bytes()); - } - Line::Export(_) => { /* no-op */ } - } - } - let (start, end) = match org { - SectionOrg::Start(start) => (*start, start + bytes.len() as u64), - SectionOrg::Range(start, end) => (*start, *end), - }; - - let section = match block { - SectionBlock::Data { .. } => Section::Data { - start, - end, - contents: bytes, - }, - SectionBlock::Code { .. } => Section::Code { - start, - end, - contents: bytes, - }, - SectionBlock::Meta { .. } => unreachable!(), - }; - sections.push(section); - } - SectionBlock::Meta { entries } => { - let entries = entries - .iter() - .map(|(name, value)| { - ( - name.to_string(), - self.get_value(value).expect("TODO : value label not found"), - ) - }) - .collect(); - sections.push(Section::Meta { entries }); - } - } - } - Ok(Object { - version: LAYOUT_VERSION, - sections, - }) - } - - fn gather_symbols(block: &SectionBlock, export: bool) -> Result> { - match block { - SectionBlock::Data { org, body, .. } | SectionBlock::Code { org, body, .. } => { - let mut exports = HashSet::new(); - let mut labels = HashMap::new(); - let mut pos = match org { - SectionOrg::Start(start) | SectionOrg::Range(start, _) => (*start) as usize, - }; - for line in body.iter() { - match line { - Line::Inst(inst) => { - pos += inst.len(); - } - Line::LabelDef(label) => { - if labels.contains_key(label) { - return Err(AssembleError::DuplicateSymbol { - name: label.to_string(), - }); - } else { - labels.insert(label.to_string(), pos as u64); - } - } - Line::ValueDecl(decl) => { - pos += decl.len(); - } - Line::Export(name) => { - if export { - exports.insert(name); - } - } - } - } - // TODO : make sure we aren't trying to export anything that doesn't exist - - // only return exports if specified - if export { - labels.retain(|k, _| exports.contains(k)); - } - Ok(labels) - } - SectionBlock::Meta { .. } => Ok(Default::default()), - } - } - - fn get_value(&self, value: &ImmValue) -> Option { - match value { - ImmValue::Number(n) => Some(*n), - ImmValue::Label(s) => self.symbols.get(s), - } - } - - fn assemble_inst(&self, inst: &Inst) -> Vec { - let mut builder = InstBuilder::default(); - builder = match inst { - Inst::Add(r1, r2) => builder.op(ADD).r1(*r1).r2(*r2), - Inst::Mul(r1, r2) => builder.op(MUL).r1(*r1).r2(*r2), - Inst::Div(r1, r2) => builder.op(DIV).r1(*r1).r2(*r2), - Inst::Mod(r1, r2) => builder.op(MOD).r1(*r1).r2(*r2), - Inst::INeg(r1) => builder.op(INEG).r1(*r1), - Inst::And(r1, r2) => builder.op(AND).r1(*r1).r2(*r2), - Inst::Or(r1, r2) => builder.op(OR).r1(*r1).r2(*r2), - Inst::Inv(r1) => builder.op(INV).r1(*r1), - Inst::Not(r1) => builder.op(NOT).r1(*r1), - Inst::Xor(r1, r2) => builder.op(XOR).r1(*r1).r2(*r2), - Inst::Shl(r1, r2) => builder.op(SHL).r1(*r1).r2(*r2), - Inst::Shr(r1, r2) => builder.op(SHR).r1(*r1).r2(*r2), - Inst::CmpEq(r1, r2) => builder.op(CMPEQ).r1(*r1).r2(*r2), - Inst::CmpLt(r1, r2) => builder.op(CMPLT).r1(*r1).r2(*r2), - Inst::Jmp(r1) => builder.op(JMP).r1(*r1), - Inst::Jz(r1) => builder.op(JZ).r1(*r1), - Inst::Jnz(r1) => builder.op(JNZ).r1(*r1), - Inst::Load(r1, r2) => builder.op(LOAD).r1(*r1).r2(*r2), - Inst::Store(r1, r2) => builder.op(STORE).r1(*r1).r2(*r2), - Inst::StoreImm(r1, imm) => match imm { - ImmValue::Number(num) => { - if *num > (u32::max_value() as u64) { - builder.op(STOREIMM64).imm64(*num) - } else { - builder.op(STOREIMM32).imm32(*num as u32) - } - } - ImmValue::Label(name) => { - let imm = self.symbols.get(name).expect("TODO: value label not found"); - builder.op(STOREIMM64).imm64(imm) - } - } - .r1(*r1), - Inst::StoreImm32(r1, imm) => { - let imm = self.get_value(imm).expect("TODO : value label not found"); - let imm_truncated = (imm & 0xFFFFFFFF) as u32; - // TODO compile-time warnings - if imm != (imm_truncated as u64) { - eprintln!( - "WARNING: immediate 32 bit value being truncated ({:#x} to {:#x})", - imm, imm_truncated - ) - } - builder.op(STOREIMM32).imm32(imm_truncated).r1(*r1) - } - Inst::StoreImm64(r1, imm) => { - let imm = self.get_value(imm).expect("TODO : value label not found"); - builder.op(STOREIMM64).imm64(imm).r1(*r1) - } - Inst::MemCopy(r1, r2) => builder.op(MEMCOPY).r1(*r1).r2(*r2), - Inst::RegCopy(r1, r2) => builder.op(REGCOPY).r1(*r1).r2(*r2), - Inst::Nop => builder.op(NOP), - Inst::Halt => builder.op(HALT), - }; - - builder.finish() - } -} - -#[derive(Debug, Default)] -struct InstBuilder { - op: Option, - r1: Option, - r2: Option, - imm32: Option, - imm64: Option, -} - -impl InstBuilder { - fn op(mut self, op: InstOp) -> Self { - self.op = Some(op); - self - } - - fn r1(mut self, r1: Reg) -> Self { - self.r1 = Some(r1); - self - } - - fn r2(mut self, r2: Reg) -> Self { - self.r2 = Some(r2); - self - } - - fn imm32(mut self, imm32: u32) -> Self { - self.imm32 = Some(imm32); - self - } - - fn imm64(mut self, imm64: u64) -> Self { - self.imm64 = Some(imm64); - self - } - - fn finish(self) -> Vec { - let mut cursor = Cursor::new(Vec::new()); - let InstBuilder { - op, - r1, - r2, - imm32, - imm64, - } = self; - - let op = op.expect("no op specified"); - cursor.write_u16::(op).unwrap(); - match (r1, r2, imm32, imm64) { - (Some(r1), Some(r2), None, None) => { - let tail = ((r1 as u16) << 10) | ((r2 as u16) << 4); - cursor.write_u16::(tail).unwrap(); - } - (Some(r1), None, None, None) => { - let tail = (r1 as u16) << 10; - cursor.write_u16::(tail).unwrap(); - } - (Some(r1), None, Some(imm32), None) => { - let tail = (r1 as u16) << 10; - cursor.write_u16::(tail).unwrap(); - cursor.write_u32::(imm32).unwrap(); - } - (Some(r1), None, None, Some(imm64)) => { - let tail = (r1 as u16) << 10; - cursor.write_u16::(tail).unwrap(); - cursor.write_u32::(0).unwrap(); - cursor.write_u64::(imm64).unwrap(); - } - (_, _, _, _) if op == HALT || op == NOP => {} - (_, _, _, _) => { - panic!( - r#"invalid instruction combo for opcode 0x{:04x}: -r1 : {:?} -r2 : {:?} -imm32 : {:?} -imm64 : {:?}"#, - op, r1, r2, imm32, imm64 - ); - } - } - cursor.into_inner() - } -} - -#[derive(Debug, Clone, Default)] -struct SymbolTable { - globals: HashMap, - locals: HashMap, -} - -impl SymbolTable { - pub fn new() -> Self { - Default::default() - } - - pub fn globals(&self) -> &HashMap { - &self.globals - } - - pub fn locals(&self) -> &HashMap { - &self.locals - } - - pub fn globals_mut(&mut self) -> &mut HashMap { - &mut self.globals - } - - pub fn locals_mut(&mut self) -> &mut HashMap { - &mut self.locals - } - - pub fn insert_global(&mut self, name: String, value: u64) -> Option { - self.globals_mut().insert(name, value) - } - - pub fn insert_local(&mut self, name: String, value: u64) -> Option { - self.locals_mut().insert(name, value) - } - - pub fn replace_locals(&mut self, locals: HashMap) -> HashMap { - mem::replace(self.locals_mut(), locals) - } - - pub fn get(&self, name: &String) -> Option { - self.locals - .get(name) - .or_else(|| self.globals.get(name)) - .copied() - } -}