mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +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
|
@ -33,11 +33,12 @@ pub fn build(b: *Builder) void {
|
|||
// LLVM IR 32-bit (wasm)
|
||||
var target = b.standardTargetOptions(.{});
|
||||
|
||||
// 32-bit x86, useful for debuggin
|
||||
// target.os_tag = std.Target.Os.Tag.linux;
|
||||
// target.cpu_arch = std.Target.Cpu.Arch.i386;
|
||||
// target.abi = std.Target.Abi.musl;
|
||||
|
||||
// Thisis what we want eventually, currently segfaults
|
||||
// This is what we want eventually, currently segfaults
|
||||
target.os_tag = std.Target.Os.Tag.wasi;
|
||||
target.cpu_arch = std.Target.Cpu.Arch.wasm32;
|
||||
target.abi = std.Target.Abi.none;
|
||||
|
|
|
@ -109,6 +109,7 @@ comptime {
|
|||
const utils = @import("utils.zig");
|
||||
comptime {
|
||||
exportUtilsFn(utils.test_panic, "test_panic");
|
||||
exportUtilsFn(utils.decrefC, "decref");
|
||||
|
||||
@export(utils.panic, .{ .name = "roc_builtins.utils." ++ "panic", .linkage = .Weak });
|
||||
}
|
||||
|
|
|
@ -104,6 +104,18 @@ pub const IntWidth = enum(u8) {
|
|||
Usize,
|
||||
};
|
||||
|
||||
pub fn decrefC(
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
alignment: u32,
|
||||
) callconv(.C) void {
|
||||
// IMPORTANT: bytes_or_null is this case is expected to be a pointer to the refcount
|
||||
// (NOT the start of the data, or the start of the allocation)
|
||||
if (bytes_or_null) |bytes| {
|
||||
return @call(.{ .modifier = always_inline }, decref, .{ bytes + @sizeOf(usize), data_bytes, alignment });
|
||||
}
|
||||
}
|
||||
|
||||
pub fn decref(
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
|
|
|
@ -82,3 +82,4 @@ pub const DEC_MUL_WITH_OVERFLOW: &str = "roc_builtins.dec.mul_with_overflow";
|
|||
pub const DEC_DIV: &str = "roc_builtins.dec.div";
|
||||
|
||||
pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
|
||||
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
||||
|
|
|
@ -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,113 +228,27 @@ 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);
|
||||
|
||||
// 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,
|
||||
call_void_bitcode_fn(
|
||||
env,
|
||||
&[
|
||||
refcount.into(),
|
||||
refcount_type.const_int(-1_i64 as u64, true).into(),
|
||||
env.builder.build_bitcast(
|
||||
parent.get_nth_param(0).unwrap(),
|
||||
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||
"foo",
|
||||
),
|
||||
data_bytes.into(),
|
||||
alignment.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",
|
||||
roc_builtins::bitcode::UTILS_DECREF,
|
||||
);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_refcount_struct<'a, 'ctx, 'env>(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue