mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
wasm_interp: implement local.get, local.set, and local.tee
This commit is contained in:
parent
987fcf616e
commit
ff63831fd1
3 changed files with 83 additions and 11 deletions
|
@ -14,7 +14,7 @@ pub struct ExecutionState<'a> {
|
||||||
memory: Vec<'a, u8>,
|
memory: Vec<'a, u8>,
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
call_stack: CallStack<'a>,
|
pub call_stack: CallStack<'a>,
|
||||||
|
|
||||||
pub value_stack: ValueStack<'a>,
|
pub value_stack: ValueStack<'a>,
|
||||||
program_counter: usize,
|
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>) {
|
pub fn execute_next_instruction(&mut self, module: &WasmModule<'a>) {
|
||||||
use OpCode::*;
|
use OpCode::*;
|
||||||
|
|
||||||
|
@ -82,13 +86,19 @@ impl<'a> ExecutionState<'a> {
|
||||||
todo!("{:?}", op_code);
|
todo!("{:?}", op_code);
|
||||||
}
|
}
|
||||||
GETLOCAL => {
|
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 => {
|
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 => {
|
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 => {
|
GETGLOBAL => {
|
||||||
todo!("{:?}", op_code);
|
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) {
|
pub fn push(&mut self, value: Value) {
|
||||||
match value {
|
match value {
|
||||||
Value::I32(x) => {
|
Value::I32(x) => {
|
||||||
|
@ -69,6 +73,14 @@ impl<'a> ValueStack<'a> {
|
||||||
value
|
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 {
|
fn get(&self, is_64: bool, is_float: bool, bytes_idx: usize) -> Value {
|
||||||
if is_64 {
|
if is_64 {
|
||||||
let mut b = [0; 8];
|
let mut b = [0; 8];
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use roc_wasm_interp::{ExecutionState, Value};
|
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_MEMORY_PAGES: u32 = 1;
|
||||||
const DEFAULT_PROGRAM_COUNTER: usize = 0;
|
const DEFAULT_PROGRAM_COUNTER: usize = 0;
|
||||||
|
@ -52,14 +52,64 @@ const DEFAULT_PROGRAM_COUNTER: usize = 0;
|
||||||
// #[test]
|
// #[test]
|
||||||
// fn test_select() {}
|
// fn test_select() {}
|
||||||
|
|
||||||
// #[test]
|
#[test]
|
||||||
// fn test_getlocal() {}
|
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]
|
let local_decls = [
|
||||||
// fn test_setlocal() {}
|
(1, ValueType::F32),
|
||||||
|
(1, ValueType::F64),
|
||||||
|
(1, ValueType::I32),
|
||||||
|
(1, ValueType::I64),
|
||||||
|
];
|
||||||
|
state.call_stack.push_frame(0x1234, &local_decls);
|
||||||
|
|
||||||
// #[test]
|
module.code.bytes.push(OpCode::I32CONST as u8);
|
||||||
// fn test_teelocal() {}
|
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]
|
// #[test]
|
||||||
// fn test_getglobal() {}
|
// fn test_getglobal() {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue