Refactor SymbolStorage into two enums instead of one

This commit is contained in:
Brian Carroll 2021-10-02 16:15:06 +01:00
parent ffa6ff0a62
commit 6aed70978d
2 changed files with 78 additions and 149 deletions

View file

@ -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 {:?}",

View file

@ -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>) -> 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<u32> {
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<LocalId>,
) -> 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
}
}
}
}