From 335497c99f97a29f92d1dba82d5b47d34c3fe207 Mon Sep 17 00:00:00 2001 From: Brian Carroll Date: Mon, 21 Nov 2022 23:47:09 +0000 Subject: [PATCH] wasm_interp: implement globals --- crates/wasm_interp/src/execute.rs | 15 +++++-- crates/wasm_interp/tests/test_opcodes.rs | 55 ++++++++++++++++-------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/crates/wasm_interp/src/execute.rs b/crates/wasm_interp/src/execute.rs index 1910b61260..e0b6e91bd2 100644 --- a/crates/wasm_interp/src/execute.rs +++ b/crates/wasm_interp/src/execute.rs @@ -17,16 +17,23 @@ pub struct ExecutionState<'a> { pub call_stack: CallStack<'a>, pub value_stack: ValueStack<'a>, + + pub globals: Vec<'a, Value>, + program_counter: usize, } impl<'a> ExecutionState<'a> { - pub fn new(arena: &'a Bump, memory_pages: u32, program_counter: usize) -> Self { + pub fn new(arena: &'a Bump, memory_pages: u32, program_counter: usize, globals: G) -> Self + where + G: IntoIterator, + { let mem_bytes = memory_pages * MemorySection::PAGE_SIZE; ExecutionState { memory: Vec::with_capacity_in(mem_bytes as usize, arena), call_stack: CallStack::new(arena), value_stack: ValueStack::new(arena), + globals: Vec::from_iter_in(globals, arena), program_counter, } } @@ -101,10 +108,12 @@ impl<'a> ExecutionState<'a> { self.call_stack.set_local(index, value); } GETGLOBAL => { - todo!("{:?}", op_code); + let index = self.fetch_immediate_u32(module); + self.value_stack.push(self.globals[index as usize]); } SETGLOBAL => { - todo!("{:?}", op_code); + let index = self.fetch_immediate_u32(module); + self.globals[index as usize] = self.value_stack.pop(); } I32LOAD => { todo!("{:?}", op_code); diff --git a/crates/wasm_interp/tests/test_opcodes.rs b/crates/wasm_interp/tests/test_opcodes.rs index 30f0d35c9f..0710e69ed7 100644 --- a/crates/wasm_interp/tests/test_opcodes.rs +++ b/crates/wasm_interp/tests/test_opcodes.rs @@ -7,12 +7,6 @@ use roc_wasm_module::{opcodes::OpCode, SerialBuffer, ValueType, WasmModule}; const DEFAULT_MEMORY_PAGES: u32 = 1; const DEFAULT_PROGRAM_COUNTER: usize = 0; -// #[test] -// fn test_unreachable() {} - -// #[test] -// fn test_nop() {} - // #[test] // fn test_block() {} @@ -55,7 +49,7 @@ const DEFAULT_PROGRAM_COUNTER: usize = 0; #[test] fn test_set_get_local() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); let local_decls = [ @@ -84,7 +78,7 @@ fn test_set_get_local() { #[test] fn test_tee_get_local() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); let local_decls = [ @@ -111,11 +105,34 @@ fn test_tee_get_local() { assert_eq!(state.value_stack.pop(), Value::I32(12345)); } -// #[test] -// fn test_getglobal() {} +#[test] +fn test_global() { + let arena = Bump::new(); + let mut state = ExecutionState::new( + &arena, + DEFAULT_MEMORY_PAGES, + DEFAULT_PROGRAM_COUNTER, + [Value::F64(1.11), Value::I32(222), Value::F64(3.33)], + ); + let mut module = WasmModule::new(&arena); -// #[test] -// fn test_setglobal() {} + module.code.bytes.push(OpCode::GETGLOBAL as u8); + module.code.bytes.encode_u32(1); + module.code.bytes.push(OpCode::I32CONST as u8); + module.code.bytes.encode_i32(555); + module.code.bytes.push(OpCode::SETGLOBAL as u8); + module.code.bytes.encode_u32(1); + module.code.bytes.push(OpCode::GETGLOBAL as u8); + module.code.bytes.encode_u32(1); + + state.execute_next_instruction(&module); + 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(555)); + assert_eq!(state.value_stack.pop(), Value::I32(222)); +} // #[test] // fn test_i32load() {} @@ -195,7 +212,7 @@ fn test_tee_get_local() { #[test] fn test_i32const() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::I32CONST as u8); @@ -208,7 +225,7 @@ fn test_i32const() { #[test] fn test_i64const() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::I64CONST as u8); @@ -221,7 +238,7 @@ fn test_i64const() { #[test] fn test_f32const() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::F32CONST as u8); @@ -234,7 +251,7 @@ fn test_f32const() { #[test] fn test_f64const() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::F64CONST as u8); @@ -358,7 +375,7 @@ fn test_f64const() { #[test] fn test_i32add() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::I32CONST as u8); @@ -376,7 +393,7 @@ fn test_i32add() { #[test] fn test_i32sub() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::I32CONST as u8); @@ -394,7 +411,7 @@ fn test_i32sub() { #[test] fn test_i32mul() { let arena = Bump::new(); - let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER); + let mut state = ExecutionState::new(&arena, DEFAULT_MEMORY_PAGES, DEFAULT_PROGRAM_COUNTER, []); let mut module = WasmModule::new(&arena); module.code.bytes.push(OpCode::I32CONST as u8);