diff --git a/compiler/builtins/bitcode/src/utils.zig b/compiler/builtins/bitcode/src/utils.zig index 6877bd85d1..67240bdb2d 100644 --- a/compiler/builtins/bitcode/src/utils.zig +++ b/compiler/builtins/bitcode/src/utils.zig @@ -118,11 +118,12 @@ pub fn decrefC( } pub fn decrefCheckNullC( - bytes_or_null: ?[*]isize, + bytes_or_null: ?[*]u8, alignment: u32, ) callconv(.C) void { if (bytes_or_null) |bytes| { - return @call(.{ .modifier = always_inline }, decref_ptr_to_refcount, .{ bytes, alignment }); + const isizes: [*]isize = @ptrCast([*]isize, @alignCast(@sizeOf(isize), bytes)); + return @call(.{ .modifier = always_inline }, decref_ptr_to_refcount, .{ isizes - 1, alignment }); } } diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index b8c9b922e8..71da6f4bef 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -8,10 +8,10 @@ use crate::llvm::build_dict::{ }; use crate::llvm::build_hash::generic_hash; use crate::llvm::build_list::{ - allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains, - list_drop, list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len, - list_map, list_map2, list_map3, list_map_with_index, list_prepend, list_range, list_repeat, - list_reverse, list_set, list_single, list_sort_with, list_swap, + self, allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, + list_contains, list_drop, list_get_unsafe, list_join, list_keep_errs, list_keep_if, + list_keep_oks, list_len, list_map, list_map2, list_map3, list_map_with_index, list_prepend, + list_range, list_repeat, list_reverse, list_set, list_single, list_sort_with, list_swap, }; use crate::llvm::build_str::{ empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int, @@ -2538,23 +2538,13 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>( DecRef(symbol) => { let (value, layout) = load_symbol_and_layout(scope, symbol); + let alignment = layout.alignment_bytes(env.ptr_bytes); + match layout { Layout::Builtin(Builtin::List(_)) => { debug_assert!(value.is_struct_value()); - // because of how we insert DECREF for lists, we can't guarantee that - // the list is non-empty. When the list is empty, the pointer to the - // elements is NULL, and trying to get to the RC address will - // underflow, causing a segfault. Therefore, in this case we must - // manually check that the list is non-empty - let refcount_ptr = PointerToRefcount::from_list_wrapper( - env, - value.into_struct_value(), - ); - - let length = list_len(env.builder, value.into_struct_value()); - - decrement_with_size_check(env, parent, length, *layout, refcount_ptr); + build_list::decref(env, value.into_struct_value(), alignment); } Layout::Builtin(Builtin::Dict(_, _)) | Layout::Builtin(Builtin::Set(_)) => { debug_assert!(value.is_struct_value()); diff --git a/compiler/gen_llvm/src/llvm/build_list.rs b/compiler/gen_llvm/src/llvm/build_list.rs index 8cbdd71083..2fe94d4cb5 100644 --- a/compiler/gen_llvm/src/llvm/build_list.rs +++ b/compiler/gen_llvm/src/llvm/build_list.rs @@ -1136,3 +1136,17 @@ pub fn store_list<'a, 'ctx, 'env>( "cast_collection", ) } + +pub fn decref<'a, 'ctx, 'env>( + env: &Env<'a, 'ctx, 'env>, + wrapper_struct: StructValue<'ctx>, + alignment: u32, +) { + let (_, pointer) = load_list( + env.builder, + wrapper_struct, + env.context.i8_type().ptr_type(AddressSpace::Generic), + ); + + crate::llvm::refcounting::decref_pointer_check_null(env, pointer, alignment); +} diff --git a/compiler/gen_llvm/src/llvm/refcounting.rs b/compiler/gen_llvm/src/llvm/refcounting.rs index bc730e187e..d65ebff5e3 100644 --- a/compiler/gen_llvm/src/llvm/refcounting.rs +++ b/compiler/gen_llvm/src/llvm/refcounting.rs @@ -230,7 +230,7 @@ impl<'ctx> PointerToRefcount<'ctx> { } } -pub fn decref_pointer<'a, 'ctx, 'env>( +fn decref_pointer<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, pointer: PointerValue<'ctx>, alignment: u32, @@ -262,8 +262,8 @@ pub fn decref_pointer_check_null<'a, 'ctx, 'env>( &[ env.builder.build_bitcast( pointer, - env.ptr_int().ptr_type(AddressSpace::Generic), - "to_isize_ptr", + env.context.i8_type().ptr_type(AddressSpace::Generic), + "to_i8_ptr", ), alignment.into(), ],