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);
|
var bytes: [*]u8 = @ptrCast([*]u8, nonUnique.bytes);
|
||||||
const ptr_width = @sizeOf(usize);
|
const ptr_width = @sizeOf(usize);
|
||||||
const refcount_ptr = @ptrCast([*]isize, @alignCast(ptr_width, bytes) - ptr_width);
|
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
|
defer nonUnique.decref(@sizeOf(u8)); // listConcat will dec the other refcount
|
||||||
|
|
||||||
var unique = RocList.fromSlice(u8, ([_]u8{ 2, 3, 4 })[0..]);
|
var unique = RocList.fromSlice(u8, ([_]u8{ 2, 3, 4 })[0..]);
|
||||||
|
|
|
@ -173,8 +173,10 @@ comptime {
|
||||||
// Utils
|
// Utils
|
||||||
comptime {
|
comptime {
|
||||||
exportUtilsFn(utils.test_panic, "test_panic");
|
exportUtilsFn(utils.test_panic, "test_panic");
|
||||||
exportUtilsFn(utils.increfC, "incref");
|
exportUtilsFn(utils.increfRcPtrC, "incref_rc_ptr");
|
||||||
exportUtilsFn(utils.decrefC, "decref");
|
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.isUnique, "is_unique");
|
||||||
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
|
exportUtilsFn(utils.decrefCheckNullC, "decref_check_null");
|
||||||
exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount");
|
exportUtilsFn(utils.allocateWithRefcountC, "allocate_with_refcount");
|
||||||
|
|
|
@ -162,7 +162,7 @@ pub const RocStr = extern struct {
|
||||||
const ref_ptr = self.getRefcountPtr();
|
const ref_ptr = self.getRefcountPtr();
|
||||||
if (ref_ptr != null) {
|
if (ref_ptr != null) {
|
||||||
const isizes: [*]isize = @ptrCast([*]isize, @alignCast(@alignOf(isize), ref_ptr));
|
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;
|
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;
|
if (RC_TYPE == Refcount.none) return;
|
||||||
// Ensure that the refcount is not whole program lifetime.
|
// Ensure that the refcount is not whole program lifetime.
|
||||||
if (ptr_to_refcount.* != REFCOUNT_MAX_ISIZE) {
|
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,
|
bytes_or_null: ?[*]isize,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
) callconv(.C) void {
|
) 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(
|
pub fn decref(
|
||||||
bytes_or_null: ?[*]u8,
|
bytes_or_null: ?[*]u8,
|
||||||
data_bytes: usize,
|
data_bytes: usize,
|
||||||
|
@ -363,13 +393,13 @@ pub const UpdateMode = enum(u8) {
|
||||||
test "increfC, refcounted data" {
|
test "increfC, refcounted data" {
|
||||||
var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17;
|
var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17;
|
||||||
var ptr_to_refcount: *isize = &mock_rc;
|
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);
|
try std.testing.expectEqual(mock_rc, REFCOUNT_ONE_ISIZE + 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "increfC, static data" {
|
test "increfC, static data" {
|
||||||
var mock_rc: isize = REFCOUNT_MAX_ISIZE;
|
var mock_rc: isize = REFCOUNT_MAX_ISIZE;
|
||||||
var ptr_to_refcount: *isize = &mock_rc;
|
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);
|
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_TEST_PANIC: &str = "roc_builtins.utils.test_panic";
|
||||||
pub const UTILS_ALLOCATE_WITH_REFCOUNT: &str = "roc_builtins.utils.allocate_with_refcount";
|
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_INCREF_RC_PTR: &str = "roc_builtins.utils.incref_rc_ptr";
|
||||||
pub const UTILS_DECREF: &str = "roc_builtins.utils.decref";
|
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_IS_UNIQUE: &str = "roc_builtins.utils.is_unique";
|
||||||
pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null";
|
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::Hash => unimplemented!(),
|
||||||
LowLevel::PtrCast => unimplemented!(),
|
LowLevel::PtrCast => unimplemented!(),
|
||||||
LowLevel::PtrWrite => unimplemented!(),
|
LowLevel::PtrWrite => unimplemented!(),
|
||||||
LowLevel::RefCountInc => unimplemented!(),
|
LowLevel::RefCountIncRcPtr => unimplemented!(),
|
||||||
LowLevel::RefCountDec => unimplemented!(),
|
LowLevel::RefCountDecRcPtr=> unimplemented!(),
|
||||||
|
LowLevel::RefCountIncDataPtr => unimplemented!(),
|
||||||
|
LowLevel::RefCountDecDataPtr=> unimplemented!(),
|
||||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||||
|
|
||||||
// these are not implemented, not sure why
|
// 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);
|
self.build_ptr_write(*sym, args[0], args[1], element_layout);
|
||||||
}
|
}
|
||||||
LowLevel::RefCountDec => self.build_fn_call(
|
LowLevel::RefCountDecRcPtr => self.build_fn_call(
|
||||||
sym,
|
sym,
|
||||||
bitcode::UTILS_DECREF.to_string(),
|
bitcode::UTILS_DECREF_RC_PTR.to_string(),
|
||||||
args,
|
args,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
),
|
),
|
||||||
LowLevel::RefCountInc => self.build_fn_call(
|
LowLevel::RefCountIncRcPtr => self.build_fn_call(
|
||||||
sym,
|
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,
|
args,
|
||||||
arg_layouts,
|
arg_layouts,
|
||||||
ret_layout,
|
ret_layout,
|
||||||
|
|
|
@ -1247,7 +1247,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
||||||
unreachable!("The {:?} operation is turned into mono Expr", op)
|
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);
|
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -212,7 +212,7 @@ fn incref_pointer<'a, 'ctx, 'env>(
|
||||||
.into(),
|
.into(),
|
||||||
amount.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(),
|
.into(),
|
||||||
alignment.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);
|
self.load_args(backend);
|
||||||
backend.code_builder.i32_eqz();
|
backend.code_builder.i32_eqz();
|
||||||
}
|
}
|
||||||
RefCountInc => self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF),
|
RefCountIncRcPtr => self.load_args_and_call_zig(backend, bitcode::UTILS_INCREF_RC_PTR),
|
||||||
RefCountDec => self.load_args_and_call_zig(backend, bitcode::UTILS_DECREF),
|
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),
|
RefCountIsUnique => self.load_args_and_call_zig(backend, bitcode::UTILS_IS_UNIQUE),
|
||||||
|
|
||||||
PtrCast => {
|
PtrCast => {
|
||||||
|
|
|
@ -116,8 +116,10 @@ pub enum LowLevel {
|
||||||
Hash,
|
Hash,
|
||||||
PtrCast,
|
PtrCast,
|
||||||
PtrWrite,
|
PtrWrite,
|
||||||
RefCountInc,
|
RefCountIncRcPtr,
|
||||||
RefCountDec,
|
RefCountDecRcPtr,
|
||||||
|
RefCountIncDataPtr,
|
||||||
|
RefCountDecDataPtr,
|
||||||
RefCountIsUnique,
|
RefCountIsUnique,
|
||||||
BoxExpr,
|
BoxExpr,
|
||||||
UnboxExpr,
|
UnboxExpr,
|
||||||
|
@ -222,8 +224,10 @@ macro_rules! map_symbol_to_lowlevel {
|
||||||
LowLevel::Hash => unimplemented!(),
|
LowLevel::Hash => unimplemented!(),
|
||||||
LowLevel::PtrCast => unimplemented!(),
|
LowLevel::PtrCast => unimplemented!(),
|
||||||
LowLevel::PtrWrite => unimplemented!(),
|
LowLevel::PtrWrite => unimplemented!(),
|
||||||
LowLevel::RefCountInc => unimplemented!(),
|
LowLevel::RefCountIncRcPtr => unimplemented!(),
|
||||||
LowLevel::RefCountDec => unimplemented!(),
|
LowLevel::RefCountDecRcPtr=> unimplemented!(),
|
||||||
|
LowLevel::RefCountIncDataPtr => unimplemented!(),
|
||||||
|
LowLevel::RefCountDecDataPtr=> unimplemented!(),
|
||||||
LowLevel::RefCountIsUnique => unimplemented!(),
|
LowLevel::RefCountIsUnique => unimplemented!(),
|
||||||
|
|
||||||
// these are not implemented, not sure why
|
// 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")
|
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);
|
unreachable!("Only inserted *after* borrow checking: {:?}", op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -758,7 +758,7 @@ fn modify_refcount<'a>(
|
||||||
HelperOp::Inc => {
|
HelperOp::Inc => {
|
||||||
let zig_call_expr = Expr::Call(Call {
|
let zig_call_expr = Expr::Call(Call {
|
||||||
call_type: CallType::LowLevel {
|
call_type: CallType::LowLevel {
|
||||||
op: LowLevel::RefCountInc,
|
op: LowLevel::RefCountIncRcPtr,
|
||||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||||
},
|
},
|
||||||
arguments: root.arena.alloc([rc_ptr, Symbol::ARG_2]),
|
arguments: root.arena.alloc([rc_ptr, Symbol::ARG_2]),
|
||||||
|
@ -774,7 +774,7 @@ fn modify_refcount<'a>(
|
||||||
|
|
||||||
let zig_call_expr = Expr::Call(Call {
|
let zig_call_expr = Expr::Call(Call {
|
||||||
call_type: CallType::LowLevel {
|
call_type: CallType::LowLevel {
|
||||||
op: LowLevel::RefCountDec,
|
op: LowLevel::RefCountDecRcPtr,
|
||||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||||
},
|
},
|
||||||
arguments: root.arena.alloc([rc_ptr, alignment_sym]),
|
arguments: root.arena.alloc([rc_ptr, alignment_sym]),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue