diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index 34e6d479..95502f18 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -3205,7 +3205,10 @@ impl Codegen { #[cfg(test)] { - self.disasm(&mut String::new()); + let mut vc = Vec::::new(); + if self.disasm(&mut vc).is_err() { + panic!("{}", String::from_utf8(vc).unwrap()); + } } self.run_vm(); @@ -3223,8 +3226,7 @@ impl Codegen { ret } - #[cfg(test)] - fn disasm(&mut self, output: &mut String) { + pub fn disasm(&mut self, output: &mut impl std::io::Write) -> std::io::Result<()> { use crate::DisasmItem; let mut sluce = self.output.code.as_slice(); let functions = self @@ -3280,20 +3282,15 @@ impl Codegen { .map(|s| (s.range.start, ("string", s.range.len() as _, DisasmItem::Global))), ) .collect::>(); - if crate::disasm(&mut sluce, &functions, output, |bin| { + crate::disasm(&mut sluce, &functions, output, |bin| { if self.ct.active() && let Some(trap) = Self::read_trap(bin.as_ptr() as u64) { bin.take(..trap.size() + 1).unwrap(); } }) - .is_err() - { - panic!("{} {:?}", output, sluce); - } } - #[cfg(test)] fn is_fully_linked(&self, func: ty::Func) -> bool { self.output .relocs @@ -3471,7 +3468,12 @@ mod tests { let mut out = Vec::new(); codegen.dump(&mut out).unwrap(); - codegen.disasm(output); + let mut buf = Vec::::new(); + let err = codegen.disasm(&mut buf); + output.push_str(String::from_utf8(buf).unwrap().as_str()); + if err.is_err() { + return; + } use std::fmt::Write; diff --git a/hblang/src/lib.rs b/hblang/src/lib.rs index 8cef29bd..69a7e6ad 100644 --- a/hblang/src/lib.rs +++ b/hblang/src/lib.rs @@ -135,27 +135,25 @@ fn decode(binary: &mut &[u8]) -> Option { unsafe { Some(std::ptr::read(binary.take(..std::mem::size_of::())?.as_ptr() as *const T)) } } -#[cfg(test)] #[derive(Clone, Copy)] enum DisasmItem { Func, Global, } -#[cfg(test)] fn disasm( binary: &mut &[u8], functions: &HashMap, - out: &mut String, + out: &mut impl std::io::Write, mut eca_handler: impl FnMut(&mut &[u8]), -) -> std::fmt::Result { +) -> std::io::Result<()> { use self::instrs::Instr; - fn instr_from_byte(b: u8) -> Result { + fn instr_from_byte(b: u8) -> std::io::Result { if b as usize >= instrs::NAMES.len() { - return Err(std::fmt::Error); + return Err(std::io::ErrorKind::InvalidData.into()); } - unsafe { std::mem::transmute(b) } + Ok(unsafe { std::mem::transmute::(b) }) } let mut labels = HashMap::::default(); @@ -179,7 +177,7 @@ fn disasm( if offset as u32 == off + len { break; } - instrs::parse_args(binary, inst, &mut buf).ok_or(std::fmt::Error)?; + instrs::parse_args(binary, inst, &mut buf).ok_or(std::io::ErrorKind::OutOfMemory)?; for op in buf.drain(..) { let rel = match op { @@ -211,18 +209,16 @@ fn disasm( } let prev = *binary; - use std::fmt::Write; - writeln!(out, "{name}:")?; binary.take(..off as usize).unwrap(); while let Some(&byte) = binary.first() { - let inst = instr_from_byte(byte)?; + let inst = instr_from_byte(byte).unwrap(); let offset: i32 = (prev.len() - binary.len()).try_into().unwrap(); if offset as u32 == off + len { break; } - instrs::parse_args(binary, inst, &mut buf).ok_or(std::fmt::Error)?; + instrs::parse_args(binary, inst, &mut buf).unwrap(); if let Some(label) = labels.get(&offset.try_into().unwrap()) { write!(out, "{:>2}: ", label)?; @@ -281,8 +277,12 @@ fn disasm( *binary = prev; } - if has_oob || has_cycle { - return Err(std::fmt::Error); + if has_oob { + return Err(std::io::ErrorKind::InvalidInput.into()); + } + + if has_cycle { + return Err(std::io::ErrorKind::TimedOut.into()); } Ok(()) @@ -700,6 +700,7 @@ pub fn run_test( pub struct Options { pub fmt: bool, pub fmt_current: bool, + pub dump_asm: bool, pub extra_threads: usize, } @@ -752,13 +753,17 @@ pub fn run_compiler( } else if options.fmt_current { let ast = parsed.into_iter().next().unwrap(); let source = std::fs::read_to_string(&*ast.path)?; - format_to(&ast, &source, &mut std::io::stdout())?; + format_to(&ast, &source, out)?; } else { let mut codegen = codegen::Codegen::default(); codegen.files = parsed; codegen.generate(); - codegen.dump(out)?; + if options.dump_asm { + codegen.disasm(out)?; + } else { + codegen.dump(out)?; + } } Ok(()) diff --git a/hblang/src/main.rs b/hblang/src/main.rs index 6065f66d..c1e0386e 100644 --- a/hblang/src/main.rs +++ b/hblang/src/main.rs @@ -15,6 +15,7 @@ fn main() -> std::io::Result<()> { hblang::Options { fmt: args.contains(&"--fmt"), fmt_current: args.contains(&"--fmt-current"), + dump_asm: args.contains(&"--dump-asm"), extra_threads: args .iter() .position(|&a| a == "--threads") diff --git a/hblang/src/son.rs b/hblang/src/son.rs index 60b40ce2..4ec22575 100644 --- a/hblang/src/son.rs +++ b/hblang/src/son.rs @@ -7,7 +7,7 @@ use { log, parser::{ self, - idfl::{self, index}, + idfl::{self}, Expr, ExprRef, FileId, Pos, }, HashMap, @@ -17,7 +17,6 @@ use { mem, ops::{self, Range}, rc::Rc, - usize, }, };