diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index 6a516e543d..e5a114f888 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -277,6 +277,7 @@ impl<'a> WasmBackend<'a> { location, size, alignment_bytes, + .. } => { let (from_ptr, from_offset) = location.local_and_offset(self.storage.stack_frame_pointer); diff --git a/compiler/gen_wasm/src/layout.rs b/compiler/gen_wasm/src/layout.rs index 2cd562dcc8..6e0a8d94fb 100644 --- a/compiler/gen_wasm/src/layout.rs +++ b/compiler/gen_wasm/src/layout.rs @@ -2,6 +2,15 @@ use roc_mono::layout::{Layout, UnionLayout}; use crate::{wasm_module::ValueType, PTR_SIZE, PTR_TYPE}; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum StackMemoryFormat { + /// Record, Str, List, Dict, etc. + Aggregate, + Int128, + Float128, + Decimal, +} + // See README for background information on Wasm locals, memory and function calls #[derive(Debug, Clone)] pub enum WasmLayout { @@ -10,7 +19,11 @@ pub enum WasmLayout { Primitive(ValueType, u32), // Local pointer to stack memory - StackMemory { size: u32, alignment_bytes: u32 }, + StackMemory { + size: u32, + alignment_bytes: u32, + format: StackMemoryFormat, + }, // Local pointer to heap memory HeapMemory, @@ -35,23 +48,32 @@ impl WasmLayout { Layout::Builtin(Float64) => Self::Primitive(F64, size), Layout::Builtin( - Int128 - | Decimal - | Float128 - | Str - | Dict(_, _) - | Set(_) - | List(_) - | EmptyStr - | EmptyList - | EmptyDict - | EmptySet, + Str | Dict(_, _) | Set(_) | List(_) | EmptyStr | EmptyList | EmptyDict | EmptySet, ) | Layout::Struct(_) | Layout::LambdaSet(_) | Layout::Union(NonRecursive(_)) => Self::StackMemory { size, alignment_bytes, + format: StackMemoryFormat::Aggregate, + }, + + Layout::Builtin(Int128) => Self::StackMemory { + size, + alignment_bytes, + format: StackMemoryFormat::Int128, + }, + + Layout::Builtin(Decimal) => Self::StackMemory { + size, + alignment_bytes, + format: StackMemoryFormat::Decimal, + }, + + Layout::Builtin(Float128) => Self::StackMemory { + size, + alignment_bytes, + format: StackMemoryFormat::Float128, }, Layout::Union( diff --git a/compiler/gen_wasm/src/storage.rs b/compiler/gen_wasm/src/storage.rs index cf4f336c06..8cb10d739e 100644 --- a/compiler/gen_wasm/src/storage.rs +++ b/compiler/gen_wasm/src/storage.rs @@ -4,7 +4,7 @@ use bumpalo::Bump; use roc_collections::all::MutMap; use roc_module::symbol::Symbol; -use crate::layout::WasmLayout; +use crate::layout::{StackMemoryFormat, WasmLayout}; use crate::wasm_module::{Align, CodeBuilder, LocalId, ValueType, VmSymbolState}; use crate::{copy_memory, round_up_to_alignment, CopyMemoryConfig, PTR_SIZE, PTR_TYPE}; @@ -50,6 +50,7 @@ pub enum StoredValue { location: StackMemoryLocation, size: u32, alignment_bytes: u32, + format: StackMemoryFormat, }, } @@ -147,6 +148,7 @@ impl<'a> Storage<'a> { WasmLayout::StackMemory { size, alignment_bytes, + format, } => { let location = match kind { StoredValueKind::Parameter => { @@ -175,6 +177,7 @@ impl<'a> Storage<'a> { location, size: *size, alignment_bytes: *alignment_bytes, + format: *format, } } }; @@ -239,13 +242,26 @@ impl<'a> Storage<'a> { code_builder.set_top_symbol(sym); } - StoredValue::StackMemory { location, .. } => { + StoredValue::StackMemory { + location, format, .. + } => { let (local_id, offset) = location.local_and_offset(self.stack_frame_pointer); + + // Load the address of the value code_builder.get_local(local_id); if offset != 0 { code_builder.i32_const(offset as i32); code_builder.i32_add(); } + + if format != StackMemoryFormat::Aggregate { + // It's one of the 128-bit numbers, all of which we load as two i64's + // Mark the same Symbol twice in the VM value stack! Shouldn't matter except debug. + code_builder.i64_load(Align::Bytes8, offset); + code_builder.set_top_symbol(sym); + code_builder.i64_load(Align::Bytes8, offset + 8); + } + code_builder.set_top_symbol(sym); } } @@ -292,6 +308,7 @@ impl<'a> Storage<'a> { location, size, alignment_bytes, + format: StackMemoryFormat::Aggregate, } = self.get(sym) { if *size == 0 { @@ -334,6 +351,7 @@ impl<'a> Storage<'a> { location, size, alignment_bytes, + .. } => { let (from_ptr, from_offset) = location.local_and_offset(self.stack_frame_pointer); copy_memory( @@ -390,6 +408,7 @@ impl<'a> Storage<'a> { location, size, alignment_bytes, + .. } => { let (to_ptr, to_offset) = location.local_and_offset(self.stack_frame_pointer); copy_memory( @@ -490,11 +509,13 @@ impl<'a> Storage<'a> { location: to_location, size: to_size, alignment_bytes: to_alignment_bytes, + .. }, StackMemory { location: from_location, size: from_size, alignment_bytes: from_alignment_bytes, + .. }, ) => { let (from_ptr, from_offset) =