diff --git a/compiler/gen_wasm/src/backend.rs b/compiler/gen_wasm/src/backend.rs index f062786e33..3d574eb8da 100644 --- a/compiler/gen_wasm/src/backend.rs +++ b/compiler/gen_wasm/src/backend.rs @@ -7,7 +7,7 @@ use roc_module::symbol::Symbol; use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt}; use roc_mono::layout::{Builtin, Layout, LayoutIds}; -use crate::layout::WasmLayout; +use crate::layout::{StackMemoryFormat, WasmLayout}; use crate::low_level::{decode_low_level, LowlevelBuildResult}; use crate::storage::{Storage, StoredValue, StoredValueKind}; use crate::wasm_module::linking::{ @@ -803,15 +803,31 @@ impl<'a> WasmBackend<'a> { Some(ret_layout.value_type()) }; - // Zig's "fast calling convention" packs structs into CPU registers (stack machine slots) if possible. - // If they're small enough they can go into an I32 or I64. If they're big, they're pointers (I32). for arg in arguments { - param_types.push(match self.storage.get(arg) { - StoredValue::StackMemory { size, .. } if *size > 4 && *size <= 8 => { - ValueType::I64 + match self.storage.get(arg) { + stored @ StoredValue::StackMemory { size, format, .. } => { + use StackMemoryFormat::*; + + match format { + Aggregate => { + // Zig's "fast calling convention" packs structs into CPU registers + // (stack machine slots) if possible. If they're small enough they + // can go into an I32 or I64. If they're big, they're pointers (I32). + if *size > 4 && *size <= 8 { + param_types.push(ValueType::I64) + } else { + param_types.push(stored.value_type()) + } + } + Int128 | Float128 | Decimal => { + // these types are passed as 2 i64s + param_types.push(ValueType::I64); + param_types.push(ValueType::I64); + } + } } - stored => stored.value_type(), - }); + stored => param_types.push(stored.value_type()), + } } let signature_index = self.module.types.insert(Signature { diff --git a/compiler/gen_wasm/src/low_level.rs b/compiler/gen_wasm/src/low_level.rs index d94c6f8c7c..700268c9fa 100644 --- a/compiler/gen_wasm/src/low_level.rs +++ b/compiler/gen_wasm/src/low_level.rs @@ -2,7 +2,7 @@ use roc_builtins::bitcode::{self, FloatWidth}; use roc_module::low_level::{LowLevel, LowLevel::*}; use roc_module::symbol::Symbol; -use crate::layout::WasmLayout; +use crate::layout::{StackMemoryFormat, WasmLayout}; use crate::storage::Storage; use crate::wasm_module::{ CodeBuilder, @@ -63,11 +63,20 @@ pub fn decode_low_level<'a>( return NotImplemented; } - NumAdd => match ret_layout.value_type() { - I32 => code_builder.i32_add(), - I64 => code_builder.i64_add(), - F32 => code_builder.f32_add(), - F64 => code_builder.f64_add(), + NumAdd => match ret_layout { + WasmLayout::Primitive(value_type, _) => match value_type { + I32 => code_builder.i32_add(), + I64 => code_builder.i64_add(), + F32 => code_builder.f32_add(), + F64 => code_builder.f64_add(), + }, + WasmLayout::StackMemory { format, .. } => match format { + StackMemoryFormat::Aggregate => return NotImplemented, + StackMemoryFormat::Int128 => return NotImplemented, + StackMemoryFormat::Float128 => return NotImplemented, + StackMemoryFormat::Decimal => return BuiltinCall(bitcode::DEC_ADD_WITH_OVERFLOW), + }, + WasmLayout::HeapMemory { .. } => return NotImplemented, }, NumAddWrap => match ret_layout.value_type() { I32 => { diff --git a/compiler/test_gen/src/gen_num.rs b/compiler/test_gen/src/gen_num.rs index 0adbf3e867..ecf899f1b4 100644 --- a/compiler/test_gen/src/gen_num.rs +++ b/compiler/test_gen/src/gen_num.rs @@ -609,7 +609,7 @@ fn gen_float_eq() { } #[test] -#[cfg(any(feature = "gen-llvm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] fn gen_add_dec() { assert_evals_to!( indoc!(