diff --git a/crates/compiler/gen_wasm/src/backend.rs b/crates/compiler/gen_wasm/src/backend.rs index e288774ad4..4997e54426 100644 --- a/crates/compiler/gen_wasm/src/backend.rs +++ b/crates/compiler/gen_wasm/src/backend.rs @@ -1084,7 +1084,14 @@ impl<'a, 'r> WasmBackend<'a, 'r> { tag_id, union_layout, index, - } => self.expr_union_field_ptr_at_index(*structure, *tag_id, union_layout, *index, sym), + } => self.expr_union_field_ptr_at_index( + *structure, + *tag_id, + union_layout, + *index, + sym, + storage, + ), Expr::ExprBox { symbol: arg_sym } => self.expr_box(sym, *arg_sym, layout, storage), @@ -1885,6 +1892,7 @@ impl<'a, 'r> WasmBackend<'a, 'r> { union_layout: &UnionLayout<'a>, index: u64, symbol: Symbol, + storage: &StoredValue, ) { use UnionLayout::*; @@ -1934,18 +1942,28 @@ impl<'a, 'r> WasmBackend<'a, 'r> { let stores_tag_id_in_pointer = union_layout.stores_tag_id_in_pointer(TARGET_INFO); - let from_addr_val = if stores_tag_id_in_pointer { - self.code_builder.get_local(tag_local_id); - self.code_builder.i32_const(-4); // 11111111...1100 - self.code_builder.i32_and(); - AddressValue::Loaded - } else { - AddressValue::NotLoaded(tag_local_id) - }; - let from_offset = tag_offset + field_offset; - self.code_builder.i32_const(from_offset as i32); + self.code_builder.get_local(tag_local_id); + + if stores_tag_id_in_pointer { + self.code_builder.i32_const(-4); // 11111111...1100 + self.code_builder.i32_and(); + } + + self.code_builder.i32_const(from_offset as _); + self.code_builder.i32_add(); + + let symbol_local = match self.storage.ensure_value_has_local( + &mut self.code_builder, + symbol, + storage.clone(), + ) { + StoredValue::Local { local_id, .. } => local_id, + _ => internal_error!("A heap pointer will always be an i32"), + }; + + self.code_builder.set_local(symbol_local); } /******************************************************************* diff --git a/crates/compiler/gen_wasm/src/low_level.rs b/crates/compiler/gen_wasm/src/low_level.rs index dbd04fdd27..8e76474d6d 100644 --- a/crates/compiler/gen_wasm/src/low_level.rs +++ b/crates/compiler/gen_wasm/src/low_level.rs @@ -1962,42 +1962,25 @@ impl<'a> LowLevelCall<'a> { PtrStore => { // PtrStore : Ptr a, a -> {} - let ptr_sym = self.arguments[0]; - let value_sym = self.arguments[1]; + let ptr = self.arguments[0]; + let value = self.arguments[1]; - // create a local variable for the heap pointer - let ptr_local_id = match backend.storage.ensure_value_has_local( - &mut backend.code_builder, - ptr_sym, - self.ret_storage.clone(), - ) { - StoredValue::Local { local_id, .. } => local_id, - StoredValue::StackMemory { location, .. } => { - location - .local_and_offset(backend.storage.stack_frame_pointer) - .0 - } - other => internal_error!( - "Struct should be allocated in stack memory, but it's in {:?}", - other - ), + let (ptr_local_id, offset) = match backend.storage.get(&ptr) { + StoredValue::Local { local_id, .. } => (*local_id, 0), + _ => internal_error!("A pointer will always be an i32"), }; - dbg!(ptr_local_id); - - // store the pointer value from the value stack into the local variable - backend.code_builder.set_local(ptr_local_id); - // copy the argument to the pointer address backend.storage.copy_value_to_memory( &mut backend.code_builder, ptr_local_id, - 0, - value_sym, + offset, + value, ); } PtrLoad => backend.expr_unbox(self.ret_symbol, self.arguments[0]), PtrToStackValue => { + // PtrToStackValue : a -> Ptr a let arg = self.arguments[0]; let arg_layout = backend.storage.symbol_layouts.get(&arg).unwrap(); @@ -2009,6 +1992,7 @@ impl<'a> LowLevelCall<'a> { .storage .allocate_anonymous_stack_memory(size, alignment_bytes); + // write the default value into the stack memory backend.storage.copy_value_to_memory( &mut backend.code_builder, frame_ptr, @@ -2026,9 +2010,6 @@ impl<'a> LowLevelCall<'a> { _ => internal_error!("A pointer will always be an i32"), }; - // store the pointer value from the value stack into the local variable - dbg!(offset, size, alignment_bytes); - backend.code_builder.get_local(frame_ptr); backend.code_builder.i32_const(offset as i32); backend.code_builder.i32_add();