@@ -2144,7 +2144,9 @@ pub const MonoLlvmCodeGen = struct {
21442144 .list_prepend = > try self .emitListPrepend (target , arg_locals , unique_args ),
21452145 .list_sublist , .list_drop_first , .list_drop_last , .list_take_first , .list_take_last = > try self .emitListSublist (target , op , arg_locals , unique_args ),
21462146 .list_drop_at = > try self .emitListDropAt (target , arg_locals , unique_args ),
2147+ .list_swap = > try self .emitListSwap (target , arg_locals , unique_args ),
21472148 .list_set = > try self .emitListSet (target , arg_locals , unique_args ),
2149+ .list_replace_unsafe = > try self .emitListReplaceUnsafe (target , arg_locals , unique_args ),
21482150 .list_map_can_reuse = > try self .emitListMapCanReuse (target , arg_locals ),
21492151 .list_map_cast_unsafe = > try self .copyBytes (self .slot (target ).ptr , self .slot (arg_locals [0 ]).ptr , self .slot (target ).size , self .slot (target ).alignment ),
21502152 .list_map_extract_unsafe = > try self .emitListMapExtractUnsafe (target , arg_locals ),
@@ -3274,6 +3276,22 @@ pub const MonoLlvmCodeGen = struct {
32743276 try self .callBuiltinVoid ("roc_builtins_list_drop_at" , call_args .types .items , call_args .values .items );
32753277 }
32763278
3279+ fn emitListSwap (self : * MonoLlvmCodeGen , target : LocalId , args : []const LocalId , unique_args : u64 ) Error ! void {
3280+ const builder = self .builder orelse return error .CompilationFailed ;
3281+ const abi = self .layouts ().builtinListAbi (self .localLayout (args [0 ]));
3282+ var call_args = try self .rocListArgs1 (args [0 ]);
3283+ defer call_args .deinit (self .allocator );
3284+ try call_args .prepend (self .allocator , try self .ptrType (), self .slot (target ).ptr );
3285+ try call_args .append (self .allocator , .i32 , builder .intValue (.i32 , abi .elem_alignment ) catch return error .OutOfMemory );
3286+ try call_args .append (self .allocator , self .ptrSizedIntType (), builder .intValue (self .ptrSizedIntType (), abi .elem_size ) catch return error .OutOfMemory );
3287+ try call_args .append (self .allocator , .i64 , try self .coerceScalar (try self .loadScalar (self .slot (args [1 ]).ptr , self .localLayout (args [1 ])), .i64 , false ));
3288+ try call_args .append (self .allocator , .i64 , try self .coerceScalar (try self .loadScalar (self .slot (args [2 ]).ptr , self .localLayout (args [2 ])), .i64 , false ));
3289+ try self .appendListElementRcArgs (& call_args , abi , true , true );
3290+ try self .appendUpdateModeArg (& call_args , unique_args );
3291+ try call_args .append (self .allocator , try self .ptrType (), self .rocOps ());
3292+ try self .callBuiltinVoid ("roc_builtins_list_swap" , call_args .types .items , call_args .values .items );
3293+ }
3294+
32773295 fn emitListSet (self : * MonoLlvmCodeGen , target : LocalId , args : []const LocalId , unique_args : u64 ) Error ! void {
32783296 const builder = self .builder orelse return error .CompilationFailed ;
32793297 const abi = self .layouts ().builtinListAbi (self .localLayout (args [0 ]));
@@ -3291,6 +3309,44 @@ pub const MonoLlvmCodeGen = struct {
32913309 try self .callBuiltinVoid ("roc_builtins_list_replace" , call_args .types .items , call_args .values .items );
32923310 }
32933311
3312+ fn emitListReplaceUnsafe (self : * MonoLlvmCodeGen , target : LocalId , args : []const LocalId , unique_args : u64 ) Error ! void {
3313+ const builder = self .builder orelse return error .CompilationFailed ;
3314+ // The result is a { list, prev } record. Reuse roc_builtins_list_replace
3315+ // and aim its (out_list, out_element) outputs directly at the record's
3316+ // fields, disambiguated by layout tag like the dev backend does.
3317+ const record_layout_val = self .layoutValue (self .localLayout (target ));
3318+ if (record_layout_val .tag != .struct_ ) return error .CompilationFailed ;
3319+ const rec_idx = record_layout_val .getStruct ().idx ;
3320+ const f0_layout = self .layoutValue (self .layouts ().getStructFieldLayoutByOriginalIndex (rec_idx , 0 ));
3321+ const f0_offset = self .layouts ().getStructFieldOffsetByOriginalIndex (rec_idx , 0 );
3322+ const f1_offset = self .layouts ().getStructFieldOffsetByOriginalIndex (rec_idx , 1 );
3323+ const f0_is_list = f0_layout .tag == .list or f0_layout .tag == .list_of_zst ;
3324+ const list_out_ptr = try self .offsetPtr (self .slot (target ).ptr , if (f0_is_list ) f0_offset else f1_offset );
3325+ const value_out_ptr = try self .offsetPtr (self .slot (target ).ptr , if (f0_is_list ) f1_offset else f0_offset );
3326+
3327+ const abi = self .layouts ().builtinListAbi (self .localLayout (args [0 ]));
3328+ if (abi .elem_size == 0 ) {
3329+ // listReplace would dereference a NULL element pointer for ZST
3330+ // elements; the result list is the input unchanged and the prev
3331+ // field is zero-sized.
3332+ try self .copyBytes (list_out_ptr , self .slot (args [0 ]).ptr , self .slot (args [0 ]).size , self .slot (args [0 ]).alignment );
3333+ return ;
3334+ }
3335+
3336+ var call_args = try self .rocListArgs1 (args [0 ]);
3337+ defer call_args .deinit (self .allocator );
3338+ try call_args .prepend (self .allocator , try self .ptrType (), list_out_ptr );
3339+ try call_args .append (self .allocator , .i32 , builder .intValue (.i32 , abi .elem_alignment ) catch return error .OutOfMemory );
3340+ try call_args .append (self .allocator , .i64 , try self .coerceScalar (try self .loadScalar (self .slot (args [1 ]).ptr , self .localLayout (args [1 ])), .i64 , false ));
3341+ try call_args .append (self .allocator , try self .ptrType (), self .slot (args [2 ]).ptr );
3342+ try call_args .append (self .allocator , self .ptrSizedIntType (), builder .intValue (self .ptrSizedIntType (), abi .elem_size ) catch return error .OutOfMemory );
3343+ try call_args .append (self .allocator , try self .ptrType (), value_out_ptr );
3344+ try self .appendListElementRcArgs (& call_args , abi , true , true );
3345+ try self .appendUpdateModeArg (& call_args , unique_args );
3346+ try call_args .append (self .allocator , try self .ptrType (), self .rocOps ());
3347+ try self .callBuiltinVoid ("roc_builtins_list_replace" , call_args .types .items , call_args .values .items );
3348+ }
3349+
32943350 fn emitListReserve (self : * MonoLlvmCodeGen , target : LocalId , args : []const LocalId , unique_args : u64 ) Error ! void {
32953351 const builder = self .builder orelse return error .CompilationFailed ;
32963352 const abi = self .layouts ().builtinListAbi (self .localLayout (args [0 ]));
0 commit comments