diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index 00e2dcbe68..924c86b992 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -119,20 +119,23 @@ impl<'a> WasmBackend<'a> { fn finalize(&mut self, return_type: Option) -> FunctionDefinition { let mut final_instructions = Vec::with_capacity(self.instructions.len() + 10); - allocate_stack_frame( - &mut final_instructions, - self.stack_memory, - self.stack_frame_pointer, - ); + if self.stack_memory > 0 { + allocate_stack_frame( + &mut final_instructions, + self.stack_memory, + self.stack_frame_pointer.unwrap(), + ); + } final_instructions.extend(self.instructions.drain(0..)); - free_stack_frame( - &mut final_instructions, - self.stack_memory, - self.stack_frame_pointer, - ); - + if self.stack_memory > 0 { + free_stack_frame( + &mut final_instructions, + self.stack_memory, + self.stack_frame_pointer.unwrap(), + ); + } final_instructions.push(Instruction::End); let signature_builder = if let Some(t) = return_type { diff --git a/compiler/gen_wasm/src/lib.rs b/compiler/gen_wasm/src/lib.rs index 8a612572bf..d439fca3cc 100644 --- a/compiler/gen_wasm/src/lib.rs +++ b/compiler/gen_wasm/src/lib.rs @@ -23,6 +23,7 @@ pub const ALIGN_4: u32 = 2; pub const ALIGN_8: u32 = 3; pub const STACK_POINTER_GLOBAL_ID: u32 = 0; +pub const STACK_ALIGNMENT_BYTES: i32 = 16; #[derive(Clone, Copy, Debug)] pub struct LocalId(pub u32); @@ -156,38 +157,27 @@ fn copy_memory( pub fn allocate_stack_frame( instructions: &mut Vec, size: i32, - local_frame_pointer: Option, + local_frame_pointer: LocalId, ) { - if size == 0 { - return; - } - instructions.push(GetGlobal(STACK_POINTER_GLOBAL_ID)); - instructions.push(I32Const(size)); - instructions.push(I32Sub); - if let Some(LocalId(local_index)) = local_frame_pointer { - instructions.push(TeeLocal(local_index)); - } - instructions.push(SetGlobal(STACK_POINTER_GLOBAL_ID)); + let aligned_size = (size + STACK_ALIGNMENT_BYTES - 1) & (-STACK_ALIGNMENT_BYTES); + instructions.extend([ + GetGlobal(STACK_POINTER_GLOBAL_ID), + I32Const(aligned_size), + I32Sub, + TeeLocal(local_frame_pointer.0), + SetGlobal(STACK_POINTER_GLOBAL_ID), + ]); } pub fn free_stack_frame( instructions: &mut Vec, size: i32, - local_frame_pointer: Option, + local_frame_pointer: LocalId, ) { - if size == 0 { - return; - } - let get_stack_frame = - if let Some(LocalId(local_index)) = local_frame_pointer { - GetLocal(local_index) - } else { - GetGlobal(STACK_POINTER_GLOBAL_ID) - }; - + let aligned_size = (size + STACK_ALIGNMENT_BYTES - 1) & (-STACK_ALIGNMENT_BYTES); instructions.extend([ - get_stack_frame, - I32Const(size), + GetLocal(local_frame_pointer.0), + I32Const(aligned_size), I32Add, SetGlobal(STACK_POINTER_GLOBAL_ID), ]); diff --git a/compiler/gen_wasm/tests/helpers/wasm32_test_result.rs b/compiler/gen_wasm/tests/helpers/wasm32_test_result.rs index dd069ec0bb..a84bf48e89 100644 --- a/compiler/gen_wasm/tests/helpers/wasm32_test_result.rs +++ b/compiler/gen_wasm/tests/helpers/wasm32_test_result.rs @@ -44,12 +44,12 @@ pub trait Wasm32TestResult { macro_rules! build_wrapper_body_primitive { ($store_instruction: expr, $align: expr) => { fn build_wrapper_body(main_function_index: u32) -> Vec { - const MAX_ALIGNED_SIZE: i32 = 16; + let size: i32 = 8; let mut instructions = Vec::with_capacity(16); allocate_stack_frame( &mut instructions, - MAX_ALIGNED_SIZE, - Some(LocalId(STACK_POINTER_LOCAL_ID)), + size, + LocalId(STACK_POINTER_LOCAL_ID), ); instructions.extend([ // load result address to prepare for the store instruction later @@ -66,8 +66,8 @@ macro_rules! build_wrapper_body_primitive { ]); free_stack_frame( &mut instructions, - MAX_ALIGNED_SIZE, - Some(LocalId(STACK_POINTER_LOCAL_ID)), + size, + LocalId(STACK_POINTER_LOCAL_ID), ); instructions.push(End); instructions @@ -88,7 +88,7 @@ fn build_wrapper_body_stack_memory(main_function_index: u32, size: usize) -> Vec allocate_stack_frame( &mut instructions, size as i32, - Some(LocalId(STACK_POINTER_LOCAL_ID)), + LocalId(STACK_POINTER_LOCAL_ID), ); instructions.extend([ // @@ -98,12 +98,12 @@ fn build_wrapper_body_stack_memory(main_function_index: u32, size: usize) -> Vec Call(main_function_index), // // Return the result address - GetGlobal(STACK_POINTER_GLOBAL_ID), + GetLocal(STACK_POINTER_LOCAL_ID), ]); free_stack_frame( &mut instructions, size as i32, - Some(LocalId(STACK_POINTER_LOCAL_ID)), + LocalId(STACK_POINTER_LOCAL_ID), ); instructions.push(End); instructions