mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
use zig's decref instead of an LLVM implementation
This commit is contained in:
parent
59c63ef3a8
commit
5cb7dbd3cc
5 changed files with 34 additions and 104 deletions
|
@ -1,4 +1,5 @@
|
|||
use crate::debug_info_init;
|
||||
use crate::llvm::bitcode::{self, call_void_bitcode_fn};
|
||||
use crate::llvm::build::{
|
||||
add_func, cast_basic_basic, cast_block_of_memory_to_tag, get_tag_id, get_tag_id_non_recursive,
|
||||
tag_pointer_clear_tag_id, Env, FAST_CALL_CONV, LLVM_SADD_WITH_OVERFLOW_I32,
|
||||
|
@ -227,112 +228,26 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
}
|
||||
};
|
||||
|
||||
let refcount = refcount_ptr.get_refcount(env);
|
||||
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
||||
|
||||
let is_static_allocation = builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
refcount,
|
||||
env.ptr_int().const_zero(),
|
||||
"is_static_allocation",
|
||||
// has to be non-zero, or the deallocation is skipped
|
||||
let data_bytes = env.ptr_int().const_int(1, false);
|
||||
|
||||
call_void_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
env.builder.build_bitcast(
|
||||
parent.get_nth_param(0).unwrap(),
|
||||
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||
"foo",
|
||||
),
|
||||
data_bytes.into(),
|
||||
alignment.into(),
|
||||
],
|
||||
roc_builtins::bitcode::UTILS_DECREF,
|
||||
);
|
||||
|
||||
// build blocks
|
||||
let branch_block = ctx.append_basic_block(parent, "branch");
|
||||
let then_block = ctx.append_basic_block(parent, "then");
|
||||
let else_block = ctx.append_basic_block(parent, "else");
|
||||
let return_block = ctx.append_basic_block(parent, "return");
|
||||
|
||||
builder.build_conditional_branch(is_static_allocation, return_block, branch_block);
|
||||
|
||||
let add_intrinsic = match env.ptr_bytes {
|
||||
8 => LLVM_SADD_WITH_OVERFLOW_I64,
|
||||
4 => LLVM_SADD_WITH_OVERFLOW_I32,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let add_with_overflow;
|
||||
|
||||
{
|
||||
builder.position_at_end(branch_block);
|
||||
|
||||
add_with_overflow = env
|
||||
.call_intrinsic(
|
||||
add_intrinsic,
|
||||
&[
|
||||
refcount.into(),
|
||||
refcount_type.const_int(-1_i64 as u64, true).into(),
|
||||
],
|
||||
)
|
||||
.into_struct_value();
|
||||
|
||||
let has_overflowed = builder
|
||||
.build_extract_value(add_with_overflow, 1, "has_overflowed")
|
||||
.unwrap();
|
||||
|
||||
let has_overflowed_comparison = builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
has_overflowed.into_int_value(),
|
||||
ctx.bool_type().const_int(1_u64, false),
|
||||
"has_overflowed",
|
||||
);
|
||||
|
||||
// TODO what would be most optimial for the branch predictor
|
||||
//
|
||||
// are most refcounts 1 most of the time? or not?
|
||||
builder.build_conditional_branch(has_overflowed_comparison, then_block, else_block);
|
||||
}
|
||||
|
||||
// build then block
|
||||
{
|
||||
builder.position_at_end(then_block);
|
||||
if !env.is_gen_test {
|
||||
let ptr = builder.build_pointer_cast(
|
||||
refcount_ptr.value,
|
||||
ctx.i8_type().ptr_type(AddressSpace::Generic),
|
||||
"cast_to_i8_ptr",
|
||||
);
|
||||
|
||||
match alignment {
|
||||
n if env.ptr_bytes == n => {
|
||||
// the refcount ptr is also the ptr to the allocated region
|
||||
env.call_dealloc(ptr, alignment);
|
||||
}
|
||||
n if 2 * env.ptr_bytes == n => {
|
||||
// we need to step back another ptr_bytes to get the allocated ptr
|
||||
let allocated = Self::from_ptr_to_data(env, ptr);
|
||||
env.call_dealloc(allocated.value, alignment);
|
||||
}
|
||||
n => unreachable!("invalid extra_bytes {:?}", n),
|
||||
}
|
||||
}
|
||||
builder.build_unconditional_branch(return_block);
|
||||
}
|
||||
|
||||
// build else block
|
||||
{
|
||||
builder.position_at_end(else_block);
|
||||
|
||||
let max = builder.build_int_compare(
|
||||
IntPredicate::EQ,
|
||||
refcount,
|
||||
refcount_type.const_int(REFCOUNT_MAX as u64, false),
|
||||
"refcount_max_check",
|
||||
);
|
||||
let decremented = builder
|
||||
.build_extract_value(add_with_overflow, 0, "decrement_refcount")
|
||||
.unwrap()
|
||||
.into_int_value();
|
||||
let selected = builder.build_select(max, refcount, decremented, "select_refcount");
|
||||
|
||||
refcount_ptr.set_refcount(env, selected.into_int_value());
|
||||
|
||||
builder.build_unconditional_branch(return_block);
|
||||
}
|
||||
|
||||
{
|
||||
builder.position_at_end(return_block);
|
||||
builder.build_return(None);
|
||||
}
|
||||
builder.build_return(None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue