Add object layout, object parsing, instruction layout

* Object layout and parsing are done in the vm::obj module
* Add MemCursor, a wrapper around the std::io::Cursor type for walking
  through VM memory
* Add vm::tick module for containing the Vm::tick() method
  implementation, since it's pretty big
* Instructions are now variable-sized, and are read lazily,
  one-at-a-time directly from memory.
* Add VM runtime error structure
* Probably some other stuff I forgot

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-02-03 17:56:32 -05:00
parent 47ee61ca0d
commit 214f0b8aed
12 changed files with 554 additions and 502 deletions

107
src/vm/obj/obj.rs Normal file
View File

@@ -0,0 +1,107 @@
use crate::vm::obj::error::ParseError;
use std::{
convert::TryFrom,
fmt::Debug,
};
pub const MAGIC: u64 = 0xDEAD_BEA7_BA5E_BA11;
#[derive(Debug)]
pub struct Object {
pub header: Header,
pub sections: Vec<Box<dyn Section>>,
}
#[derive(Debug, Clone, Copy)]
pub struct Header {
pub version: u16,
pub sections: u16,
}
macro_rules! section_kind {
(
pub enum $enum_name:ident {
$($name:ident = $value:expr),* $(,)?
}
) => {
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum $enum_name {
$($name = $value),*
}
impl TryFrom<u8> for SectionKind {
type Error = ParseError;
fn try_from(other: u8) -> std::result::Result<Self, Self::Error> {
match other {
$(
$value => Ok($enum_name::$name),
)*
_ => Err(ParseError::UnknownSectionKind { kind: other }),
}
}
}
};
}
section_kind! {
pub enum SectionKind {
Data = 0x00,
Code = 0x10,
Meta = 0xFF,
}
}
pub trait Section: Debug {
fn header(&self) -> SectionHeader;
}
#[derive(Debug, Clone, Copy)]
pub struct SectionHeader {
pub kind: SectionKind,
pub checksum: u32,
pub len: u64,
}
#[derive(Debug, Clone)]
pub struct DataSection {
pub header: SectionHeader,
pub load_location: u64,
pub contents: Vec<u8>,
}
impl Section for DataSection {
fn header(&self) -> SectionHeader {
self.header
}
}
#[derive(Debug, Clone)]
pub struct CodeSection {
pub header: SectionHeader,
pub load_location: u64,
pub contents: Vec<u8>,
}
impl Section for CodeSection {
fn header(&self) -> SectionHeader {
self.header
}
}
#[derive(Debug, Clone)]
pub struct MetaSection {
pub header: SectionHeader,
pub entry_count: u64,
pub entries: Vec<(String, Vec<u8>)>,
}
impl Section for MetaSection {
fn header(&self) -> SectionHeader {
self.header
}
}