add lowlevel to inc/dec a data pointer

This commit is contained in:
Folkert 2023-04-28 15:30:23 +02:00
parent a61e7a696d
commit cf54304cf4
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
13 changed files with 90 additions and 28 deletions

View file

@ -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..]);

View file

@ -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");

View file

@ -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));
} }
} }
} }

View file

@ -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);
} }

View file

@ -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";

View file

@ -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

View file

@ -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,

View file

@ -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);
} }

View file

@ -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,
); );
} }

View file

@ -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 => {

View file

@ -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

View file

@ -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);
} }
} }

View file

@ -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]),