wasm_interp: implement select instruction

This commit is contained in:
Brian Carroll 2022-11-27 09:23:28 +00:00
parent 9e7a92574d
commit ae2e561945
No known key found for this signature in database
GPG key ID: 5C7B2EC4101703C0
2 changed files with 63 additions and 3 deletions

View file

@ -418,7 +418,14 @@ impl<'a> ExecutionState<'a> {
DROP => {
self.value_stack.pop();
}
SELECT => todo!("{:?} @ {:#x}", op_code, file_offset),
SELECT => {
let c = self.value_stack.pop_i32();
let val2 = self.value_stack.pop();
let val1 = self.value_stack.pop();
assert_eq!(ValueType::from(val1), ValueType::from(val2));
let result = if c != 0 { val1 } else { val2 };
self.value_stack.push(result);
}
GETLOCAL => {
let index = self.fetch_immediate_u32(module);
let value = self.call_stack.get_local(index);

View file

@ -16,6 +16,28 @@ fn default_state(arena: &Bump) -> ExecutionState {
ExecutionState::new(arena, pages, program_counter, globals)
}
fn const_value(buf: &mut Vec<'_, u8>, value: Value) {
use Value::*;
match value {
I32(x) => {
buf.push(OpCode::I32CONST as u8);
buf.encode_i32(x);
}
I64(x) => {
buf.push(OpCode::I64CONST as u8);
buf.encode_i64(x);
}
F32(x) => {
buf.push(OpCode::F32CONST as u8);
buf.encode_f32(x);
}
F64(x) => {
buf.push(OpCode::F64CONST as u8);
buf.encode_f64(x);
}
}
}
#[test]
fn test_loop() {
test_loop_help(10, 55);
@ -672,8 +694,39 @@ fn test_call_indirect_help(table_index: u32, elem_index: u32) -> Value {
// #[test]
// fn test_drop() {}
// #[test]
// fn test_select() {}
#[test]
fn test_select() {
test_select_help(Value::F32(1.11), Value::F32(2.22), -100, Value::F32(1.11));
test_select_help(Value::F64(1.11), Value::F64(2.22), 0, Value::F64(2.22));
}
fn test_select_help(first: Value, second: Value, condition: i32, expected: Value) {
let arena = Bump::new();
let mut module = WasmModule::new(&arena);
let buf = &mut module.code.bytes;
buf.push(0); // no locals
const_value(buf, first);
const_value(buf, second);
const_value(buf, Value::I32(condition));
buf.push(OpCode::SELECT as u8);
buf.push(OpCode::END as u8);
let mut state = default_state(&arena);
state.call_stack.push_frame(
0,
0,
&[],
&mut state.value_stack,
&module.code.bytes,
&mut state.program_counter,
);
while let Action::Continue = state.execute_next_instruction(&module) {}
assert_eq!(state.value_stack.pop(), expected);
}
#[test]
fn test_set_get_local() {