feat(codegen): stack under/overflow guards in compiled words (WS-007)
Compiled code could silently move dsp/rsp/fsp out of their stack regions (e.g. DROP on an empty stack), corrupting later pushes with no diagnostic -- the addresses stay inside valid linear memory, so nothing could trap. Host-side checks cannot catch it. - Guards are emitted at the sp-adjustment choke points (dsp_inc/ dsp_dec, fsp_inc/fsp_dec, rpush/rpop/rpeek, peek, TwoDup/TwoDrop, promoted prologue/epilogue -- DROP never loads its value, so guarding pop() alone is not enough). On fault: write the code to SYSVAR_FAULT_CODE, call _STACK_FAULT_, which THROWs it -- so guards are CATCHable and print standard messages (-3/-4/-5/-6/ -44/-45). - The batch/consolidated compile path (all boot primitives) and the export path are wired too; a thread-local carries the fault index into the shared emission helpers. - Config: codegen.stack_guards, default ON. `wafer build` output defaults OFF (production artifact); WAFER_STACK_GUARDS=0|1 overrides either. Perf comparison lanes run unguarded. - Measured overhead in release loops: within noise (never-taken branches). - toolstest.fth baseline 37 -> 38: line 368's bare interpreted `R>` used to underflow silently and count as passing; the guard now correctly reports -6.
This commit is contained in:
@@ -120,8 +120,14 @@ pub fn export_module(
|
||||
metadata_json: metadata_json.as_bytes(),
|
||||
};
|
||||
|
||||
let wasm_bytes = compile_exportable_module(&words, &local_fn_map, table_size, &export_sections)
|
||||
.map_err(|e| anyhow::anyhow!("export codegen error: {e}"))?;
|
||||
let wasm_bytes = compile_exportable_module(
|
||||
&words,
|
||||
&local_fn_map,
|
||||
table_size,
|
||||
&export_sections,
|
||||
vm.stack_guard_param(),
|
||||
)
|
||||
.map_err(|e| anyhow::anyhow!("export codegen error: {e}"))?;
|
||||
|
||||
Ok((wasm_bytes, metadata))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user