mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
fix list decref
This commit is contained in:
parent
5e68d31afc
commit
cd9b32ba65
4 changed files with 27 additions and 22 deletions
|
@ -118,11 +118,12 @@ pub fn decrefC(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrefCheckNullC(
|
pub fn decrefCheckNullC(
|
||||||
bytes_or_null: ?[*]isize,
|
bytes_or_null: ?[*]u8,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
) callconv(.C) void {
|
) callconv(.C) void {
|
||||||
if (bytes_or_null) |bytes| {
|
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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ use crate::llvm::build_dict::{
|
||||||
};
|
};
|
||||||
use crate::llvm::build_hash::generic_hash;
|
use crate::llvm::build_hash::generic_hash;
|
||||||
use crate::llvm::build_list::{
|
use crate::llvm::build_list::{
|
||||||
allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat, list_contains,
|
self, allocate_list, empty_list, empty_polymorphic_list, list_append, list_concat,
|
||||||
list_drop, list_get_unsafe, list_join, list_keep_errs, list_keep_if, list_keep_oks, list_len,
|
list_contains, list_drop, list_get_unsafe, list_join, list_keep_errs, list_keep_if,
|
||||||
list_map, list_map2, list_map3, list_map_with_index, list_prepend, list_range, list_repeat,
|
list_keep_oks, list_len, list_map, list_map2, list_map3, list_map_with_index, list_prepend,
|
||||||
list_reverse, list_set, list_single, list_sort_with, list_swap,
|
list_range, list_repeat, list_reverse, list_set, list_single, list_sort_with, list_swap,
|
||||||
};
|
};
|
||||||
use crate::llvm::build_str::{
|
use crate::llvm::build_str::{
|
||||||
empty_str, str_concat, str_count_graphemes, str_ends_with, str_from_float, str_from_int,
|
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) => {
|
DecRef(symbol) => {
|
||||||
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
let (value, layout) = load_symbol_and_layout(scope, symbol);
|
||||||
|
|
||||||
|
let alignment = layout.alignment_bytes(env.ptr_bytes);
|
||||||
|
|
||||||
match layout {
|
match layout {
|
||||||
Layout::Builtin(Builtin::List(_)) => {
|
Layout::Builtin(Builtin::List(_)) => {
|
||||||
debug_assert!(value.is_struct_value());
|
debug_assert!(value.is_struct_value());
|
||||||
|
|
||||||
// because of how we insert DECREF for lists, we can't guarantee that
|
build_list::decref(env, value.into_struct_value(), alignment);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
Layout::Builtin(Builtin::Dict(_, _)) | Layout::Builtin(Builtin::Set(_)) => {
|
Layout::Builtin(Builtin::Dict(_, _)) | Layout::Builtin(Builtin::Set(_)) => {
|
||||||
debug_assert!(value.is_struct_value());
|
debug_assert!(value.is_struct_value());
|
||||||
|
|
|
@ -1136,3 +1136,17 @@ pub fn store_list<'a, 'ctx, 'env>(
|
||||||
"cast_collection",
|
"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);
|
||||||
|
}
|
||||||
|
|
|
@ -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>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
@ -262,8 +262,8 @@ pub fn decref_pointer_check_null<'a, 'ctx, 'env>(
|
||||||
&[
|
&[
|
||||||
env.builder.build_bitcast(
|
env.builder.build_bitcast(
|
||||||
pointer,
|
pointer,
|
||||||
env.ptr_int().ptr_type(AddressSpace::Generic),
|
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||||
"to_isize_ptr",
|
"to_i8_ptr",
|
||||||
),
|
),
|
||||||
alignment.into(),
|
alignment.into(),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue