adding disasm option

This commit is contained in:
mlokr 2024-09-04 17:56:59 +02:00
parent 3807276a55
commit a21dee61e7
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
4 changed files with 35 additions and 28 deletions

View file

@ -3205,7 +3205,10 @@ impl Codegen {
#[cfg(test)] #[cfg(test)]
{ {
self.disasm(&mut String::new()); let mut vc = Vec::<u8>::new();
if self.disasm(&mut vc).is_err() {
panic!("{}", String::from_utf8(vc).unwrap());
}
} }
self.run_vm(); self.run_vm();
@ -3223,8 +3226,7 @@ impl Codegen {
ret ret
} }
#[cfg(test)] pub fn disasm(&mut self, output: &mut impl std::io::Write) -> std::io::Result<()> {
fn disasm(&mut self, output: &mut String) {
use crate::DisasmItem; use crate::DisasmItem;
let mut sluce = self.output.code.as_slice(); let mut sluce = self.output.code.as_slice();
let functions = self let functions = self
@ -3280,20 +3282,15 @@ impl Codegen {
.map(|s| (s.range.start, ("string", s.range.len() as _, DisasmItem::Global))), .map(|s| (s.range.start, ("string", s.range.len() as _, DisasmItem::Global))),
) )
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
if crate::disasm(&mut sluce, &functions, output, |bin| { crate::disasm(&mut sluce, &functions, output, |bin| {
if self.ct.active() if self.ct.active()
&& let Some(trap) = Self::read_trap(bin.as_ptr() as u64) && let Some(trap) = Self::read_trap(bin.as_ptr() as u64)
{ {
bin.take(..trap.size() + 1).unwrap(); bin.take(..trap.size() + 1).unwrap();
} }
}) })
.is_err()
{
panic!("{} {:?}", output, sluce);
}
} }
#[cfg(test)]
fn is_fully_linked(&self, func: ty::Func) -> bool { fn is_fully_linked(&self, func: ty::Func) -> bool {
self.output self.output
.relocs .relocs
@ -3471,7 +3468,12 @@ mod tests {
let mut out = Vec::new(); let mut out = Vec::new();
codegen.dump(&mut out).unwrap(); codegen.dump(&mut out).unwrap();
codegen.disasm(output); let mut buf = Vec::<u8>::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; use std::fmt::Write;

View file

@ -135,27 +135,25 @@ fn decode<T>(binary: &mut &[u8]) -> Option<T> {
unsafe { Some(std::ptr::read(binary.take(..std::mem::size_of::<T>())?.as_ptr() as *const T)) } unsafe { Some(std::ptr::read(binary.take(..std::mem::size_of::<T>())?.as_ptr() as *const T)) }
} }
#[cfg(test)]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum DisasmItem { enum DisasmItem {
Func, Func,
Global, Global,
} }
#[cfg(test)]
fn disasm( fn disasm(
binary: &mut &[u8], binary: &mut &[u8],
functions: &HashMap<u32, (&str, u32, DisasmItem)>, functions: &HashMap<u32, (&str, u32, DisasmItem)>,
out: &mut String, out: &mut impl std::io::Write,
mut eca_handler: impl FnMut(&mut &[u8]), mut eca_handler: impl FnMut(&mut &[u8]),
) -> std::fmt::Result { ) -> std::io::Result<()> {
use self::instrs::Instr; use self::instrs::Instr;
fn instr_from_byte(b: u8) -> Result<Instr, std::fmt::Error> { fn instr_from_byte(b: u8) -> std::io::Result<Instr> {
if b as usize >= instrs::NAMES.len() { 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::<u8, Instr>(b) })
} }
let mut labels = HashMap::<u32, u32>::default(); let mut labels = HashMap::<u32, u32>::default();
@ -179,7 +177,7 @@ fn disasm(
if offset as u32 == off + len { if offset as u32 == off + len {
break; 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(..) { for op in buf.drain(..) {
let rel = match op { let rel = match op {
@ -211,18 +209,16 @@ fn disasm(
} }
let prev = *binary; let prev = *binary;
use std::fmt::Write;
writeln!(out, "{name}:")?; writeln!(out, "{name}:")?;
binary.take(..off as usize).unwrap(); binary.take(..off as usize).unwrap();
while let Some(&byte) = binary.first() { 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(); let offset: i32 = (prev.len() - binary.len()).try_into().unwrap();
if offset as u32 == off + len { if offset as u32 == off + len {
break; 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()) { if let Some(label) = labels.get(&offset.try_into().unwrap()) {
write!(out, "{:>2}: ", label)?; write!(out, "{:>2}: ", label)?;
@ -281,8 +277,12 @@ fn disasm(
*binary = prev; *binary = prev;
} }
if has_oob || has_cycle { if has_oob {
return Err(std::fmt::Error); return Err(std::io::ErrorKind::InvalidInput.into());
}
if has_cycle {
return Err(std::io::ErrorKind::TimedOut.into());
} }
Ok(()) Ok(())
@ -700,6 +700,7 @@ pub fn run_test(
pub struct Options { pub struct Options {
pub fmt: bool, pub fmt: bool,
pub fmt_current: bool, pub fmt_current: bool,
pub dump_asm: bool,
pub extra_threads: usize, pub extra_threads: usize,
} }
@ -752,13 +753,17 @@ pub fn run_compiler(
} else if options.fmt_current { } else if options.fmt_current {
let ast = parsed.into_iter().next().unwrap(); let ast = parsed.into_iter().next().unwrap();
let source = std::fs::read_to_string(&*ast.path)?; let source = std::fs::read_to_string(&*ast.path)?;
format_to(&ast, &source, &mut std::io::stdout())?; format_to(&ast, &source, out)?;
} else { } else {
let mut codegen = codegen::Codegen::default(); let mut codegen = codegen::Codegen::default();
codegen.files = parsed; codegen.files = parsed;
codegen.generate(); codegen.generate();
codegen.dump(out)?; if options.dump_asm {
codegen.disasm(out)?;
} else {
codegen.dump(out)?;
}
} }
Ok(()) Ok(())

View file

@ -15,6 +15,7 @@ fn main() -> std::io::Result<()> {
hblang::Options { hblang::Options {
fmt: args.contains(&"--fmt"), fmt: args.contains(&"--fmt"),
fmt_current: args.contains(&"--fmt-current"), fmt_current: args.contains(&"--fmt-current"),
dump_asm: args.contains(&"--dump-asm"),
extra_threads: args extra_threads: args
.iter() .iter()
.position(|&a| a == "--threads") .position(|&a| a == "--threads")

View file

@ -7,7 +7,7 @@ use {
log, log,
parser::{ parser::{
self, self,
idfl::{self, index}, idfl::{self},
Expr, ExprRef, FileId, Pos, Expr, ExprRef, FileId, Pos,
}, },
HashMap, HashMap,
@ -17,7 +17,6 @@ use {
mem, mem,
ops::{self, Range}, ops::{self, Range},
rc::Rc, rc::Rc,
usize,
}, },
}; };