mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
update list decref to know about seamless slices
This commit is contained in:
parent
146dff5446
commit
f9274e575b
2 changed files with 54 additions and 12 deletions
|
@ -2784,13 +2784,12 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
|||
match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Str) => todo!(),
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
// debug_assert!(value.is_struct_value());
|
||||
// let element_layout = layout_interner.get(element_layout);
|
||||
// let alignment =
|
||||
// element_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
debug_assert!(value.is_struct_value());
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let alignment =
|
||||
element_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
|
||||
// build_list::decref(env, value.into_struct_value(), alignment);
|
||||
todo!()
|
||||
build_list::decref(env, value.into_struct_value(), alignment, parent);
|
||||
}
|
||||
|
||||
lay if lay.is_refcounted() => {
|
||||
|
|
|
@ -801,13 +801,56 @@ pub(crate) fn decref<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
wrapper_struct: StructValue<'ctx>,
|
||||
alignment: u32,
|
||||
parent: FunctionValue<'ctx>,
|
||||
) {
|
||||
// TODO: This definitely needs to handle seamless slices
|
||||
let (_, pointer) = load_list(
|
||||
env.builder,
|
||||
wrapper_struct,
|
||||
env.context.i8_type().ptr_type(AddressSpace::default()),
|
||||
let builder = env.builder;
|
||||
let ctx = env.context;
|
||||
|
||||
let capacity = list_capacity(builder, wrapper_struct);
|
||||
let is_regular_list = builder.build_int_compare(
|
||||
IntPredicate::SGE,
|
||||
capacity,
|
||||
env.ptr_int().const_zero(),
|
||||
"cap >= 0",
|
||||
);
|
||||
|
||||
crate::llvm::refcounting::decref_pointer_check_null(env, pointer, alignment);
|
||||
let get_list_ptr_block = ctx.append_basic_block(parent, "get_list_ptr");
|
||||
let get_slice_ptr_block = ctx.append_basic_block(parent, "get_slice_ptr");
|
||||
let decref_block = ctx.append_basic_block(parent, "decref");
|
||||
builder.build_conditional_branch(is_regular_list, get_list_ptr_block, get_slice_ptr_block);
|
||||
|
||||
builder.position_at_end(get_list_ptr_block);
|
||||
let ptr_type = env.context.i8_type().ptr_type(AddressSpace::default());
|
||||
let (_, list_ptr) = load_list(builder, wrapper_struct, ptr_type);
|
||||
builder.build_unconditional_branch(decref_block);
|
||||
|
||||
builder.position_at_end(get_slice_ptr_block);
|
||||
let refcount_ptr_int = builder.build_left_shift(
|
||||
capacity,
|
||||
env.ptr_int().const_int(1, false),
|
||||
"extract_refcount_from_capacity",
|
||||
);
|
||||
// TODO: adding one here feels silly.
|
||||
// We should probably expose a zig builtin to directly deal with the refcount pointer.
|
||||
// Instead we add one and then zig subtracts one.
|
||||
let slice_ptr_int = builder.build_int_add(
|
||||
refcount_ptr_int,
|
||||
env.ptr_int().const_int(1, false),
|
||||
"inc_refcount_ptr",
|
||||
);
|
||||
let slice_ptr = builder.build_int_to_ptr(slice_ptr_int, ptr_type, "to_slice_ptr");
|
||||
builder.build_unconditional_branch(decref_block);
|
||||
|
||||
builder.position_at_end(decref_block);
|
||||
let result = builder.build_phi(ptr_type, "branch");
|
||||
result.add_incoming(&[
|
||||
(&list_ptr, get_list_ptr_block),
|
||||
(&slice_ptr, get_slice_ptr_block),
|
||||
]);
|
||||
|
||||
crate::llvm::refcounting::decref_pointer_check_null(
|
||||
env,
|
||||
result.as_basic_value().into_pointer_value(),
|
||||
alignment,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue