diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index c19f374d2e..e7feba0a23 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -418,9 +418,6 @@ impl<'a, 'r> WasmBackend<'a, 'r> { self.storage.arg_types.push(PTR_TYPE); None } - ZigPackedStruct => { - internal_error!("C calling convention does not return Zig packed structs") - } }; // Create a block so we can exit the function without skipping stack frame "pop" code. @@ -528,7 +525,6 @@ impl<'a, 'r> WasmBackend<'a, 'r> { n_inner_wasm_args += 1; None } - x => internal_error!("A Roc function should never use ReturnMethod {:?}", x), }; // Load all the arguments for the inner function @@ -1349,16 +1345,14 @@ impl<'a, 'r> WasmBackend<'a, 'r> { } => { let name = foreign_symbol.as_str(); let wasm_layout = WasmLayout::new(self.layout_interner, *ret_layout); - let (num_wasm_args, has_return_val, ret_zig_packed_struct) = - self.storage.load_symbols_for_call( - self.env.arena, - &mut self.code_builder, - arguments, - ret_sym, - &wasm_layout, - CallConv::C, - ); - debug_assert!(!ret_zig_packed_struct); // only true in another place where we use the same helper fn + let (num_wasm_args, has_return_val) = self.storage.load_symbols_for_call( + self.env.arena, + &mut self.code_builder, + arguments, + ret_sym, + &wasm_layout, + CallConv::C, + ); self.call_host_fn_after_loading_args(name, num_wasm_args, has_return_val) } } @@ -1382,16 +1376,14 @@ impl<'a, 'r> WasmBackend<'a, 'r> { return self.expr_call_low_level(lowlevel, arguments, ret_sym, ret_layout, ret_storage); } - let (num_wasm_args, has_return_val, ret_zig_packed_struct) = - self.storage.load_symbols_for_call( - self.env.arena, - &mut self.code_builder, - arguments, - ret_sym, - &wasm_layout, - CallConv::C, - ); - debug_assert!(!ret_zig_packed_struct); + let (num_wasm_args, has_return_val) = self.storage.load_symbols_for_call( + self.env.arena, + &mut self.code_builder, + arguments, + ret_sym, + &wasm_layout, + CallConv::C, + ); let roc_proc_index = self .proc_lookup diff --git a/crates/compiler/gen_wasm/src/layout.rs b/crates/compiler/gen_wasm/src/layout.rs index 3d32cb7875..ac06053448 100644 --- a/crates/compiler/gen_wasm/src/layout.rs +++ b/crates/compiler/gen_wasm/src/layout.rs @@ -13,8 +13,6 @@ pub enum ReturnMethod { WriteToPointerArg, /// This layout is empty and requires no return value or argument (e.g. refcount helpers) NoReturnValue, - /// This layout is returned as a packed struct in an integer. Only used by Zig, not C. - ZigPackedStruct, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -197,13 +195,7 @@ impl CallConv { match self { CallConv::C => WriteToPointerArg, - CallConv::Zig => { - if size <= 8 { - ZigPackedStruct - } else { - WriteToPointerArg - } - } + CallConv::Zig => WriteToPointerArg, } } } diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index 96d69cb401..e502cf7882 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -135,7 +135,7 @@ impl<'a> LowLevelCall<'a> { /// For numerical ops, this just pushes the arguments to the Wasm VM's value stack /// It implements the calling convention used by Zig for both numbers and structs /// Result is the type signature of the call - fn load_args(&self, backend: &mut WasmBackend<'a, '_>) -> (usize, bool, bool) { + fn load_args(&self, backend: &mut WasmBackend<'a, '_>) -> (usize, bool) { backend.storage.load_symbols_for_call( backend.env.arena, &mut backend.code_builder, @@ -147,29 +147,8 @@ impl<'a> LowLevelCall<'a> { } fn load_args_and_call_zig(&self, backend: &mut WasmBackend<'a, '_>, name: &'a str) { - let (num_wasm_args, has_return_val, ret_zig_packed_struct) = self.load_args(backend); + let (num_wasm_args, has_return_val) = self.load_args(backend); backend.call_host_fn_after_loading_args(name, num_wasm_args, has_return_val); - - if ret_zig_packed_struct { - match self.ret_storage { - StoredValue::StackMemory { - size, - alignment_bytes, - .. - } => { - // The address of the return value was already loaded before the call - let align = Align::from(alignment_bytes); - if size > 4 { - backend.code_builder.i64_store(align, 0); - } else { - backend.code_builder.i32_store(align, 0); - } - } - _ => { - internal_error!("Zig packed struct should always be stored to StackMemory") - } - } - } } /// Wrap an integer that should have less than 32 bits, but is represented in Wasm as i32. diff --git a/crates/compiler/gen_wasm/src/storage.rs b/crates/compiler/gen_wasm/src/storage.rs index 89ff9facd5..cd61c9deae 100644 --- a/crates/compiler/gen_wasm/src/storage.rs +++ b/crates/compiler/gen_wasm/src/storage.rs @@ -493,7 +493,7 @@ impl<'a> Storage<'a> { return_symbol: Symbol, return_layout: &WasmLayout, call_conv: CallConv, - ) -> (usize, bool, bool) { + ) -> (usize, bool) { use ReturnMethod::*; let mut num_wasm_args = 0; @@ -508,14 +508,6 @@ impl<'a> Storage<'a> { symbols_to_load.push(return_symbol); false } - ZigPackedStruct => { - // Workaround for Zig's incorrect implementation of the C calling convention. - // We need to copy the packed struct into the stack frame - // Load the address before the call so that afterward, it will be 2nd on the value stack, - // ready for the store instruction. - symbols_to_load.push(return_symbol); - true - } }; for arg in arguments { @@ -533,7 +525,7 @@ impl<'a> Storage<'a> { // If the symbols were already at the top of the stack, do nothing! // Should be common for simple cases, due to the structure of the Mono IR if !code_builder.verify_stack_match(&symbols_to_load) { - if matches!(return_method, WriteToPointerArg | ZigPackedStruct) { + if matches!(return_method, WriteToPointerArg) { self.load_return_address_ccc(code_builder, return_symbol); }; @@ -545,11 +537,7 @@ impl<'a> Storage<'a> { } } - ( - num_wasm_args, - has_return_val, - return_method == ZigPackedStruct, - ) + (num_wasm_args, has_return_val) } /// Generate code to copy a StoredValue to an arbitrary memory location