mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Refactor SymbolStorage into two enums instead of one
This commit is contained in:
parent
ffa6ff0a62
commit
6aed70978d
2 changed files with 78 additions and 149 deletions
|
@ -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 {:?}",
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue