Run rustfmt

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2020-03-09 16:47:30 -04:00
parent 63c81f07f7
commit d0f8d93edf
16 changed files with 218 additions and 194 deletions

View File

@@ -1,6 +1,6 @@
use cfgrammar::yacc::YaccKind; use cfgrammar::yacc::YaccKind;
use lrlex::LexerBuilder; use lrlex::LexerBuilder;
use lrpar::{CTParserBuilder}; use lrpar::CTParserBuilder;
use rerun_except::rerun_except; use rerun_except::rerun_except;
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
@@ -10,9 +10,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
LexerBuilder::new() LexerBuilder::new()
.rule_ids_map(lex_rule_ids_map) .rule_ids_map(lex_rule_ids_map)
.process_file_in_src("obj/syn/lexer.l")?; .process_file_in_src("obj/syn/lexer.l")?;
rerun_except(&[ rerun_except(&["examples/*.asm", "tests/*.asm"]).unwrap();
"examples/*.asm",
"tests/*.asm",
]).unwrap();
Ok(()) Ok(())
} }

View File

@@ -33,7 +33,7 @@ macro_rules! impl_add_assign {
self.0 = self.0 + (rhs as u64); self.0 = self.0 + (rhs as u64);
} }
} }
} };
} }
impl_add_assign!(usize); impl_add_assign!(usize);
@@ -53,7 +53,7 @@ macro_rules! impl_cmp {
self.0.partial_cmp(&other) self.0.partial_cmp(&other)
} }
} }
} };
} }
impl_cmp!(usize); impl_cmp!(usize);
@@ -66,7 +66,7 @@ macro_rules! impl_from {
Addr(other as u64) Addr(other as u64)
} }
} }
} };
} }
impl_from!(usize); impl_from!(usize);

View File

@@ -1,4 +1,4 @@
use crate::{inst::InstOp, reg::Reg, addr::*,}; use crate::{addr::*, inst::InstOp, reg::Reg};
use snafu::Snafu; use snafu::Snafu;
#[derive(Snafu, Debug, Clone)] #[derive(Snafu, Debug, Clone)]

View File

@@ -125,34 +125,28 @@ impl Inst {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
match self { match self {
Inst::Add(dest, source) Inst::Add(dest, source)
| Inst::Sub(dest, source) | Inst::Sub(dest, source)
| Inst::Mul(dest, source) | Inst::Mul(dest, source)
| Inst::Div(dest, source) | Inst::Div(dest, source)
| Inst::IDiv(dest, source) | Inst::IDiv(dest, source)
| Inst::Mod(dest, source) | Inst::Mod(dest, source)
| Inst::And(dest, source) | Inst::And(dest, source)
| Inst::Or(dest, source) | Inst::Or(dest, source)
| Inst::Xor(dest, source) | Inst::Xor(dest, source)
| Inst::Shl(dest, source) | Inst::Shl(dest, source)
| Inst::Shr(dest, source) | Inst::Shr(dest, source)
| Inst::INeg(dest, source) | Inst::INeg(dest, source)
| Inst::Inv(dest, source) | Inst::Inv(dest, source)
| Inst::Not(dest, source) | Inst::Not(dest, source)
| Inst::Mov(dest, source) => { 3 + dest.len() + source.len() } | Inst::Mov(dest, source) => 3 + dest.len() + source.len(),
Inst::CmpEq(s1, s2) Inst::CmpEq(s1, s2) | Inst::CmpLt(s1, s2) | Inst::Int(s1, s2) => {
| Inst::CmpLt(s1, s2) 3 + s1.len() + s2.len()
| Inst::Int(s1, s2) => { 3 + s1.len() + s2.len() } }
Inst::Jmp(v) Inst::Jmp(v) | Inst::Jz(v) | Inst::Jnz(v) | Inst::Call(v) | Inst::Push(v) => {
| Inst::Jz(v) 3 + v.len()
| Inst::Jnz(v) }
| Inst::Call(v) Inst::Pop(v) => 3 + v.len(),
| Inst::Push(v) => { 3 + v.len() } Inst::Ret | Inst::Halt | Inst::Nop | Inst::Dump | Inst::IRet => 2,
Inst::Pop(v) => { 3 + v.len() }
Inst::Ret
| Inst::Halt
| Inst::Nop
| Inst::Dump
| Inst::IRet => { 2 }
} }
} }
} }
@@ -176,7 +170,10 @@ impl Source {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
match self { match self {
Source::Addr64(_) | Source::Addr32(_) | Source::Addr16(_) | Source::Addr8(_) => 8, Source::Addr64(_) | Source::Addr32(_) | Source::Addr16(_) | Source::Addr8(_) => 8,
Source::RegAddr64(_) | Source::RegAddr32(_) | Source::RegAddr16(_) | Source::RegAddr8(_) => 1, Source::RegAddr64(_)
| Source::RegAddr32(_)
| Source::RegAddr16(_)
| Source::RegAddr8(_) => 1,
Source::Reg(_) => 1, Source::Reg(_) => 1,
Source::Imm(_) => 8, Source::Imm(_) => 8,
} }

View File

@@ -26,7 +26,7 @@ pub const IVT_LENGTH: usize = 512;
pub struct Interrupt(u64); pub struct Interrupt(u64);
const ENABLED_MASK: u64 = 0x8000_0000_0000_0000; const ENABLED_MASK: u64 = 0x8000_0000_0000_0000;
const ADDR_MASK: u64 = 0x07ff_ffff_ffff_ffff; const ADDR_MASK: u64 = 0x07ff_ffff_ffff_ffff;
impl Interrupt { impl Interrupt {
pub fn enabled(&self) -> bool { pub fn enabled(&self) -> bool {

View File

@@ -8,11 +8,14 @@ pub struct MemCursor<T> {
} }
impl<T> MemCursor<T> impl<T> MemCursor<T>
where Cursor<T>: ReadBytesExt, where
T: AsRef<[u8]> Cursor<T>: ReadBytesExt,
T: AsRef<[u8]>,
{ {
pub fn new(mem: T) -> Self { pub fn new(mem: T) -> Self {
MemCursor { cursor: Cursor::new(mem) } MemCursor {
cursor: Cursor::new(mem),
}
} }
pub fn position(&self) -> u64 { pub fn position(&self) -> u64 {
@@ -32,7 +35,7 @@ impl<T> MemCursor<T>
let end = start + count; let end = start + count;
self.check_addr(end as u64 - 1)?; self.check_addr(end as u64 - 1)?;
self.cursor.set_position(end as u64); self.cursor.set_position(end as u64);
Ok(&self.cursor.get_ref().as_ref()[start .. end]) Ok(&self.cursor.get_ref().as_ref()[start..end])
} }
pub fn next_u8_unchecked(&mut self) -> u8 { pub fn next_u8_unchecked(&mut self) -> u8 {
@@ -220,7 +223,8 @@ impl<T> MemCursor<T>
} }
impl<T> MemCursor<T> impl<T> MemCursor<T>
where T: AsRef<[u8]> where
T: AsRef<[u8]>,
{ {
fn check_addr(&self, addr: u64) -> Result<()> { fn check_addr(&self, addr: u64) -> Result<()> {
if addr >= (self.cursor.get_ref().as_ref().len() as u64) { if addr >= (self.cursor.get_ref().as_ref().len() as u64) {
@@ -232,8 +236,9 @@ impl<T> MemCursor<T>
} }
impl<T> MemCursor<T> impl<T> MemCursor<T>
where Cursor<T>: WriteBytesExt, where
T: AsRef<[u8]> Cursor<T>: WriteBytesExt,
T: AsRef<[u8]>,
{ {
pub fn write_u8_unchecked(&mut self, value: u8) { pub fn write_u8_unchecked(&mut self, value: u8) {
self.cursor.write_u8(value).unwrap(); self.cursor.write_u8(value).unwrap();

View File

@@ -1,7 +1,7 @@
pub mod error; pub mod error;
pub mod session;
mod includes; mod includes;
mod names; mod names;
pub mod session;
use self::{error::*, session::AsmSession}; use self::{error::*, session::AsmSession};
use crate::{ use crate::{
@@ -11,7 +11,7 @@ use crate::{
obj::{ obj::{
obj::{self, Object}, obj::{self, Object},
syn::ast::*, syn::ast::*,
} },
}; };
use byteorder::{WriteBytesExt, LE}; use byteorder::{WriteBytesExt, LE};
use std::{collections::HashMap, path::Path}; use std::{collections::HashMap, path::Path};
@@ -48,7 +48,7 @@ impl Asm for Directive {
match self { match self {
Directive::Data(section) => Ok(Some(obj::Section::Data(section.assemble(asm)?))), Directive::Data(section) => Ok(Some(obj::Section::Data(section.assemble(asm)?))),
Directive::Meta(section) => section.assemble(asm).map(Some), Directive::Meta(section) => section.assemble(asm).map(Some),
Directive::Include(_) => { Ok(None) } Directive::Include(_) => Ok(None),
} }
} }
} }
@@ -81,7 +81,10 @@ impl Asm for DataSection {
let mut contents = Vec::with_capacity(content_len as usize); let mut contents = Vec::with_capacity(content_len as usize);
for (pos, line) in self.lines(start) { for (pos, line) in self.lines(start) {
let expected_len = pos - (start as usize); let expected_len = pos - (start as usize);
assert!(expected_len >= contents.len(), "next line size would cause section to shrink"); assert!(
expected_len >= contents.len(),
"next line size would cause section to shrink"
);
// resize contents if necessary, this pads out aligned values // resize contents if necessary, this pads out aligned values
contents.resize(expected_len, 0); contents.resize(expected_len, 0);
contents.extend(line.assemble(session)?); contents.extend(line.assemble(session)?);
@@ -93,11 +96,7 @@ impl Asm for DataSection {
"in section {}", "in section {}",
self.name self.name
); );
assert_eq!( assert_eq!(session.pos - start, content_len, "in section {}", self.name);
session.pos - start, content_len,
"in section {}",
self.name
);
session.name_stack.pop(); session.name_stack.pop();
Ok(obj::DataSection { Ok(obj::DataSection {
@@ -122,8 +121,15 @@ impl Asm for MetaSection {
} }
let value = match &line.value { let value = match &line.value {
Value::Int(i) => *i, Value::Int(i) => *i,
Value::Name(s) => session.lookup_name(s.as_str()) Value::Name(s) => {
.ok_or_else(|| AsmError::UnknownName { name: s.to_string() })?.addr.0, session
.lookup_name(s.as_str())
.ok_or_else(|| AsmError::UnknownName {
name: s.to_string(),
})?
.addr
.0
}
Value::Reg(_) | Value::Here | Value::Addr(_, _) => { Value::Reg(_) | Value::Here | Value::Addr(_, _) => {
return Err(AsmError::IllegalMetaValue { return Err(AsmError::IllegalMetaValue {
name: line.name.to_string(), name: line.name.to_string(),
@@ -218,10 +224,7 @@ impl Asm for Inst {
let dest_encoding = dest.source_encoding() << 4; let dest_encoding = dest.source_encoding() << 4;
bytes.write_u8(dest_encoding).unwrap(); bytes.write_u8(dest_encoding).unwrap();
bytes.extend(dest.assemble(session)?); bytes.extend(dest.assemble(session)?);
assert_eq!( assert_eq!(len, bytes.len(),);
len,
bytes.len(),
);
Ok(bytes) Ok(bytes)
} }
Inst::Int(v1, v2) => self.map_source_source(session, inst::INT, v1, v2), Inst::Int(v1, v2) => self.map_source_source(session, inst::INT, v1, v2),
@@ -235,47 +238,56 @@ impl Asm for Inst {
} }
impl Inst { impl Inst {
fn map_dest_source(&self, session: &mut AsmSession, op: inst::InstOp, dest: &Value, source: &Value) -> Result<Vec<u8>> { fn map_dest_source(
&self,
session: &mut AsmSession,
op: inst::InstOp,
dest: &Value,
source: &Value,
) -> Result<Vec<u8>> {
let len = self.len(); let len = self.len();
let mut bytes = Vec::with_capacity(len); let mut bytes = Vec::with_capacity(len);
bytes.write_u16::<LE>(op).unwrap(); bytes.write_u16::<LE>(op).unwrap();
let dest_encoding = let dest_encoding = dest
dest.dest_encoding() .dest_encoding()
.ok_or_else(|| AsmError::IllegalDestValue { .ok_or_else(|| AsmError::IllegalDestValue {
value: dest.clone(), value: dest.clone(),
})?; })?;
let source_encoding = source.source_encoding(); let source_encoding = source.source_encoding();
bytes bytes
.write_u8((dest_encoding << 4) | source_encoding) .write_u8((dest_encoding << 4) | source_encoding)
.unwrap(); .unwrap();
bytes.extend(dest.assemble(session)?); bytes.extend(dest.assemble(session)?);
bytes.extend(source.assemble(session)?); bytes.extend(source.assemble(session)?);
assert_eq!( assert_eq!(len, bytes.len(),);
len,
bytes.len(),
);
Ok(bytes) Ok(bytes)
} }
fn map_source_source(&self, session: &mut AsmSession, op: inst::InstOp, s1: &Value, s2: &Value) -> Result<Vec<u8>> { fn map_source_source(
&self,
session: &mut AsmSession,
op: inst::InstOp,
s1: &Value,
s2: &Value,
) -> Result<Vec<u8>> {
let len = self.len(); let len = self.len();
let mut bytes = Vec::with_capacity(len); let mut bytes = Vec::with_capacity(len);
bytes.write_u16::<LE>(op).unwrap(); bytes.write_u16::<LE>(op).unwrap();
let s1_encoding = s1.source_encoding(); let s1_encoding = s1.source_encoding();
let s2_encoding = s2.source_encoding(); let s2_encoding = s2.source_encoding();
bytes bytes.write_u8((s1_encoding << 4) | s2_encoding).unwrap();
.write_u8((s1_encoding << 4) | s2_encoding)
.unwrap();
bytes.extend(s1.assemble(session)?); bytes.extend(s1.assemble(session)?);
bytes.extend(s2.assemble(session)?); bytes.extend(s2.assemble(session)?);
assert_eq!( assert_eq!(len, bytes.len(),);
len,
bytes.len(),
);
Ok(bytes) Ok(bytes)
} }
fn map_source(&self, session: &mut AsmSession, op: inst::InstOp, source: &Value) -> Result<Vec<u8>> { fn map_source(
&self,
session: &mut AsmSession,
op: inst::InstOp,
source: &Value,
) -> Result<Vec<u8>> {
let len = self.len(); let len = self.len();
let mut bytes = Vec::with_capacity(len); let mut bytes = Vec::with_capacity(len);
bytes.write_u16::<LE>(op).unwrap(); bytes.write_u16::<LE>(op).unwrap();
@@ -290,10 +302,7 @@ impl Inst {
let len = self.len(); let len = self.len();
let mut bytes = Vec::with_capacity(len); let mut bytes = Vec::with_capacity(len);
bytes.write_u16::<LE>(op).unwrap(); bytes.write_u16::<LE>(op).unwrap();
assert_eq!( assert_eq!(len, bytes.len(),);
len,
bytes.len(),
);
Ok(bytes) Ok(bytes)
} }
} }
@@ -306,8 +315,12 @@ impl Asm for Value {
Value::Int(i) => Ok(i.to_le_bytes().to_vec()), Value::Int(i) => Ok(i.to_le_bytes().to_vec()),
Value::Reg(r) => Ok(vec![*r]), Value::Reg(r) => Ok(vec![*r]),
Value::Name(name) => { Value::Name(name) => {
let value = session.lookup_name(name.as_str()) let value =
.ok_or_else(|| AsmError::UnknownName { name: name.to_string() })?; session
.lookup_name(name.as_str())
.ok_or_else(|| AsmError::UnknownName {
name: name.to_string(),
})?;
Ok(value.addr.0.to_le_bytes().to_vec()) Ok(value.addr.0.to_le_bytes().to_vec())
} }
Value::Here => Ok(session.pos.to_le_bytes().to_vec()), Value::Here => Ok(session.pos.to_le_bytes().to_vec()),
@@ -331,7 +344,7 @@ mod test {
fn test_inst_len() { fn test_inst_len() {
let mut session = AsmSession::default(); let mut session = AsmSession::default();
//asm.names //asm.names
//.push(vec![("test".to_string(), Addr(0u64))].into_iter().collect()); //.push(vec![("test".to_string(), Addr(0u64))].into_iter().collect());
macro_rules! assert_len { macro_rules! assert_len {
($inst:expr) => {{ ($inst:expr) => {{

View File

@@ -112,4 +112,3 @@ impl From<LexParseError> for SyntaxError {
} }
pub type Result<T, E = AsmError> = std::result::Result<T, E>; pub type Result<T, E = AsmError> = std::result::Result<T, E>;

View File

@@ -1,14 +1,14 @@
use crate::{ use crate::{
addr::Addr, addr::Addr,
obj::{ obj::{
assemble::{ assemble::{error::*, session::AsmSession},
session::AsmSession, syn::ast::{DataLine, DataSection, Directive},
error::*,
},
syn::ast::{DataSection, DataLine, Directive},
}, },
}; };
use std::{collections::{HashMap, HashSet}, rc::Rc}; use std::{
collections::{HashMap, HashSet},
rc::Rc,
};
// TODO(asm) make custom Names type that has "merge" that will catch errors with duplicate names // TODO(asm) make custom Names type that has "merge" that will catch errors with duplicate names
pub type Names = HashMap<String, Name>; pub type Names = HashMap<String, Name>;
@@ -54,11 +54,14 @@ pub fn get_section_names(section: &DataSection) -> Result<Names> {
} }
let export = exports.remove(name); let export = exports.remove(name);
names.insert(name.clone(), Name { names.insert(
name: name.clone(), name.clone(),
addr: Addr(pos as u64), Name {
export, name: name.clone(),
}); addr: Addr(pos as u64),
export,
},
);
} }
} }
@@ -66,7 +69,9 @@ pub fn get_section_names(section: &DataSection) -> Result<Names> {
if exports.is_empty() { if exports.is_empty() {
Ok(names) Ok(names)
} else { } else {
Err(AsmError::UnknownExport { name: exports.iter().next().unwrap().to_string() }) Err(AsmError::UnknownExport {
name: exports.iter().next().unwrap().to_string(),
})
} }
} }
@@ -93,12 +98,16 @@ pub fn get_exports(session: &mut AsmSession) -> Result<Names> {
for name_map in all_exports.iter() { for name_map in all_exports.iter() {
let names_set: HashSet<_> = name_map.keys().collect(); let names_set: HashSet<_> = name_map.keys().collect();
if let Some(dupe) = exports.intersection(&names_set).next() { if let Some(dupe) = exports.intersection(&names_set).next() {
return Err(AsmError::DuplicateExport { name: dupe.to_string() }); return Err(AsmError::DuplicateExport {
name: dupe.to_string(),
});
} }
exports.extend(names_set); exports.extend(names_set);
} }
// NOTE: this can probably be done with a fancy combinator chain // NOTE: this can probably be done with a fancy combinator chain
Ok(all_exports.into_iter() Ok(all_exports.into_iter().fold(Names::new(), |mut acc, val| {
.fold(Names::new(), |mut acc, val| { acc.extend(val); acc })) acc.extend(val);
acc
}))
} }

View File

@@ -1,14 +1,12 @@
use crate::{ use crate::obj::{
obj::{ assemble::{
assemble::{ error::*,
Asm, includes::GetIncludes,
includes::GetIncludes, names::{self, Name, Names},
names::{self, Name, Names}, Asm,
error::*,
},
obj::Object,
syn::ast::Ast,
}, },
obj::Object,
syn::ast::Ast,
}; };
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
@@ -19,19 +17,17 @@ use std::{
/// A shared session for the assembler. /// A shared session for the assembler.
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct AsmSession { pub struct AsmSession {
pub (in super) includes: Rc<BTreeMap<PathBuf, Ast>>, pub(super) includes: Rc<BTreeMap<PathBuf, Ast>>,
pub (in super) include_search_paths: Vec<PathBuf>, pub(super) include_search_paths: Vec<PathBuf>,
pub (in super) include_stack: Vec<PathBuf>, pub(super) include_stack: Vec<PathBuf>,
pub (in super) name_stack: Vec<Names>, pub(super) name_stack: Vec<Names>,
pub (in super) pos: u64, pub(super) pos: u64,
} }
impl AsmSession { impl AsmSession {
pub fn assemble(&mut self) -> Result<Object> { pub fn assemble(&mut self) -> Result<Object> {
let includes = Rc::clone(&self.includes); let includes = Rc::clone(&self.includes);
let sections: Vec<_> = includes.iter() let sections: Vec<_> = includes.iter().flat_map(|(_, ast)| ast).collect();
.flat_map(|(_, ast)| ast)
.collect();
sections.assemble(self) sections.assemble(self)
} }
@@ -46,19 +42,21 @@ impl AsmSession {
Ok(()) Ok(())
} }
pub (in super) fn current_include_path(&self) -> Option<&Path> { pub(super) fn current_include_path(&self) -> Option<&Path> {
self.include_stack.last().map(PathBuf::as_path) self.include_stack.last().map(PathBuf::as_path)
} }
pub (in super) fn resolve_include_path(&self, path: impl AsRef<Path>) -> Option<PathBuf> { pub(super) fn resolve_include_path(&self, path: impl AsRef<Path>) -> Option<PathBuf> {
let path = path.as_ref(); let path = path.as_ref();
self.current_include_path() self.current_include_path()
.and_then(|last_path| last_path.parent()) .and_then(|last_path| last_path.parent())
.map(|last_dir| last_dir.join(path)) .map(|last_dir| last_dir.join(path))
.or_else(|| self.include_search_paths .or_else(|| {
.iter() self.include_search_paths
.filter_map(|include| include.join(path).canonicalize().ok()) .iter()
.next()) .filter_map(|include| include.join(path).canonicalize().ok())
.next()
})
} }
pub fn lookup_name(&self, name: &str) -> Option<&Name> { pub fn lookup_name(&self, name: &str) -> Option<&Name> {

View File

@@ -1,8 +1,9 @@
use crate::{mem::MemCursor, obj::obj::*}; use crate::{mem::MemCursor, obj::obj::*};
use prettytable::{Table, row, cell}; use prettytable::{cell, row, Table};
use std::io::{self, Write as Write}; use std::io::{self, Write};
const SEP: &str = "================================================================================"; const SEP: &str =
"================================================================================";
pub trait Disasm { pub trait Disasm {
fn disasm(&self, writer: &mut dyn Write) -> io::Result<()>; fn disasm(&self, writer: &mut dyn Write) -> io::Result<()>;
@@ -61,8 +62,8 @@ impl Disasm for DataSection {
if let Ok(inst) = cursor.next_inst() { if let Ok(inst) = cursor.next_inst() {
let start = cursor_pos as usize; let start = cursor_pos as usize;
let end = start + inst.len(); let end = start + inst.len();
let data = &self.contents.as_slice()[start .. end]; let data = &self.contents.as_slice()[start..end];
table.add_row(row! [ table.add_row(row![
format!("{:016x} <{}+{:x}>", pos, self.name, cursor_pos), format!("{:016x} <{}+{:x}>", pos, self.name, cursor_pos),
bytes_hex(data), bytes_hex(data),
format!("{:?}", inst), format!("{:?}", inst),

View File

@@ -42,4 +42,3 @@ into_parse_error! {
} }
pub type Result<T, E = ParseError> = std::result::Result<T, E>; pub type Result<T, E = ParseError> = std::result::Result<T, E>;

View File

@@ -114,8 +114,8 @@ pub enum Section {
impl Section { impl Section {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
match self { match self {
Section::Data(s) => { 1 + 8 + s.len() }, Section::Data(s) => 1 + 8 + s.len(),
Section::Meta(s) => { 1 + 8 + s.len() }, Section::Meta(s) => 1 + 8 + s.len(),
} }
} }
@@ -129,7 +129,7 @@ impl Section {
Section::Meta(s) => { Section::Meta(s) => {
cursor.write_u8(SectionKind::Meta.into()).unwrap(); cursor.write_u8(SectionKind::Meta.into()).unwrap();
s.to_bytes() s.to_bytes()
}, }
}; };
cursor.write_u64::<LE>(bytes.len() as u64).unwrap(); cursor.write_u64::<LE>(bytes.len() as u64).unwrap();
cursor.write(&bytes).unwrap(); cursor.write(&bytes).unwrap();
@@ -181,7 +181,7 @@ impl DataSection {
let name_len = cursor.read_u16::<LE>()? as usize; let name_len = cursor.read_u16::<LE>()? as usize;
let name_start = cursor.position() as usize; let name_start = cursor.position() as usize;
let name_end = name_start + name_len; let name_end = name_start + name_len;
let name_bytes = &bytes[name_start .. name_end]; let name_bytes = &bytes[name_start..name_end];
let name_string = String::from_utf8(name_bytes.to_vec())?; let name_string = String::from_utf8(name_bytes.to_vec())?;
cursor.set_position(name_end as u64); cursor.set_position(name_end as u64);
@@ -205,7 +205,9 @@ pub struct MetaSection {
impl MetaSection { impl MetaSection {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
8 + self.entries.iter() 8 + self
.entries
.iter()
.map(|(k, _)| 8 + k.as_bytes().len() + 8) .map(|(k, _)| 8 + k.as_bytes().len() + 8)
.sum::<usize>() .sum::<usize>()
} }
@@ -254,11 +256,11 @@ mod test {
name: "data".to_string(), name: "data".to_string(),
start: 0, start: 0,
len: 16, len: 16,
contents: vec!(0u8; 16), contents: vec![0u8; 16],
}), }),
Section::Meta(MetaSection { Section::Meta(MetaSection {
entries: Default::default(), entries: Default::default(),
}) }),
], ],
}; };

View File

@@ -1,8 +1,4 @@
use crate::{ use crate::{inst, interrupt::Interrupt, reg::Reg};
interrupt::Interrupt,
inst,
reg::Reg,
};
pub type Ast = Vec<Directive>; pub type Ast = Vec<Directive>;
@@ -291,34 +287,30 @@ impl Inst {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
match self { match self {
Inst::Add(v1, v2) Inst::Add(v1, v2)
| Inst::Sub(v1, v2) | Inst::Sub(v1, v2)
| Inst::Mul(v1, v2) | Inst::Mul(v1, v2)
| Inst::Div(v1, v2) | Inst::Div(v1, v2)
| Inst::IDiv(v1, v2) | Inst::IDiv(v1, v2)
| Inst::Mod(v1, v2) | Inst::Mod(v1, v2)
| Inst::And(v1, v2) | Inst::And(v1, v2)
| Inst::Or(v1, v2) | Inst::Or(v1, v2)
| Inst::Xor(v1, v2) | Inst::Xor(v1, v2)
| Inst::Shl(v1, v2) | Inst::Shl(v1, v2)
| Inst::Shr(v1, v2) | Inst::Shr(v1, v2)
| Inst::INeg(v1, v2) | Inst::INeg(v1, v2)
| Inst::Inv(v1, v2) | Inst::Inv(v1, v2)
| Inst::Not(v1, v2) | Inst::Not(v1, v2)
| Inst::CmpEq(v1, v2) | Inst::CmpEq(v1, v2)
| Inst::CmpLt(v1, v2) | Inst::CmpLt(v1, v2)
| Inst::Int(v1, v2) | Inst::Int(v1, v2)
| Inst::Mov(v1, v2) => { 3 + v1.len() + v2.len() } | Inst::Mov(v1, v2) => 3 + v1.len() + v2.len(),
Inst::Jmp(v) Inst::Jmp(v)
| Inst::Jz(v) | Inst::Jz(v)
| Inst::Jnz(v) | Inst::Jnz(v)
| Inst::Call(v) | Inst::Call(v)
| Inst::Push(v) | Inst::Push(v)
| Inst::Pop(v) => { 3 + v.len() } | Inst::Pop(v) => 3 + v.len(),
Inst::Ret Inst::Ret | Inst::IRet | Inst::Halt | Inst::Nop | Inst::Dump => 2,
| Inst::IRet
| Inst::Halt
| Inst::Nop
| Inst::Dump => { 2 }
} }
} }
} }

View File

@@ -146,21 +146,25 @@ impl State {
pub fn ivt(&self) -> Result<&[Interrupt]> { pub fn ivt(&self) -> Result<&[Interrupt]> {
let ivt_addr = self.get_reg_unchecked(IVT); let ivt_addr = self.get_reg_unchecked(IVT);
if ivt_addr % 64 != 0 { if ivt_addr % 64 != 0 {
panic!("illegal IVT address {:#x}; must be divisible by 64", ivt_addr); panic!(
"illegal IVT address {:#x}; must be divisible by 64",
ivt_addr
);
} }
let start = ivt_addr as usize; let start = ivt_addr as usize;
let end = start + (IVT_LENGTH * mem::size_of::<Interrupt>()); let end = start + (IVT_LENGTH * mem::size_of::<Interrupt>());
if end > self.mem.len() { if end > self.mem.len() {
return Err(VmError::MemOutOfBounds { addr: Addr(ivt_addr) }); return Err(VmError::MemOutOfBounds {
addr: Addr(ivt_addr),
});
} }
// This is safe because we check the bounds above // This is safe because we check the bounds above
let slice_ptr = (&self.mem[start..]).as_ptr(); let slice_ptr = (&self.mem[start..]).as_ptr();
let slice = unsafe { let slice =
std::slice::from_raw_parts(slice_ptr as *const Interrupt, IVT_LENGTH) unsafe { std::slice::from_raw_parts(slice_ptr as *const Interrupt, IVT_LENGTH) };
};
Ok(slice) Ok(slice)
} }
@@ -386,7 +390,9 @@ impl State {
// create a destination based on the size of the source // create a destination based on the size of the source
let dest = match source { let dest = match source {
Source::Addr64(_) | Source::RegAddr64(_) | Source::Reg(_) | Source::Imm(_) => Dest::Addr64(Addr(stack_addr)), Source::Addr64(_) | Source::RegAddr64(_) | Source::Reg(_) | Source::Imm(_) => {
Dest::Addr64(Addr(stack_addr))
}
Source::Addr32(_) | Source::RegAddr32(_) => Dest::Addr32(Addr(stack_addr)), Source::Addr32(_) | Source::RegAddr32(_) => Dest::Addr32(Addr(stack_addr)),
Source::Addr16(_) | Source::RegAddr16(_) => Dest::Addr16(Addr(stack_addr)), Source::Addr16(_) | Source::RegAddr16(_) => Dest::Addr16(Addr(stack_addr)),
Source::Addr8(_) | Source::RegAddr8(_) => Dest::Addr8(Addr(stack_addr)), Source::Addr8(_) | Source::RegAddr8(_) => Dest::Addr8(Addr(stack_addr)),

View File

@@ -2,21 +2,26 @@ mod common;
extern crate libvm as vm; extern crate libvm as vm;
use structopt::StructOpt;
use snafu::Snafu; use snafu::Snafu;
use std::{fs, io::{stdout, Write}, path::{Path, PathBuf}, process}; use std::{
fs,
io::{stdout, Write},
path::{Path, PathBuf},
process,
};
use structopt::StructOpt;
const DEFAULT_MAX_MEM: usize = 64 * 1024 * 1024; const DEFAULT_MAX_MEM: usize = 64 * 1024 * 1024;
#[derive(Snafu, Debug, Clone, PartialEq)] #[derive(Snafu, Debug, Clone, PartialEq)]
enum ArgParseError<'a> { enum ArgParseError<'a> {
#[snafu(display("invalid specified size: {} (sizes may end in G, M, or K)", text))] #[snafu(display("invalid specified size: {} (sizes may end in G, M, or K)", text))]
InvalidSize { text: &'a str } InvalidSize { text: &'a str },
} }
fn from_bytes_size<'a>(mut text: &'a str) -> std::result::Result<usize, ArgParseError<'a>> { fn from_bytes_size<'a>(mut text: &'a str) -> std::result::Result<usize, ArgParseError<'a>> {
if text.is_empty() { if text.is_empty() {
return Err(ArgParseError::InvalidSize { text }) return Err(ArgParseError::InvalidSize { text });
} }
let multiplier = match text.chars().last().unwrap() { let multiplier = match text.chars().last().unwrap() {
'k' | 'K' => 1024, 'k' | 'K' => 1024,
@@ -26,9 +31,11 @@ fn from_bytes_size<'a>(mut text: &'a str) -> std::result::Result<usize, ArgParse
}; };
// trim the last character // trim the last character
if multiplier != 1 { if multiplier != 1 {
text = &text[0 .. text.len() - 1]; text = &text[0..text.len() - 1];
} }
let value = text.parse::<usize>().map_err(|_| ArgParseError::InvalidSize { text })?; let value = text
.parse::<usize>()
.map_err(|_| ArgParseError::InvalidSize { text })?;
Ok(value * multiplier) Ok(value * multiplier)
} }
@@ -56,7 +63,6 @@ fn test_bytes_size() {
struct Options { struct Options {
// maybe some other options: // maybe some other options:
// * debug // * debug
/// The input file to work with. /// The input file to work with.
/// ///
/// By default, the file will be executed. If -c is passed, it will not run and only compile. /// By default, the file will be executed. If -c is passed, it will not run and only compile.
@@ -82,7 +88,6 @@ struct Options {
/// Only compile the input file to an object. /// Only compile the input file to an object.
#[structopt(short = "c", long)] #[structopt(short = "c", long)]
compile_only: bool, compile_only: bool,
} }
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>; type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
@@ -107,8 +112,8 @@ fn get_writer(path: impl AsRef<Path>) -> Result<Box<dyn Write>> {
fn main() -> Result<()> { fn main() -> Result<()> {
use vm::{ use vm::{
state::State,
obj::{assemble, disassemble::Disasm}, obj::{assemble, disassemble::Disasm},
state::State,
}; };
let opt = Options::from_args(); let opt = Options::from_args();
@@ -125,7 +130,9 @@ fn main() -> Result<()> {
writer.write(&bytes)?; writer.write(&bytes)?;
Ok(()) Ok(())
} else if opt.disassemble { } else if opt.disassemble {
let outfile = opt.out.as_ref() let outfile = opt
.out
.as_ref()
.map(|p| p.as_path()) .map(|p| p.as_path())
.unwrap_or_else(|| Path::new("-")); .unwrap_or_else(|| Path::new("-"));
let mut writer = get_writer(&outfile)?; let mut writer = get_writer(&outfile)?;
@@ -138,4 +145,3 @@ fn main() -> Result<()> {
process::exit((status & 0xffff_ffff) as i32); process::exit((status & 0xffff_ffff) as i32);
} }
} }