update list decref to know about seamless slices

This commit is contained in:
Brendan Hansknecht 2023-03-11 14:43:12 -08:00
parent 146dff5446
commit f9274e575b
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
2 changed files with 54 additions and 12 deletions

View file

@ -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() => {

View file

@ -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,
);
}