mirror of
https://github.com/imjasonh/nescript
synced 2026-07-08 17:06:04 +00:00
tooling: add --no-opt CLI flag and criterion compile benchmarks
Adds two items from the "Code quality / tooling" section of docs/future-work.md. Both make it easier to chase regressions without touching codegen. - `nescript build --no-opt` skips the IR optimizer pass so optimizer-introduced miscompiles can be bisected against the unoptimized output. Threaded through CompileOptions and gated at the single optimizer call site in src/main.rs. Covered by a new integration test that compiles the same program twice (opt on / opt off) and asserts both outputs are valid iNES ROMs with matching headers and reset vectors. - A criterion-based `benches/compile.rs` harness that times the full parse -> analyze -> lower -> optimize -> codegen -> link pipeline on every examples/*.ne file. Sources are pre-read into memory so file I/O stays off the hot loop, and each example gets its own Criterion group for easy regression spotting. Committed ROM bytes under examples/*.nes are unchanged; the emulator goldens under tests/emulator/goldens/ are untouched.
This commit is contained in:
parent
d2cfce595b
commit
65a63f9a68
5 changed files with 740 additions and 2 deletions
19
src/main.rs
19
src/main.rs
|
|
@ -42,6 +42,13 @@ enum Cli {
|
|||
/// Dump a call graph showing which functions call which.
|
||||
#[arg(long)]
|
||||
call_graph: bool,
|
||||
|
||||
/// Skip the IR optimizer pass. Useful for bisecting
|
||||
/// optimizer-introduced miscompiles: if a program misbehaves
|
||||
/// with the optimizer on but works with `--no-opt`, the bug
|
||||
/// lives in `src/optimizer/`.
|
||||
#[arg(long)]
|
||||
no_opt: bool,
|
||||
},
|
||||
/// Type-check a source file without building
|
||||
Check {
|
||||
|
|
@ -62,6 +69,7 @@ fn main() {
|
|||
dump_ir,
|
||||
memory_map,
|
||||
call_graph,
|
||||
no_opt,
|
||||
} => {
|
||||
let output = output.unwrap_or_else(|| input.with_extension("nes"));
|
||||
match compile(
|
||||
|
|
@ -72,6 +80,7 @@ fn main() {
|
|||
dump_ir,
|
||||
memory_map,
|
||||
call_graph,
|
||||
no_opt,
|
||||
},
|
||||
) {
|
||||
Ok(rom) => {
|
||||
|
|
@ -220,6 +229,7 @@ struct CompileOptions {
|
|||
dump_ir: bool,
|
||||
memory_map: bool,
|
||||
call_graph: bool,
|
||||
no_opt: bool,
|
||||
}
|
||||
|
||||
fn compile(input: &PathBuf, opts: &CompileOptions) -> Result<Vec<u8>, ()> {
|
||||
|
|
@ -228,6 +238,7 @@ fn compile(input: &PathBuf, opts: &CompileOptions) -> Result<Vec<u8>, ()> {
|
|||
let dump_ir = opts.dump_ir;
|
||||
let memory_map = opts.memory_map;
|
||||
let call_graph = opts.call_graph;
|
||||
let no_opt = opts.no_opt;
|
||||
let raw_source = std::fs::read_to_string(input).map_err(|e| {
|
||||
eprintln!("error: failed to read {}: {e}", input.display());
|
||||
})?;
|
||||
|
|
@ -265,9 +276,13 @@ fn compile(input: &PathBuf, opts: &CompileOptions) -> Result<Vec<u8>, ()> {
|
|||
return Err(());
|
||||
}
|
||||
|
||||
// IR lowering and optimization
|
||||
// IR lowering and (optionally) optimization. `--no-opt` skips
|
||||
// the IR optimizer pass entirely so optimizer-introduced
|
||||
// miscompiles can be bisected against the unoptimized output.
|
||||
let mut ir_program = ir::lower(&program, &analysis);
|
||||
optimizer::optimize(&mut ir_program);
|
||||
if !no_opt {
|
||||
optimizer::optimize(&mut ir_program);
|
||||
}
|
||||
|
||||
if dump_ir {
|
||||
print!("{}", ir_program.pretty());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue