feat(tvix/eval): implement DisassemblingObserver for compiler
This type implements an observer that is called whenever the compiler emits a chunk (after the toplevel, thunks, or lambdas) and prints the output of the disassembler to its internal writer. This replaces half of the uses of the `disassembler` feature, which has been removed from the Cargo configuration. Note that at this commit runtime tracing is not yet implemented as an observer. Change-Id: I7894ca1ba445761aba4ad51d98e4a7b6445f1aea Reviewed-on: https://cl.tvl.fyi/c/depot/+/6449 Reviewed-by: sterni <sternenseemann@systemli.org> Tested-by: BuildkiteCI
This commit is contained in:
parent
7ae45342df
commit
8ee4d6d5db
7 changed files with 111 additions and 98 deletions
|
|
@ -4,9 +4,15 @@
|
|||
//! This can be used to gain insights from compilation, to trace the
|
||||
//! runtime, and so on.
|
||||
|
||||
use crate::value::Lambda;
|
||||
|
||||
use codemap::CodeMap;
|
||||
use std::io::Write;
|
||||
use std::rc::Rc;
|
||||
use tabwriter::TabWriter;
|
||||
|
||||
use crate::chunk::Chunk;
|
||||
use crate::disassembler::disassemble_op;
|
||||
use crate::opcode::CodeIdx;
|
||||
use crate::value::Lambda;
|
||||
|
||||
/// Implemented by types that wish to observe internal happenings of
|
||||
/// Tvix.
|
||||
|
|
@ -34,3 +40,59 @@ pub trait Observer {
|
|||
pub struct NoOpObserver {}
|
||||
|
||||
impl Observer for NoOpObserver {}
|
||||
|
||||
/// An observer that prints disassembled chunk information to its
|
||||
/// internal writer whenwever the compiler emits a toplevel function,
|
||||
/// closure or thunk.
|
||||
pub struct DisassemblingObserver<W: Write> {
|
||||
codemap: Rc<CodeMap>,
|
||||
writer: TabWriter<W>,
|
||||
}
|
||||
|
||||
impl<W: Write> DisassemblingObserver<W> {
|
||||
pub fn new(codemap: Rc<CodeMap>, writer: W) -> Self {
|
||||
Self {
|
||||
codemap,
|
||||
writer: TabWriter::new(writer),
|
||||
}
|
||||
}
|
||||
|
||||
fn lambda_header(&mut self, kind: &str, lambda: &Rc<Lambda>) {
|
||||
let _ = writeln!(
|
||||
&mut self.writer,
|
||||
"=== compiled {} @ {:p} ({} ops) ===",
|
||||
kind,
|
||||
lambda,
|
||||
lambda.chunk.code.len()
|
||||
);
|
||||
}
|
||||
|
||||
fn disassemble_chunk(&mut self, chunk: &Chunk) {
|
||||
// calculate width of the widest address in the chunk
|
||||
let width = format!("{:#x}", chunk.code.len() - 1).len();
|
||||
|
||||
for (idx, _) in chunk.code.iter().enumerate() {
|
||||
disassemble_op(&mut self.writer, &self.codemap, chunk, width, CodeIdx(idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Observer for DisassemblingObserver<W> {
|
||||
fn observe_compiled_toplevel(&mut self, lambda: &Rc<Lambda>) {
|
||||
self.lambda_header("toplevel", lambda);
|
||||
self.disassemble_chunk(&lambda.chunk);
|
||||
let _ = self.writer.flush();
|
||||
}
|
||||
|
||||
fn observe_compiled_lambda(&mut self, lambda: &Rc<Lambda>) {
|
||||
self.lambda_header("lambda", lambda);
|
||||
self.disassemble_chunk(&lambda.chunk);
|
||||
let _ = self.writer.flush();
|
||||
}
|
||||
|
||||
fn observe_compiled_thunk(&mut self, lambda: &Rc<Lambda>) {
|
||||
self.lambda_header("thunk", lambda);
|
||||
self.disassemble_chunk(&lambda.chunk);
|
||||
let _ = self.writer.flush();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue