diff --git a/compiler/builtins/bitcode/src/list.zig b/compiler/builtins/bitcode/src/list.zig index d83f888e22..6e6351a6e7 100644 --- a/compiler/builtins/bitcode/src/list.zig +++ b/compiler/builtins/bitcode/src/list.zig @@ -141,14 +141,14 @@ const Caller1 = fn (?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void; const Caller2 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void; const Caller3 = fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void; -pub fn listReverse(list: RocList, alignment: u32, element_width: usize) callconv(.C) RocList { +pub fn listReverse(list: RocList, alignment: u32, element_width: usize, update_mode: UpdateMode) callconv(.C) RocList { if (list.bytes) |source_ptr| { const size = list.len(); var i: usize = 0; const end: usize = size - 1; - if (list.isUnique()) { + if (update_mode == .InPlace or list.isUnique()) { // Working from the front and back so // we only need to go ~(n / 2) iterations. diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index 4720653867..0694299329 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -4930,7 +4930,7 @@ fn run_low_level<'a, 'ctx, 'env>( let (list, list_layout) = load_symbol_and_layout(scope, &args[0]); - list_reverse(env, list, list_layout) + list_reverse(env, list, list_layout, update_mode) } ListConcat => { debug_assert_eq!(args.len(), 2); diff --git a/compiler/gen_llvm/src/llvm/build_list.rs b/compiler/gen_llvm/src/llvm/build_list.rs index 5c42d24c52..d46d454458 100644 --- a/compiler/gen_llvm/src/llvm/build_list.rs +++ b/compiler/gen_llvm/src/llvm/build_list.rs @@ -172,6 +172,7 @@ pub fn list_reverse<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, list: BasicValueEnum<'ctx>, list_layout: &Layout<'a>, + update_mode: UpdateMode, ) -> BasicValueEnum<'ctx> { let element_layout = match *list_layout { Layout::Builtin(Builtin::EmptyList) => { @@ -190,6 +191,7 @@ pub fn list_reverse<'a, 'ctx, 'env>( pass_list_cc(env, list), env.alignment_intvalue(&element_layout), layout_width(env, &element_layout), + pass_update_mode(env, update_mode), ], bitcode::LIST_REVERSE, ) diff --git a/compiler/mono/src/alias_analysis.rs b/compiler/mono/src/alias_analysis.rs index f0dc294a95..b218875425 100644 --- a/compiler/mono/src/alias_analysis.rs +++ b/compiler/mono/src/alias_analysis.rs @@ -918,6 +918,17 @@ fn lowlevel_spec( let new_cell = builder.add_new_heap_cell(block)?; builder.add_make_tuple(block, &[new_cell, bag]) } + ListReverse => { + let list = env.symbols[&arguments[0]]; + + let bag = builder.add_get_tuple_field(block, list, LIST_BAG_INDEX)?; + let cell = builder.add_get_tuple_field(block, list, LIST_CELL_INDEX)?; + + let _unit = builder.add_update(block, update_mode_var, cell)?; + + let new_cell = builder.add_new_heap_cell(block)?; + builder.add_make_tuple(block, &[new_cell, bag]) + } ListAppend => { let list = env.symbols[&arguments[0]]; let to_insert = env.symbols[&arguments[1]];