This commit is contained in:
bQUARKz 2026-02-20 04:55:00 +00:00
parent 155be962b7
commit b57e186490
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 84 additions and 45 deletions

View File

@ -0,0 +1,55 @@
//! Deterministic tests for multi-return syscalls with the slot-based ABI.
use prometeu_bytecode::isa::core::CoreOpCode as OpCode;
use prometeu_bytecode::{FunctionMeta, Value};
use prometeu_vm::{HostContext, HostReturn, NativeInterface, VirtualMachine};
use prometeu_hal::vm_fault::VmFault;
fn enc_op(op: OpCode) -> [u8; 2] { (op as u16).to_le_bytes() }
#[test]
fn vm_syscall_multi_return_stack_contents() {
// Use a real multi-return syscall id with ret_slots = 4: PadGetUp (0x2200)
// ROM: SYSCALL 0x2200; HALT
let mut rom = Vec::new();
rom.extend_from_slice(&enc_op(OpCode::Syscall));
rom.extend_from_slice(&0x2200u32.to_le_bytes());
rom.extend_from_slice(&enc_op(OpCode::Halt));
struct TestNative;
impl NativeInterface for TestNative {
fn syscall(
&mut self,
id: u32,
_args: &[Value],
ret: &mut HostReturn,
_ctx: &mut HostContext,
) -> Result<(), VmFault> {
assert_eq!(id, 0x2200);
// Push exactly 4 results in a known order.
ret.push_int(11);
ret.push_int(22);
ret.push_bool(true);
ret.push_bounded(7)?;
Ok(())
}
}
let mut vm = VirtualMachine::new(rom.clone(), vec![]);
vm.program.functions = std::sync::Arc::from(vec![FunctionMeta {
code_offset: 0,
code_len: rom.len() as u32,
..Default::default()
}]);
let mut native = TestNative;
let mut ctx = HostContext::new(None);
vm.prepare_call("0");
let _ = vm.run_budget(100, &mut native, &mut ctx).expect("VM run failed");
// Verify stack order: last pushed is on top
assert_eq!(vm.pop().unwrap(), Value::Bounded(7));
assert_eq!(vm.pop().unwrap(), Value::Boolean(true));
assert_eq!(vm.pop().unwrap(), Value::Int64(22));
assert_eq!(vm.pop().unwrap(), Value::Int64(11));
assert!(vm.operand_stack.is_empty());
}

View File

@ -269,6 +269,35 @@ fn golden_ok_syscall_args_and_returns() {
assert!(res_b[0] >= 1);
}
#[test]
fn golden_ok_syscall_multi_returns() {
// Syscall with 0 args and 4 returns: PadGetUp (0x2200)
// Program: SYSCALL 0x2200; RET (ret_slots = 4)
let mut code = Vec::new();
code.extend_from_slice(&enc_op(OpCode::Syscall));
code.extend_from_slice(&0x2200u32.to_le_bytes()); // PadGetUp: 0 args, 4 returns
code.extend_from_slice(&enc_op(OpCode::Ret));
let functions = func(FunctionMeta { code_offset: 0, code_len: code.len() as u32, return_slots: 4, ..Default::default() });
let res = Verifier::verify(&code, &functions).unwrap();
// Max stack height should reach at least 4 due to the syscall's return values
assert!(res[0] >= 4);
}
#[test]
fn golden_err_syscall_multi_returns_mismatch() {
// Same syscall (PadGetUp: returns 4), but function declares only 3 return slots.
// Program: SYSCALL 0x2200; RET (ret_slots = 3) → verifier must reject due to BadRetStackHeight.
let mut code = Vec::new();
code.extend_from_slice(&enc_op(OpCode::Syscall));
code.extend_from_slice(&0x2200u32.to_le_bytes());
code.extend_from_slice(&enc_op(OpCode::Ret));
let functions = func(FunctionMeta { code_offset: 0, code_len: code.len() as u32, return_slots: 3, ..Default::default() });
let res = Verifier::verify(&code, &functions);
assert_eq!(res, Err(VerifierError::BadRetStackHeight { pc: 6, height: 4, expected: 3 }));
}
#[test]
fn golden_err_invalid_func_id() {
// Encode a Call with invalid function id (beyond functions.len())

View File

@ -1,45 +0,0 @@
# PR-5.6 — Syscall Multi-Return Tests
### Briefing
We must ensure multi-return syscalls behave correctly with the slot-based ABI.
### Target
* Add deterministic tests covering multi-return behavior.
### Work items
* Create or adapt at least one syscall with `ret_slots > 1`.
* Add tests:
* Verify correct stack results after syscall.
* Verify incorrect caller expectations fail verification.
### Acceptance checklist
* [ ] Multi-return syscalls behave correctly.
* [ ] Verifier catches mismatches.
* [ ] `cargo test` passes.
### Tests
* New multi-return syscall tests.
### Junie instructions
**You MAY:**
* Add deterministic tests.
* Use existing syscalls or create a simple test-only syscall.
**You MUST NOT:**
* Modify syscall semantics to satisfy tests.
* Add nondeterministic behavior.
**If unclear:**
* Ask before introducing new test syscalls.