mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 15:03:46 +00:00
add lowlevel to inc/dec a data pointer
This commit is contained in:
parent
a61e7a696d
commit
cf54304cf4
13 changed files with 90 additions and 28 deletions
|
@ -974,7 +974,7 @@ test "listConcat: non-unique with unique overlapping" {
|
|||
var bytes: [*]u8 = @ptrCast([*]u8, nonUnique.bytes);
|
||||
const ptr_width = @sizeOf(usize);
|
||||
const refcount_ptr = @ptrCast([*]isize, @alignCast(ptr_width, bytes) - ptr_width);
|
||||
utils.increfC(&refcount_ptr[0], 1);
|
||||
utils.increfRcPtrC(&refcount_ptr[0], 1);
|
||||
defer nonUnique.decref(@sizeOf(u8)); // listConcat will dec the other refcount
|
||||
|
||||
var unique = RocList.fromSlice(u8, ([_]u8{ 2, 3, 4 })[0..]);
|
||||
|
|
|
@ -173,8 +173,10 @@ comptime {
|
|||
// Utils
|
||||
comptime {
|
||||
exportUtilsFn(utils.test_panic, "test_panic");
|
||||
exportUtilsFn(utils.increfC, "incref");
|
||||
exportUtilsFn(utils.decrefC, "decref");
|
||||
exportUtilsFn(utils.increfRcPtrC, "incref_rc_ptr");
|
||||
exportUtilsFn(utils.decrefRcPtrC, "decref_rc_ptr");
|
||||
exportUtilsFn(utils.increfDataPtrC, "incref_data_ptr");
|
||||
exportUtilsFn(utils.decrefDataPtrC, "decref_data_ptr");
|
||||
exportUtilsFn(utils.isUnique, "is_unique");
|
||||
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
|
||||
exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount");
|
||||
|
|
|
@ -162,7 +162,7 @@ pub const RocStr = extern struct {
|
|||
const ref_ptr = self.getRefcountPtr();
|
||||
if (ref_ptr != null) {
|
||||
const isizes: [*]isize = @ptrCast([*]isize, @alignCast(@alignOf(isize), ref_ptr));
|
||||
utils.increfC(@ptrCast(*isize, isizes - 1), @intCast(isize, n));
|
||||
utils.increfRcPtrC(@ptrCast(*isize, isizes - 1), @intCast(isize, n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ const Refcount = enum {
|
|||
|
||||
const RC_TYPE = Refcount.normal;
|
||||
|
||||
pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
|
||||
pub fn increfRcPtrC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
|
||||
if (RC_TYPE == Refcount.none) return;
|
||||
// Ensure that the refcount is not whole program lifetime.
|
||||
if (ptr_to_refcount.* != REFCOUNT_MAX_ISIZE) {
|
||||
|
@ -165,7 +165,7 @@ pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn decrefC(
|
||||
pub fn decrefRcPtrC(
|
||||
bytes_or_null: ?[*]isize,
|
||||
alignment: u32,
|
||||
) callconv(.C) void {
|
||||
|
@ -188,6 +188,36 @@ pub fn decrefCheckNullC(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn decrefDataPtrC(
|
||||
bytes_or_null: ?[*]isize,
|
||||
alignment: u32,
|
||||
) callconv(.C) void {
|
||||
var bytes = bytes_or_null orelse return;
|
||||
|
||||
const ptr = @ptrToInt(bytes);
|
||||
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
|
||||
const masked_ptr = ptr & ~tag_mask;
|
||||
|
||||
const isizes: [*]isize = @intToPtr([*]isize, masked_ptr);
|
||||
|
||||
return decrefRcPtrC(isizes - 1, alignment);
|
||||
}
|
||||
|
||||
pub fn increfDataPtrC(
|
||||
bytes_or_null: ?[*]isize,
|
||||
inc_amount: isize,
|
||||
) callconv(.C) void {
|
||||
var bytes = bytes_or_null orelse return;
|
||||
|
||||
const ptr = @ptrToInt(bytes);
|
||||
const tag_mask: usize = if (@sizeOf(usize) == 8) 0b111 else 0b11;
|
||||
const masked_ptr = ptr & ~tag_mask;
|
||||
|
||||
const isizes: *isize = @intToPtr(*isize, masked_ptr - @sizeOf(usize));
|
||||
|
||||
return increfRcPtrC(isizes, inc_amount);
|
||||
}
|
||||
|
||||
pub fn decref(
|
||||
bytes_or_null: ?[*]u8,
|
||||
data_bytes: usize,
|
||||
|
@ -363,13 +393,13 @@ pub const UpdateMode = enum(u8) {
|
|||
test "increfC, refcounted data" {
|
||||
var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17;
|
||||
var ptr_to_refcount: *isize = &mock_rc;
|
||||
increfC(ptr_to_refcount, 2);
|
||||
increfRcPtrC(ptr_to_refcount, 2);
|
||||
try std.testing.expectEqual(mock_rc, REFCOUNT_ONE_ISIZE + 19);
|
||||
}
|
||||
|
||||
test "increfC, static data" {
|
||||
var mock_rc: isize = REFCOUNT_MAX_ISIZE;
|
||||
var ptr_to_refcount: *isize = &mock_rc;
|
||||
increfC(ptr_to_refcount, 2);
|
||||
increfRcPtrC(ptr_to_refcount, 2);
|
||||
try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE);
|
||||
}
|
||||
|
|
|
@ -376,8 +376,10 @@ pub const DEC_MUL_SATURATED: &str = "roc_builtins.dec.mul_saturated";
|
|||
|
||||
pub const UTILS_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
|
||||
pub const UTILS_ALLOCATE_WITH_REFCOUNT: &str = "roc_builtins.utils.allocate_with_refcount";
|
||||
pub const UTILS_INCREF: &str = "roc_builtins.utils.incref";
|
||||
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
||||
pub const UTILS_INCREF_RC_PTR: &str = "roc_builtins.utils.incref_rc_ptr";
|
||||
pub const UTILS_DECREF_RC_PTR: &str = "roc_builtins.utils.decref_rc_ptr";
|
||||
pub const UTILS_INCREF_DATA_PTR: &str = "roc_builtins.utils.incref_data_ptr";
|
||||
pub const UTILS_DECREF_DATA_PTR: &str = "roc_builtins.utils.decref_data_ptr";
|
||||
pub const UTILS_IS_UNIQUE: &str = "roc_builtins.utils.is_unique";
|
||||
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";
|
||||
|
||||
|
|
|
@ -86,8 +86,10 @@ macro_rules! map_symbol_to_lowlevel_and_arity {
|
|||
LowLevel::Hash => unimplemented!(),
|
||||
LowLevel::PtrCast => unimplemented!(),
|
||||
LowLevel::PtrWrite => unimplemented!(),
|
||||
LowLevel::RefCountInc => unimplemented!(),
|
||||
LowLevel::RefCountDec => unimplemented!(),
|
||||
LowLevel::RefCountIncRcPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecRcPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIncDataPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecDataPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||
|
||||
// these are not implemented, not sure why
|
||||
|
|
|
@ -1111,16 +1111,30 @@ trait Backend<'a> {
|
|||
|
||||
self.build_ptr_write(*sym, args[0], args[1], element_layout);
|
||||
}
|
||||
LowLevel::RefCountDec => self.build_fn_call(
|
||||
LowLevel::RefCountDecRcPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF.to_string(),
|
||||
bitcode::UTILS_DECREF_RC_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountInc => self.build_fn_call(
|
||||
LowLevel::RefCountIncRcPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_INCREF.to_string(),
|
||||
bitcode::UTILS_INCREF_RC_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountDecDataPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_DECREF_DATA_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
),
|
||||
LowLevel::RefCountIncDataPtr => self.build_fn_call(
|
||||
sym,
|
||||
bitcode::UTILS_INCREF_DATA_PTR.to_string(),
|
||||
args,
|
||||
arg_layouts,
|
||||
ret_layout,
|
||||
|
|
|
@ -1247,7 +1247,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
unreachable!("The {:?} operation is turned into mono Expr", op)
|
||||
}
|
||||
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec => {
|
||||
PtrCast | PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr
|
||||
| RefCountDecDataPtr => {
|
||||
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||
}
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ fn incref_pointer<'a, 'ctx, 'env>(
|
|||
.into(),
|
||||
amount.into(),
|
||||
],
|
||||
roc_builtins::bitcode::UTILS_INCREF,
|
||||
roc_builtins::bitcode::UTILS_INCREF_RC_PTR,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,7 @@ fn decref_pointer<'a, 'ctx, 'env>(
|
|||
.into(),
|
||||
alignment.into(),
|
||||
],
|
||||
roc_builtins::bitcode::UTILS_DECREF,
|
||||
roc_builtins::bitcode::UTILS_DECREF_RC_PTR,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1947,8 +1947,14 @@ impl<'a> LowLevelCall<'a> {
|
|||
self.load_args(backend);
|
||||
backend.code_builder.i32_eqz();
|
||||
}
|
||||
RefCountInc => self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF),
|
||||
RefCountDec => self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF),
|
||||
RefCountIncRcPtr => self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF_RC_PTR),
|
||||
RefCountDecRcPtr => self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF_RC_PTR),
|
||||
RefCountIncDataPtr => {
|
||||
self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF_DATA_PTR)
|
||||
}
|
||||
RefCountDecDataPtr => {
|
||||
self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF_DATA_PTR)
|
||||
}
|
||||
RefCountIsUnique => self.load_args_and_call_zig(backend, bitcode::UTILS_IS_UNIQUE),
|
||||
|
||||
PtrCast => {
|
||||
|
|
|
@ -116,8 +116,10 @@ pub enum LowLevel {
|
|||
Hash,
|
||||
PtrCast,
|
||||
PtrWrite,
|
||||
RefCountInc,
|
||||
RefCountDec,
|
||||
RefCountIncRcPtr,
|
||||
RefCountDecRcPtr,
|
||||
RefCountIncDataPtr,
|
||||
RefCountDecDataPtr,
|
||||
RefCountIsUnique,
|
||||
BoxExpr,
|
||||
UnboxExpr,
|
||||
|
@ -222,8 +224,10 @@ macro_rules! map_symbol_to_lowlevel {
|
|||
LowLevel::Hash => unimplemented!(),
|
||||
LowLevel::PtrCast => unimplemented!(),
|
||||
LowLevel::PtrWrite => unimplemented!(),
|
||||
LowLevel::RefCountInc => unimplemented!(),
|
||||
LowLevel::RefCountDec => unimplemented!(),
|
||||
LowLevel::RefCountIncRcPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecRcPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIncDataPtr => unimplemented!(),
|
||||
LowLevel::RefCountDecDataPtr=> unimplemented!(),
|
||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||
|
||||
// these are not implemented, not sure why
|
||||
|
|
|
@ -1031,7 +1031,8 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] {
|
|||
unreachable!("These lowlevel operations are turned into mono Expr's")
|
||||
}
|
||||
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec | RefCountIsUnique => {
|
||||
PtrCast | PtrWrite | RefCountIncRcPtr | RefCountDecRcPtr | RefCountIncDataPtr
|
||||
| RefCountDecDataPtr | RefCountIsUnique => {
|
||||
unreachable!("Only inserted *after* borrow checking: {:?}", op);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -758,7 +758,7 @@ fn modify_refcount<'a>(
|
|||
HelperOp::Inc => {
|
||||
let zig_call_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::RefCountInc,
|
||||
op: LowLevel::RefCountIncRcPtr,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: root.arena.alloc([rc_ptr, Symbol::ARG_2]),
|
||||
|
@ -774,7 +774,7 @@ fn modify_refcount<'a>(
|
|||
|
||||
let zig_call_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::RefCountDec,
|
||||
op: LowLevel::RefCountDecRcPtr,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: root.arena.alloc([rc_ptr, alignment_sym]),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue