From 6e5acadfead7913c438c7dd363a45074bf96e2e0 Mon Sep 17 00:00:00 2001 From: Brian Carroll Date: Wed, 24 Nov 2021 16:07:31 +0000 Subject: [PATCH] Create new lowlevels for refcounting --- compiler/builtins/bitcode/src/main.zig | 1 + compiler/builtins/bitcode/src/utils.zig | 20 ++++++++++++++++++++ compiler/builtins/src/bitcode.rs | 1 + compiler/gen_llvm/src/llvm/build.rs | 4 ++++ compiler/gen_wasm/src/low_level.rs | 1 + compiler/module/src/low_level.rs | 3 +++ compiler/mono/src/borrow.rs | 4 ++++ 7 files changed, 34 insertions(+) diff --git a/compiler/builtins/bitcode/src/main.zig b/compiler/builtins/bitcode/src/main.zig index 8b081cd1cf..37c0a3011a 100644 --- a/compiler/builtins/bitcode/src/main.zig +++ b/compiler/builtins/bitcode/src/main.zig @@ -138,6 +138,7 @@ comptime { comptime { exportUtilsFn(utils.test_panic, "test_panic"); + exportUtilsFn(utils.increfC, "incref"); exportUtilsFn(utils.decrefC, "decref"); exportUtilsFn(utils.decrefCheckNullC, "decref_check_null"); diff --git a/compiler/builtins/bitcode/src/utils.zig b/compiler/builtins/bitcode/src/utils.zig index ab2ea26171..940e8d945b 100644 --- a/compiler/builtins/bitcode/src/utils.zig +++ b/compiler/builtins/bitcode/src/utils.zig @@ -104,6 +104,12 @@ pub const IntWidth = enum(u8) { I128 = 9, }; +pub fn increfC(ptr_to_refcount: *isize, amount: isize) callconv(.C) void { + var refcount = ptr_to_refcount.*; + var masked_amount = if (refcount == REFCOUNT_MAX_ISIZE) 0 else amount; + ptr_to_refcount.* = refcount + masked_amount; +} + pub fn decrefC( bytes_or_null: ?[*]isize, alignment: u32, @@ -261,3 +267,17 @@ pub const UpdateMode = enum(u8) { Immutable = 0, InPlace = 1, }; + +test "increfC, refcounted data" { + var mock_rc: isize = REFCOUNT_ONE_ISIZE + 17; + var ptr_to_refcount: *isize = &mock_rc; + increfC(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); + try std.testing.expectEqual(mock_rc, REFCOUNT_MAX_ISIZE); +} diff --git a/compiler/builtins/src/bitcode.rs b/compiler/builtins/src/bitcode.rs index afffd31dd9..da9de5a6e6 100644 --- a/compiler/builtins/src/bitcode.rs +++ b/compiler/builtins/src/bitcode.rs @@ -309,5 +309,6 @@ 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_INCREF: &str = "roc_builtins.utils.incref"; pub const UTILS_DECREF: &str = "roc_builtins.utils.decref"; pub const UTILS_DECREF_CHECK_NULL: &str = "roc_builtins.utils.decref_check_null"; diff --git a/compiler/gen_llvm/src/llvm/build.rs b/compiler/gen_llvm/src/llvm/build.rs index 69168415c0..e95cc2cb37 100644 --- a/compiler/gen_llvm/src/llvm/build.rs +++ b/compiler/gen_llvm/src/llvm/build.rs @@ -6020,6 +6020,10 @@ fn run_low_level<'a, 'ctx, 'env>( | ListAny | ListAll | ListFindUnsafe | DictWalk => { unreachable!("these are higher order, and are handled elsewhere") } + + RefCountGetPtr | RefCountInc | RefCountDec => { + unreachable!("LLVM backend does not use lowlevels for refcounting"); + } } } diff --git a/compiler/gen_wasm/src/low_level.rs b/compiler/gen_wasm/src/low_level.rs index 7cf781490a..c3698a24bb 100644 --- a/compiler/gen_wasm/src/low_level.rs +++ b/compiler/gen_wasm/src/low_level.rs @@ -370,6 +370,7 @@ pub fn decode_low_level<'a>( Not => code_builder.i32_eqz(), Hash => return NotImplemented, ExpectTrue => return NotImplemented, + RefCountGetPtr | RefCountInc | RefCountDec => return NotImplemented, } Done } diff --git a/compiler/module/src/low_level.rs b/compiler/module/src/low_level.rs index 9405956fc0..25acb8cc2d 100644 --- a/compiler/module/src/low_level.rs +++ b/compiler/module/src/low_level.rs @@ -115,6 +115,9 @@ pub enum LowLevel { Not, Hash, ExpectTrue, + RefCountGetPtr, + RefCountInc, + RefCountDec, } macro_rules! higher_order { diff --git a/compiler/mono/src/borrow.rs b/compiler/mono/src/borrow.rs index e29eca34ed..ca59b30b39 100644 --- a/compiler/mono/src/borrow.rs +++ b/compiler/mono/src/borrow.rs @@ -1008,6 +1008,10 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[bool] { SetFromList => arena.alloc_slice_copy(&[owned]), ExpectTrue => arena.alloc_slice_copy(&[irrelevant]), + + RefCountGetPtr | RefCountInc | RefCountDec => { + unreachable!("Refcounting lowlevel calls are inserted *after* borrow checking"); + } } }