mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +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 roc_mono::layout::{Builtin, Layout};
|
||||||
|
|
||||||
use crate::layout::WasmLayout;
|
use crate::layout::WasmLayout;
|
||||||
use crate::storage::SymbolStorage;
|
use crate::storage::{StackMemoryLocation, SymbolStorage};
|
||||||
use crate::{
|
use crate::{
|
||||||
pop_stack_frame, push_stack_frame, round_up_to_alignment, LocalId, MemoryCopy, PTR_SIZE,
|
pop_stack_frame, push_stack_frame, round_up_to_alignment, LocalId, MemoryCopy, PTR_SIZE,
|
||||||
PTR_TYPE,
|
PTR_TYPE,
|
||||||
|
@ -167,68 +167,55 @@ impl<'a> WasmBackend<'a> {
|
||||||
) -> SymbolStorage {
|
) -> SymbolStorage {
|
||||||
let next_local_id = LocalId((self.arg_types.len() + self.locals.len()) as u32);
|
let next_local_id = LocalId((self.arg_types.len() + self.locals.len()) as u32);
|
||||||
|
|
||||||
let storage = match kind {
|
match kind {
|
||||||
LocalKind::Parameter => {
|
LocalKind::Parameter => {
|
||||||
// Already stack-allocated by the caller if needed.
|
|
||||||
self.arg_types.push(wasm_layout.value_type());
|
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 => {
|
LocalKind::Variable => {
|
||||||
self.locals.push(Local::new(1, wasm_layout.value_type()));
|
self.locals.push(Local::new(1, wasm_layout.value_type()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match wasm_layout {
|
let storage = match wasm_layout {
|
||||||
WasmLayout::LocalOnly(value_type, size) => SymbolStorage::VarPrimitive {
|
WasmLayout::LocalOnly(value_type, size) => SymbolStorage::Local {
|
||||||
local_id: next_local_id,
|
local_id: next_local_id,
|
||||||
value_type,
|
value_type,
|
||||||
size,
|
size,
|
||||||
},
|
},
|
||||||
|
|
||||||
WasmLayout::HeapMemory => SymbolStorage::VarHeapMemory {
|
WasmLayout::HeapMemory => SymbolStorage::Local {
|
||||||
local_id: next_local_id,
|
local_id: next_local_id,
|
||||||
},
|
value_type: PTR_TYPE,
|
||||||
|
size: PTR_SIZE,
|
||||||
|
},
|
||||||
|
|
||||||
WasmLayout::StackMemory {
|
WasmLayout::StackMemory {
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
} => {
|
} => {
|
||||||
|
let location = match kind {
|
||||||
|
LocalKind::Parameter => StackMemoryLocation::ExternalPointer(next_local_id),
|
||||||
|
|
||||||
|
LocalKind::Variable => {
|
||||||
let offset =
|
let offset =
|
||||||
round_up_to_alignment(self.stack_memory, alignment_bytes as i32);
|
round_up_to_alignment(self.stack_memory, alignment_bytes as i32);
|
||||||
|
|
||||||
self.stack_memory = offset + size as i32;
|
self.stack_memory = offset + size as i32;
|
||||||
|
|
||||||
match self.stack_frame_pointer {
|
match self.stack_frame_pointer {
|
||||||
|
Some(_) => {}
|
||||||
None => {
|
None => {
|
||||||
self.stack_frame_pointer = Some(next_local_id);
|
self.stack_frame_pointer = Some(next_local_id);
|
||||||
}
|
}
|
||||||
Some(_) => {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SymbolStorage::VarStackMemory {
|
StackMemoryLocation::InternalOffset(offset as u32)
|
||||||
size,
|
|
||||||
offset: offset as u32,
|
|
||||||
alignment_bytes,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
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)
|
// Map this symbol to the first argument (pointer into caller's stack)
|
||||||
// Saves us from having to copy it later
|
// Saves us from having to copy it later
|
||||||
let storage = SymbolStorage::ParamStackMemory {
|
let storage = SymbolStorage::StackMemory {
|
||||||
local_id: LocalId(0),
|
location: StackMemoryLocation::ExternalPointer(LocalId(0)),
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
};
|
};
|
||||||
|
@ -324,14 +311,21 @@ impl<'a> WasmBackend<'a> {
|
||||||
let storage = self.symbol_storage_map.get(sym).unwrap();
|
let storage = self.symbol_storage_map.get(sym).unwrap();
|
||||||
|
|
||||||
match storage {
|
match storage {
|
||||||
VarStackMemory {
|
StackMemory {
|
||||||
|
location,
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
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 {
|
let copy = MemoryCopy {
|
||||||
from_ptr: self.stack_frame_pointer.unwrap(),
|
from_ptr,
|
||||||
from_offset: *offset,
|
from_offset,
|
||||||
to_ptr: LocalId(0),
|
to_ptr: LocalId(0),
|
||||||
to_offset: 0,
|
to_offset: 0,
|
||||||
size: *size,
|
size: *size,
|
||||||
|
@ -340,25 +334,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
copy.generate(&mut self.instructions);
|
copy.generate(&mut self.instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamStackMemory {
|
Local { local_id, .. } => {
|
||||||
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, .. } => {
|
|
||||||
self.instructions.push(GetLocal(local_id.0));
|
self.instructions.push(GetLocal(local_id.0));
|
||||||
self.instructions.push(Br(self.block_depth)); // jump to end of function (for stack frame pop)
|
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 {
|
if let Layout::Struct(field_layouts) = layout {
|
||||||
let (local_id, size) = match storage {
|
let (local_id, size) = match storage {
|
||||||
SymbolStorage::VarStackMemory { size, .. } => {
|
SymbolStorage::StackMemory { size, .. } => {
|
||||||
(self.stack_frame_pointer.unwrap(), size)
|
(storage.local_id(self.stack_frame_pointer), size)
|
||||||
}
|
}
|
||||||
SymbolStorage::ParamStackMemory { local_id, size, .. } => (local_id, size),
|
|
||||||
_ => {
|
_ => {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"Cannot create struct {:?} with storage {:?}",
|
"Cannot create struct {:?} with storage {:?}",
|
||||||
|
|
|
@ -1,82 +1,66 @@
|
||||||
use crate::{LocalId, MemoryCopy, ALIGN_1, ALIGN_2, ALIGN_4, ALIGN_8};
|
use crate::{LocalId, MemoryCopy, ALIGN_1, ALIGN_2, ALIGN_4, ALIGN_8};
|
||||||
use parity_wasm::elements::{Instruction, Instruction::*, ValueType};
|
use parity_wasm::elements::{Instruction, Instruction::*, ValueType};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum StackMemoryLocation {
|
||||||
|
ExternalPointer(LocalId),
|
||||||
|
InternalOffset(u32),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum SymbolStorage {
|
pub enum SymbolStorage {
|
||||||
VarPrimitive {
|
Local {
|
||||||
local_id: LocalId,
|
local_id: LocalId,
|
||||||
value_type: ValueType,
|
value_type: ValueType,
|
||||||
size: u32,
|
size: u32,
|
||||||
},
|
},
|
||||||
ParamPrimitive {
|
StackMemory {
|
||||||
local_id: LocalId,
|
location: StackMemoryLocation,
|
||||||
value_type: ValueType,
|
|
||||||
size: u32,
|
|
||||||
},
|
|
||||||
VarStackMemory {
|
|
||||||
size: u32,
|
|
||||||
offset: u32,
|
|
||||||
alignment_bytes: u32,
|
|
||||||
},
|
|
||||||
ParamStackMemory {
|
|
||||||
local_id: LocalId,
|
|
||||||
size: u32,
|
size: u32,
|
||||||
alignment_bytes: u32,
|
alignment_bytes: u32,
|
||||||
},
|
},
|
||||||
VarHeapMemory {
|
|
||||||
local_id: LocalId,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SymbolStorage {
|
impl SymbolStorage {
|
||||||
pub fn local_id(&self, stack_frame_pointer: Option<LocalId>) -> LocalId {
|
pub fn local_id(&self, stack_frame_pointer: Option<LocalId>) -> LocalId {
|
||||||
|
use StackMemoryLocation::*;
|
||||||
match self {
|
match self {
|
||||||
Self::ParamPrimitive { local_id, .. } => *local_id,
|
Self::Local { local_id, .. } => *local_id,
|
||||||
Self::ParamStackMemory { local_id, .. } => *local_id,
|
Self::StackMemory { location, .. } => match *location {
|
||||||
Self::VarPrimitive { local_id, .. } => *local_id,
|
ExternalPointer(local_id) => local_id,
|
||||||
Self::VarStackMemory { .. } => stack_frame_pointer.unwrap(),
|
InternalOffset(_) => stack_frame_pointer.unwrap(),
|
||||||
Self::VarHeapMemory { local_id, .. } => *local_id,
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn value_type(&self) -> ValueType {
|
pub fn value_type(&self) -> ValueType {
|
||||||
match self {
|
match self {
|
||||||
Self::ParamPrimitive { value_type, .. } => *value_type,
|
Self::Local { value_type, .. } => *value_type,
|
||||||
Self::VarPrimitive { value_type, .. } => *value_type,
|
Self::StackMemory { .. } => ValueType::I32,
|
||||||
Self::ParamStackMemory { .. } => ValueType::I32,
|
|
||||||
Self::VarStackMemory { .. } => ValueType::I32,
|
|
||||||
Self::VarHeapMemory { .. } => ValueType::I32,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_stack_memory(&self) -> bool {
|
pub fn has_stack_memory(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::ParamStackMemory { .. } => true,
|
Self::Local { .. } => false,
|
||||||
Self::VarStackMemory { .. } => true,
|
Self::StackMemory { .. } => true,
|
||||||
Self::ParamPrimitive { .. } => false,
|
|
||||||
Self::VarPrimitive { .. } => false,
|
|
||||||
Self::VarHeapMemory { .. } => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn address_offset(&self) -> Option<u32> {
|
pub fn address_offset(&self) -> Option<u32> {
|
||||||
|
use StackMemoryLocation::*;
|
||||||
match self {
|
match self {
|
||||||
Self::ParamStackMemory { .. } => Some(0),
|
Self::Local { .. } => None,
|
||||||
Self::VarStackMemory { offset, .. } => Some(*offset),
|
Self::StackMemory { location, .. } => match *location {
|
||||||
Self::ParamPrimitive { .. } => None,
|
ExternalPointer(_) => Some(0),
|
||||||
Self::VarPrimitive { .. } => None,
|
InternalOffset(offset) => Some(offset),
|
||||||
Self::VarHeapMemory { .. } => None,
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stack_size_and_alignment(&self) -> (u32, u32) {
|
pub fn stack_size_and_alignment(&self) -> (u32, u32) {
|
||||||
match self {
|
match self {
|
||||||
Self::VarStackMemory {
|
Self::StackMemory {
|
||||||
size,
|
|
||||||
alignment_bytes,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| Self::ParamStackMemory {
|
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
..
|
..
|
||||||
|
@ -94,13 +78,7 @@ impl SymbolStorage {
|
||||||
stack_frame_pointer: Option<LocalId>,
|
stack_frame_pointer: Option<LocalId>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
Self::ParamPrimitive {
|
Self::Local {
|
||||||
local_id,
|
|
||||||
value_type,
|
|
||||||
size,
|
|
||||||
..
|
|
||||||
}
|
|
||||||
| Self::VarPrimitive {
|
|
||||||
local_id,
|
local_id,
|
||||||
value_type,
|
value_type,
|
||||||
size,
|
size,
|
||||||
|
@ -123,13 +101,14 @@ impl SymbolStorage {
|
||||||
*size
|
*size
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::ParamStackMemory {
|
Self::StackMemory {
|
||||||
local_id,
|
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
|
let local_id = self.local_id(stack_frame_pointer);
|
||||||
let copy = MemoryCopy {
|
let copy = MemoryCopy {
|
||||||
from_ptr: *local_id,
|
from_ptr: local_id,
|
||||||
from_offset: 0,
|
from_offset: 0,
|
||||||
to_ptr: to_pointer,
|
to_ptr: to_pointer,
|
||||||
to_offset,
|
to_offset,
|
||||||
|
@ -139,31 +118,6 @@ impl SymbolStorage {
|
||||||
copy.generate(instructions);
|
copy.generate(instructions);
|
||||||
*size
|
*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