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:
@@ -21,7 +21,7 @@ mod tests {
|
||||
// Empty word list should produce nothing (but we guard against this at call site)
|
||||
let words = vec![];
|
||||
let map = HashMap::new();
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
// Empty is valid -- should produce a valid module with no functions
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@@ -31,7 +31,7 @@ mod tests {
|
||||
let words = vec![(WordId(1), vec![IrOp::PushI32(42)])];
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(1), 1u32); // function index 1 (after emit import)
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ mod tests {
|
||||
map.insert(WordId(1), 1u32);
|
||||
map.insert(WordId(2), 2u32);
|
||||
map.insert(WordId(3), 3u32);
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ mod tests {
|
||||
let words = vec![(WordId(3), vec![IrOp::Call(WordId(99))])];
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(3), 1u32);
|
||||
let result = compile_consolidated_module(&words, &map, 256);
|
||||
let result = compile_consolidated_module(&words, &map, 256, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ mod tests {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(1), 1u32);
|
||||
map.insert(WordId(2), 2u32);
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ mod tests {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(1), 1u32);
|
||||
map.insert(WordId(2), 2u32);
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ mod tests {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(1), 1u32);
|
||||
map.insert(WordId(2), 2u32);
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -141,7 +141,7 @@ mod tests {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(1), 1u32);
|
||||
map.insert(WordId(2), 2u32);
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ mod tests {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(WordId(1), 1u32);
|
||||
map.insert(WordId(2), 2u32);
|
||||
let result = compile_consolidated_module(&words, &map, 16);
|
||||
let result = compile_consolidated_module(&words, &map, 16, None);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user