diff --git a/crates/compiler/gen_dev/src/generic64/storage.rs b/crates/compiler/gen_dev/src/generic64/storage.rs index bfd4662e14..4cd0b28adc 100644 --- a/crates/compiler/gen_dev/src/generic64/storage.rs +++ b/crates/compiler/gen_dev/src/generic64/storage.rs @@ -841,8 +841,6 @@ impl< Builtin::Decimal => todo!(), Builtin::Str | Builtin::List(_) => { let (from_offset, size) = self.stack_offset_and_size(sym); - debug_assert_eq!(from_offset % 8, 0); - debug_assert_eq!(size % 8, 0); debug_assert_eq!(size, layout_interner.stack_size(*layout)); self.copy_to_stack_offset(buf, size, from_offset, to_offset) } @@ -885,6 +883,14 @@ impl< let size = size as i32; self.with_tmp_general_reg(buf, |_storage_manager, buf, reg| { + // on targets beside x86, misaligned copies might be a problem + for _ in 0..size % 8 { + ASM::mov_reg8_base32(buf, reg, from_offset + copied); + ASM::mov_base32_reg8(buf, to_offset + copied, reg); + + copied += 1; + } + if size - copied >= 8 { for _ in (0..(size - copied)).step_by(8) { ASM::mov_reg64_base32(buf, reg, from_offset + copied); diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 43cc4a7c81..73f9676126 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -1417,6 +1417,72 @@ trait Backend<'a> { ); } + LowLevel::ListDropAt => { + let list = args[0]; + let drop_index = args[1]; + + let list_layout = arg_layouts[0]; + let element_layout = match self.interner().get(list_layout) { + Layout::Builtin(Builtin::List(e)) => e, + _ => unreachable!(), + }; + + let (element_width_int, alignment_int) = + self.interner().stack_size_and_alignment(element_layout); + + let alignment = self.debug_symbol("alignment"); + self.load_literal_i32(&alignment, Ord::max(alignment_int, 8) as i32); + + let element_width = self.debug_symbol("element_width"); + self.load_literal_i64(&element_width, element_width_int as i64); + + let update_mode = self.debug_symbol("update_mode"); + self.load_literal_i8(&update_mode, UpdateMode::Immutable as i8); + + let arena = self.env().arena; + + let element_decrement = self.debug_symbol("element_decrement"); + let element_decrement_symbol = self.gen_refcount_proc_dec(element_layout); + let element_decrement_layout = ProcLayout { + arguments: arena.alloc([element_layout]), + result: Layout::UNIT, + niche: roc_mono::layout::Niche::NONE, + }; + let element_decrement_string = layout_ids + .get_toplevel(element_decrement_symbol, &element_decrement_layout) + .to_symbol_string(element_decrement_symbol, self.interns()); + + self.build_fn_pointer(&element_decrement, element_decrement_string); + + let layout_usize = Layout::U64; + + // list: RocList, + // alignment: u32, + // element_width: usize, + // drop_index: usize, + // dec: Dec, + + self.build_fn_call( + sym, + bitcode::LIST_DROP_AT.to_string(), + &[ + list, + alignment, + element_width, + drop_index, + element_decrement, + ], + &[ + list_layout, + Layout::U32, + layout_usize, + layout_usize, + layout_usize, + ], + ret_layout, + ); + } + x => todo!("low level, {:?}", x), } } diff --git a/crates/compiler/test_gen/src/gen_list.rs b/crates/compiler/test_gen/src/gen_list.rs index 0fba710c1e..ff2f03b16a 100644 --- a/crates/compiler/test_gen/src/gen_list.rs +++ b/crates/compiler/test_gen/src/gen_list.rs @@ -121,7 +121,7 @@ fn bool_list_concat() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn bool_list_literal_repeat() { assert_evals_to!( indoc!( @@ -198,7 +198,7 @@ fn list_append_basic() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_take_first() { assert_evals_to!( "List.takeFirst [1, 2, 3] 2", @@ -223,7 +223,7 @@ fn list_take_first() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_take_last() { assert_evals_to!( "List.takeLast [1, 2, 3] 2", @@ -288,7 +288,7 @@ fn list_sublist() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_map_try_ok() { assert_evals_to!( // No transformation @@ -318,7 +318,7 @@ fn list_map_try_ok() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_map_try_err() { use core::convert::Infallible; @@ -508,7 +508,7 @@ fn list_drop_at() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_intersperse() { assert_evals_to!( indoc!( @@ -553,7 +553,7 @@ fn list_drop_at_shared() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_drop_if_empty_list_of_int() { assert_evals_to!( indoc!( @@ -570,7 +570,7 @@ fn list_drop_if_empty_list_of_int() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_drop_if_empty_list() { assert_evals_to!( indoc!( @@ -587,7 +587,7 @@ fn list_drop_if_empty_list() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_drop_if_always_false_for_non_empty_list() { assert_evals_to!( indoc!( @@ -601,7 +601,7 @@ fn list_drop_if_always_false_for_non_empty_list() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_drop_if_always_true_for_non_empty_list() { assert_evals_to!( indoc!( @@ -615,7 +615,7 @@ fn list_drop_if_always_true_for_non_empty_list() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_drop_if_geq3() { assert_evals_to!( indoc!( @@ -643,7 +643,7 @@ fn list_drop_if_string_eq() { } #[test] -#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))] +#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))] fn list_drop_last() { assert_evals_to!( "List.dropLast [1, 2, 3]", @@ -3800,6 +3800,9 @@ mod pattern_match { #[cfg(feature = "gen-wasm")] use crate::helpers::wasm::assert_evals_to; + #[cfg(feature = "gen-dev")] + use crate::helpers::dev::assert_evals_to; + use super::RocList; #[test]