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)]
{
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();
@ -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::<HashMap<_, _>>();
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::<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;

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)) }
}
#[cfg(test)]
#[derive(Clone, Copy)]
enum DisasmItem {
Func,
Global,
}
#[cfg(test)]
fn disasm(
binary: &mut &[u8],
functions: &HashMap<u32, (&str, u32, DisasmItem)>,
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<Instr, std::fmt::Error> {
fn instr_from_byte(b: u8) -> std::io::Result<Instr> {
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();
@ -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(())

View file

@ -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")

View file

@ -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,
},
};