From 6aed70978d51d8127b95fe2f85bff03443c94d9c Mon Sep 17 00:00:00 2001 From: Brian Carroll Date: Sat, 2 Oct 2021 16:15:06 +0100 Subject: [PATCH] Refactor SymbolStorage into two enums instead of one --- compiler/gen_wasm/src/backend.rs | 119 ++++++++++++------------------- compiler/gen_wasm/src/storage.rs | 108 ++++++++-------------------- 2 files changed, 78 insertions(+), 149 deletions(-) diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index 1f028660d4..b9c6cd6900 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -11,7 +11,7 @@ use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt}; use roc_mono::layout::{Builtin, Layout}; use crate::layout::WasmLayout; -use crate::storage::SymbolStorage; +use crate::storage::{StackMemoryLocation, SymbolStorage}; use crate::{ pop_stack_frame, push_stack_frame, round_up_to_alignment, LocalId, MemoryCopy, PTR_SIZE, PTR_TYPE, @@ -167,68 +167,55 @@ impl<'a> WasmBackend<'a> { ) -> SymbolStorage { let next_local_id = LocalId((self.arg_types.len() + self.locals.len()) as u32); - let storage = match kind { + match kind { LocalKind::Parameter => { - // Already stack-allocated by the caller if needed. self.arg_types.push(wasm_layout.value_type()); - match wasm_layout { - WasmLayout::LocalOnly(value_type, size) => SymbolStorage::ParamPrimitive { - local_id: next_local_id, - value_type, - size, - }, - - WasmLayout::HeapMemory => SymbolStorage::ParamPrimitive { - local_id: next_local_id, - value_type: PTR_TYPE, - size: PTR_SIZE, - }, - - WasmLayout::StackMemory { - size, - alignment_bytes, - } => SymbolStorage::ParamStackMemory { - local_id: next_local_id, - size, - alignment_bytes, - }, - } } LocalKind::Variable => { self.locals.push(Local::new(1, wasm_layout.value_type())); + } + } - match wasm_layout { - WasmLayout::LocalOnly(value_type, size) => SymbolStorage::VarPrimitive { - local_id: next_local_id, - value_type, - size, - }, + let storage = match wasm_layout { + WasmLayout::LocalOnly(value_type, size) => SymbolStorage::Local { + local_id: next_local_id, + value_type, + size, + }, - WasmLayout::HeapMemory => SymbolStorage::VarHeapMemory { - local_id: next_local_id, - }, + WasmLayout::HeapMemory => SymbolStorage::Local { + local_id: next_local_id, + value_type: PTR_TYPE, + size: PTR_SIZE, + }, - WasmLayout::StackMemory { - size, - alignment_bytes, - } => { + WasmLayout::StackMemory { + size, + alignment_bytes, + } => { + let location = match kind { + LocalKind::Parameter => StackMemoryLocation::ExternalPointer(next_local_id), + + LocalKind::Variable => { let offset = round_up_to_alignment(self.stack_memory, alignment_bytes as i32); + self.stack_memory = offset + size as i32; match self.stack_frame_pointer { + Some(_) => {} None => { self.stack_frame_pointer = Some(next_local_id); } - Some(_) => {} }; - SymbolStorage::VarStackMemory { - size, - offset: offset as u32, - alignment_bytes, - } + StackMemoryLocation::InternalOffset(offset as u32) } + }; + SymbolStorage::StackMemory { + location, + size, + alignment_bytes, } } }; @@ -288,8 +275,8 @@ impl<'a> WasmBackend<'a> { { // Map this symbol to the first argument (pointer into caller's stack) // Saves us from having to copy it later - let storage = SymbolStorage::ParamStackMemory { - local_id: LocalId(0), + let storage = SymbolStorage::StackMemory { + location: StackMemoryLocation::ExternalPointer(LocalId(0)), size, alignment_bytes, }; @@ -324,14 +311,21 @@ impl<'a> WasmBackend<'a> { let storage = self.symbol_storage_map.get(sym).unwrap(); match storage { - VarStackMemory { + StackMemory { + location, size, alignment_bytes, - offset, } => { + let (from_ptr, from_offset) = match location { + StackMemoryLocation::ExternalPointer(local_id) => (*local_id, 0), + StackMemoryLocation::InternalOffset(offset) => { + (self.stack_frame_pointer.unwrap(), *offset) + } + }; + let copy = MemoryCopy { - from_ptr: self.stack_frame_pointer.unwrap(), - from_offset: *offset, + from_ptr, + from_offset, to_ptr: LocalId(0), to_offset: 0, size: *size, @@ -340,25 +334,7 @@ impl<'a> WasmBackend<'a> { copy.generate(&mut self.instructions); } - ParamStackMemory { - local_id, - size, - alignment_bytes, - } => { - let copy = MemoryCopy { - from_ptr: *local_id, - from_offset: 0, - to_ptr: LocalId(0), - to_offset: 0, - size: *size, - alignment_bytes: *alignment_bytes, - }; - copy.generate(&mut self.instructions); - } - - ParamPrimitive { local_id, .. } - | VarPrimitive { local_id, .. } - | VarHeapMemory { local_id, .. } => { + Local { local_id, .. } => { self.instructions.push(GetLocal(local_id.0)); self.instructions.push(Br(self.block_depth)); // jump to end of function (for stack frame pop) } @@ -551,10 +527,9 @@ impl<'a> WasmBackend<'a> { if let Layout::Struct(field_layouts) = layout { let (local_id, size) = match storage { - SymbolStorage::VarStackMemory { size, .. } => { - (self.stack_frame_pointer.unwrap(), size) + SymbolStorage::StackMemory { size, .. } => { + (storage.local_id(self.stack_frame_pointer), size) } - SymbolStorage::ParamStackMemory { local_id, size, .. } => (local_id, size), _ => { return Err(format!( "Cannot create struct {:?} with storage {:?}", diff --git a/compiler/gen_wasm/src/storage.rs b/compiler/gen_wasm/src/storage.rs index 59d728db72..f1eb565097 100644 --- a/compiler/gen_wasm/src/storage.rs +++ b/compiler/gen_wasm/src/storage.rs @@ -1,82 +1,66 @@ use crate::{LocalId, MemoryCopy, ALIGN_1, ALIGN_2, ALIGN_4, ALIGN_8}; use parity_wasm::elements::{Instruction, Instruction::*, ValueType}; +#[derive(Debug, Clone)] +pub enum StackMemoryLocation { + ExternalPointer(LocalId), + InternalOffset(u32), +} + #[derive(Debug, Clone)] pub enum SymbolStorage { - VarPrimitive { + Local { local_id: LocalId, value_type: ValueType, size: u32, }, - ParamPrimitive { - local_id: LocalId, - value_type: ValueType, - size: u32, - }, - VarStackMemory { - size: u32, - offset: u32, - alignment_bytes: u32, - }, - ParamStackMemory { - local_id: LocalId, + StackMemory { + location: StackMemoryLocation, size: u32, alignment_bytes: u32, }, - VarHeapMemory { - local_id: LocalId, - }, } impl SymbolStorage { pub fn local_id(&self, stack_frame_pointer: Option) -> LocalId { + use StackMemoryLocation::*; match self { - Self::ParamPrimitive { local_id, .. } => *local_id, - Self::ParamStackMemory { local_id, .. } => *local_id, - Self::VarPrimitive { local_id, .. } => *local_id, - Self::VarStackMemory { .. } => stack_frame_pointer.unwrap(), - Self::VarHeapMemory { local_id, .. } => *local_id, + Self::Local { local_id, .. } => *local_id, + Self::StackMemory { location, .. } => match *location { + ExternalPointer(local_id) => local_id, + InternalOffset(_) => stack_frame_pointer.unwrap(), + }, } } pub fn value_type(&self) -> ValueType { match self { - Self::ParamPrimitive { value_type, .. } => *value_type, - Self::VarPrimitive { value_type, .. } => *value_type, - Self::ParamStackMemory { .. } => ValueType::I32, - Self::VarStackMemory { .. } => ValueType::I32, - Self::VarHeapMemory { .. } => ValueType::I32, + Self::Local { value_type, .. } => *value_type, + Self::StackMemory { .. } => ValueType::I32, } } pub fn has_stack_memory(&self) -> bool { match self { - Self::ParamStackMemory { .. } => true, - Self::VarStackMemory { .. } => true, - Self::ParamPrimitive { .. } => false, - Self::VarPrimitive { .. } => false, - Self::VarHeapMemory { .. } => false, + Self::Local { .. } => false, + Self::StackMemory { .. } => true, } } pub fn address_offset(&self) -> Option { + use StackMemoryLocation::*; match self { - Self::ParamStackMemory { .. } => Some(0), - Self::VarStackMemory { offset, .. } => Some(*offset), - Self::ParamPrimitive { .. } => None, - Self::VarPrimitive { .. } => None, - Self::VarHeapMemory { .. } => None, + Self::Local { .. } => None, + Self::StackMemory { location, .. } => match *location { + ExternalPointer(_) => Some(0), + InternalOffset(offset) => Some(offset), + }, } } pub fn stack_size_and_alignment(&self) -> (u32, u32) { match self { - Self::VarStackMemory { - size, - alignment_bytes, - .. - } - | Self::ParamStackMemory { + Self::StackMemory { size, alignment_bytes, .. @@ -94,13 +78,7 @@ impl SymbolStorage { stack_frame_pointer: Option, ) -> u32 { match self { - Self::ParamPrimitive { - local_id, - value_type, - size, - .. - } - | Self::VarPrimitive { + Self::Local { local_id, value_type, size, @@ -123,13 +101,14 @@ impl SymbolStorage { *size } - Self::ParamStackMemory { - local_id, + Self::StackMemory { size, alignment_bytes, + .. } => { + let local_id = self.local_id(stack_frame_pointer); let copy = MemoryCopy { - from_ptr: *local_id, + from_ptr: local_id, from_offset: 0, to_ptr: to_pointer, to_offset, @@ -139,31 +118,6 @@ impl SymbolStorage { copy.generate(instructions); *size } - - Self::VarStackMemory { - size, - alignment_bytes, - offset, - .. - } => { - let copy = MemoryCopy { - from_ptr: stack_frame_pointer.unwrap(), - from_offset: *offset, - to_ptr: to_pointer, - to_offset, - size: *size, - alignment_bytes: *alignment_bytes, - }; - copy.generate(instructions); - *size - } - - Self::VarHeapMemory { local_id, .. } => { - instructions.push(GetLocal(to_pointer.0)); - instructions.push(GetLocal(local_id.0)); - instructions.push(I32Store(ALIGN_4, to_offset)); - 4 - } } } }