mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
add llvm refcounting and fix memory leak
This commit is contained in:
parent
7a927b6192
commit
146dff5446
4 changed files with 102 additions and 26 deletions
|
@ -2784,12 +2784,13 @@ 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);
|
||||
// build_list::decref(env, value.into_struct_value(), alignment);
|
||||
todo!()
|
||||
}
|
||||
|
||||
lay if lay.is_refcounted() => {
|
||||
|
|
|
@ -45,6 +45,21 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
Self { value }
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// the invariant is that the given pointer really points to the refcount,
|
||||
/// not the data, and only is the start of the allocated buffer if the
|
||||
/// alignment works out that way.
|
||||
pub unsafe fn from_ptr_int<'a, 'env>(env: &Env<'a, 'ctx, 'env>, int: IntValue<'ctx>) -> Self {
|
||||
let refcount_type = env.ptr_int();
|
||||
let refcount_ptr_type = refcount_type.ptr_type(AddressSpace::default());
|
||||
let value = env
|
||||
.builder
|
||||
.build_int_to_ptr(int, refcount_ptr_type, "to_refcount_ptr");
|
||||
|
||||
Self { value }
|
||||
}
|
||||
|
||||
pub fn from_ptr_to_data<'a, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
data_ptr: PointerValue<'ctx>,
|
||||
|
@ -691,22 +706,24 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
let parent = fn_val;
|
||||
let original_wrapper = arg_val.into_struct_value();
|
||||
|
||||
let len = list_capacity(builder, original_wrapper);
|
||||
let capacity = list_capacity(builder, original_wrapper);
|
||||
|
||||
let is_non_empty = builder.build_int_compare(
|
||||
IntPredicate::UGT,
|
||||
len,
|
||||
IntPredicate::SGT,
|
||||
capacity,
|
||||
env.ptr_int().const_zero(),
|
||||
"len > 0",
|
||||
"cap > 0",
|
||||
);
|
||||
|
||||
// build blocks
|
||||
let modification_block = ctx.append_basic_block(parent, "modification_block");
|
||||
let modification_list_block = ctx.append_basic_block(parent, "modification_list_block");
|
||||
let check_slice_block = ctx.append_basic_block(parent, "check_slice_block");
|
||||
let modification_slice_block = ctx.append_basic_block(parent, "modification_slice_block");
|
||||
let cont_block = ctx.append_basic_block(parent, "modify_rc_list_cont");
|
||||
|
||||
builder.build_conditional_branch(is_non_empty, modification_block, cont_block);
|
||||
builder.build_conditional_branch(is_non_empty, modification_list_block, check_slice_block);
|
||||
|
||||
builder.position_at_end(modification_block);
|
||||
builder.position_at_end(modification_list_block);
|
||||
|
||||
if layout_interner.contains_refcounted(element_layout) {
|
||||
let ptr_type = basic_type_from_layout(env, layout_interner, element_layout)
|
||||
|
@ -743,6 +760,59 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
|
||||
builder.build_unconditional_branch(cont_block);
|
||||
|
||||
builder.position_at_end(check_slice_block);
|
||||
|
||||
let is_seamless_slice = builder.build_int_compare(
|
||||
IntPredicate::SLT,
|
||||
capacity,
|
||||
env.ptr_int().const_zero(),
|
||||
"cap < 0",
|
||||
);
|
||||
builder.build_conditional_branch(is_seamless_slice, modification_slice_block, cont_block);
|
||||
|
||||
builder.position_at_end(modification_slice_block);
|
||||
|
||||
if layout_interner.contains_refcounted(element_layout) {
|
||||
let ptr_type = basic_type_from_layout(env, layout_interner, element_layout)
|
||||
.ptr_type(AddressSpace::default());
|
||||
|
||||
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
|
||||
|
||||
let loop_fn = |layout_interner, _index, element| {
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode.to_call_mode(fn_val),
|
||||
element,
|
||||
element_layout,
|
||||
);
|
||||
};
|
||||
|
||||
incrementing_elem_loop(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
element_layout,
|
||||
ptr,
|
||||
len,
|
||||
"modify_rc_index",
|
||||
loop_fn,
|
||||
);
|
||||
}
|
||||
|
||||
// a slices refcount is `capacity << 1`
|
||||
let refcount_ptr_int = builder.build_left_shift(
|
||||
capacity,
|
||||
env.ptr_int().const_int(1, false),
|
||||
"extract_refcount_from_capacity",
|
||||
);
|
||||
let refcount_ptr = unsafe { PointerToRefcount::from_ptr_int(env, refcount_ptr_int) };
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
||||
|
||||
builder.build_unconditional_branch(cont_block);
|
||||
|
||||
builder.position_at_end(cont_block);
|
||||
|
||||
// this function returns void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue