mirror of
https://github.com/roc-lang/roc.git
synced 2024-09-21 15:59:20 +03:00
wasm_interp: implement local.get, local.set, and local.tee
This commit is contained in:
parent
987fcf616e
commit
ff63831fd1
@ -14,7 +14,7 @@ pub struct ExecutionState<'a> {
|
||||
memory: Vec<'a, u8>,
|
||||
|
||||
#[allow(dead_code)]
|
||||
call_stack: CallStack<'a>,
|
||||
pub call_stack: CallStack<'a>,
|
||||
|
||||
pub value_stack: ValueStack<'a>,
|
||||
program_counter: usize,
|
||||
@ -31,6 +31,10 @@ impl<'a> ExecutionState<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fetch_immediate_u32(&mut self, module: &WasmModule<'a>) -> u32 {
|
||||
u32::parse((), &module.code.bytes, &mut self.program_counter).unwrap()
|
||||
}
|
||||
|
||||
pub fn execute_next_instruction(&mut self, module: &WasmModule<'a>) {
|
||||
use OpCode::*;
|
||||
|
||||
@ -82,13 +86,19 @@ impl<'a> ExecutionState<'a> {
|
||||
todo!("{:?}", op_code);
|
||||
}
|
||||
GETLOCAL => {
|
||||
todo!("{:?}", op_code);
|
||||
let index = self.fetch_immediate_u32(module);
|
||||
let value = self.call_stack.get_local(index);
|
||||
self.value_stack.push(value);
|
||||
}
|
||||
SETLOCAL => {
|
||||
todo!("{:?}", op_code);
|
||||
let index = self.fetch_immediate_u32(module);
|
||||
let value = self.value_stack.pop();
|
||||
self.call_stack.set_local(index, value);
|
||||
}
|
||||
TEELOCAL => {
|
||||
todo!("{:?}", op_code);
|
||||
let index = self.fetch_immediate_u32(module);
|
||||
let value = self.value_stack.peek();
|
||||
self.call_stack.set_local(index, value);
|
||||
}
|
||||
GETGLOBAL => {
|
||||
todo!("{:?}", op_code);
|
||||
|
@ -34,6 +34,10 @@ impl<'a> ValueStack<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.is_64.len()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: Value) {
|
||||
match value {
|
||||
Value::I32(x) => {
|
||||
@ -69,6 +73,14 @@ impl<'a> ValueStack<'a> {
|
||||
value
|
||||
}
|
||||
|
||||
pub fn peek(&self) -> Value {
|
||||
let is_64 = self.is_64[self.is_64.len() - 1];
|
||||
let is_float = self.is_float[self.is_float.len() - 1];
|
||||
let size = if is_64 { 8 } else { 4 };
|
||||
let bytes_idx = self.bytes.len() - size;
|
||||
self.get(is_64, is_float, bytes_idx)
|
||||
}
|
||||
|
||||
fn get(&self, is_64: bool, is_float: bool, bytes_idx: usize) -> Value {
|
||||
if is_64 {
|
||||
let mut b = [0; 8];
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use bumpalo::Bump;
|
||||
use roc_wasm_interp::{ExecutionState, Value};
|
||||
use roc_wasm_module::{opcodes::OpCode, SerialBuffer, WasmModule};
|
||||
use roc_wasm_module::{opcodes::OpCode, SerialBuffer, ValueType, WasmModule};
|
||||
|
||||
const DEFAULT_MEMORY_PAGES: u32 = 1;
|
||||
const DEFAULT_PROGRAM_COUNTER: usize = 0;
|
||||
@ -52,14 +52,64 @@ const DEFAULT_PROGRAM_COUNTER: usize = 0;
|
||||
// #[test]
|
||||
// fn test_select() {}
|
||||
|
||||
// #[test]
|
||||
// fn test_getlocal() {}
|
||||
#[test]
|
||||
fn test_set_get_local() {
|
||||
let arena = Bump::new();
|
||||
let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER);
|
||||
let mut module = WasmModule::new(&arena);
|
||||
|
||||
// #[test]
|
||||
// fn test_setlocal() {}
|
||||
let local_decls = [
|
||||
(1, ValueType::F32),
|
||||
(1, ValueType::F64),
|
||||
(1, ValueType::I32),
|
||||
(1, ValueType::I64),
|
||||
];
|
||||
state.call_stack.push_frame(0x1234, &local_decls);
|
||||
|
||||
// #[test]
|
||||
// fn test_teelocal() {}
|
||||
module.code.bytes.push(OpCode::I32CONST as u8);
|
||||
module.code.bytes.encode_i32(12345);
|
||||
module.code.bytes.push(OpCode::SETLOCAL as u8);
|
||||
module.code.bytes.encode_u32(2);
|
||||
|
||||
module.code.bytes.push(OpCode::GETLOCAL as u8);
|
||||
module.code.bytes.encode_u32(2);
|
||||
|
||||
state.execute_next_instruction(&module);
|
||||
state.execute_next_instruction(&module);
|
||||
state.execute_next_instruction(&module);
|
||||
assert_eq!(state.value_stack.len(), 1);
|
||||
assert_eq!(state.value_stack.pop(), Value::I32(12345));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tee_get_local() {
|
||||
let arena = Bump::new();
|
||||
let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER);
|
||||
let mut module = WasmModule::new(&arena);
|
||||
|
||||
let local_decls = [
|
||||
(1, ValueType::F32),
|
||||
(1, ValueType::F64),
|
||||
(1, ValueType::I32),
|
||||
(1, ValueType::I64),
|
||||
];
|
||||
state.call_stack.push_frame(0x1234, &local_decls);
|
||||
|
||||
module.code.bytes.push(OpCode::I32CONST as u8);
|
||||
module.code.bytes.encode_i32(12345);
|
||||
module.code.bytes.push(OpCode::TEELOCAL as u8);
|
||||
module.code.bytes.encode_u32(2);
|
||||
|
||||
module.code.bytes.push(OpCode::GETLOCAL as u8);
|
||||
module.code.bytes.encode_u32(2);
|
||||
|
||||
state.execute_next_instruction(&module);
|
||||
state.execute_next_instruction(&module);
|
||||
state.execute_next_instruction(&module);
|
||||
assert_eq!(state.value_stack.len(), 2);
|
||||
assert_eq!(state.value_stack.pop(), Value::I32(12345));
|
||||
assert_eq!(state.value_stack.pop(), Value::I32(12345));
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_getglobal() {}
|
||||
|
Loading…
Reference in New Issue
Block a user