From f492800a28d06635f848dee4b2bf3bb55be1bf3f Mon Sep 17 00:00:00 2001 From: Folkert Date: Tue, 22 Sep 2020 21:58:45 +0200 Subject: [PATCH] recursive refcount on lists --- compiler/gen/src/llvm/build_list.rs | 20 ++++++++ compiler/gen/src/llvm/refcounting.rs | 76 ++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 16 deletions(-) diff --git a/compiler/gen/src/llvm/build_list.rs b/compiler/gen/src/llvm/build_list.rs index 078ae8bd64..25dc8fe0e5 100644 --- a/compiler/gen/src/llvm/build_list.rs +++ b/compiler/gen/src/llvm/build_list.rs @@ -1570,6 +1570,26 @@ pub fn list_is_not_empty<'ctx>(env: &Env<'_, 'ctx, '_>, len: IntValue<'ctx>) -> ) } +pub fn load_list<'ctx>( + builder: &Builder<'ctx>, + wrapper_struct: StructValue<'ctx>, + ptr_type: PointerType<'ctx>, +) -> (IntValue<'ctx>, PointerValue<'ctx>) { + let ptr_as_int = builder + .build_extract_value(wrapper_struct, Builtin::WRAPPER_PTR, "read_list_ptr") + .unwrap() + .into_int_value(); + + let ptr = builder.build_int_to_ptr(ptr_as_int, ptr_type, "list_cast_ptr"); + + let length = builder + .build_extract_value(wrapper_struct, Builtin::WRAPPER_LEN, "list_len") + .unwrap() + .into_int_value(); + + (length, ptr) +} + pub fn load_list_ptr<'ctx>( builder: &Builder<'ctx>, wrapper_struct: StructValue<'ctx>, diff --git a/compiler/gen/src/llvm/refcounting.rs b/compiler/gen/src/llvm/refcounting.rs index d7d9113d4e..a76f56f069 100644 --- a/compiler/gen/src/llvm/refcounting.rs +++ b/compiler/gen/src/llvm/refcounting.rs @@ -100,7 +100,7 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>( #[inline(always)] fn decrement_refcount_builtin<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, - _parent: FunctionValue<'ctx>, + parent: FunctionValue<'ctx>, layout_ids: &mut LayoutIds<'a>, value: BasicValueEnum<'ctx>, layout: &Layout<'a>, @@ -109,14 +109,37 @@ fn decrement_refcount_builtin<'a, 'ctx, 'env>( use Builtin::*; match builtin { - List(MemoryMode::Refcounted, element_layout) => { + List(memory_mode, element_layout) => { + let wrapper_struct = value.into_struct_value(); if element_layout.contains_refcounted() { - // TODO decrement all values + use crate::llvm::build_list::{incrementing_elem_loop, load_list}; + use inkwell::types::BasicType; + + let ptr_type = + basic_type_from_layout(env.arena, env.context, element_layout, env.ptr_bytes) + .ptr_type(AddressSpace::Generic); + + let (len, ptr) = load_list(env.builder, wrapper_struct, ptr_type); + + let loop_fn = |_index, element| { + decrement_refcount_layout(env, parent, layout_ids, element, element_layout); + }; + + incrementing_elem_loop( + env.builder, + env.context, + parent, + ptr, + len, + "dec_index", + loop_fn, + ); } - build_dec_list(env, layout_ids, layout, value.into_struct_value()); - } - List(MemoryMode::Unique, _element_layout) => { - // do nothing + + if let MemoryMode::Refcounted = memory_mode { + build_inc_list(env, layout_ids, layout, wrapper_struct); + } + build_dec_list(env, layout_ids, layout, wrapper_struct); } Set(element_layout) => { if element_layout.contains_refcounted() { @@ -158,7 +181,7 @@ pub fn increment_refcount_layout<'a, 'ctx, 'env>( #[inline(always)] fn increment_refcount_builtin<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, - _parent: FunctionValue<'ctx>, + parent: FunctionValue<'ctx>, layout_ids: &mut LayoutIds<'a>, value: BasicValueEnum<'ctx>, layout: &Layout<'a>, @@ -167,15 +190,36 @@ fn increment_refcount_builtin<'a, 'ctx, 'env>( use Builtin::*; match builtin { - List(MemoryMode::Refcounted, element_layout) => { - if element_layout.contains_refcounted() { - // TODO decrement all values - } + List(memory_mode, element_layout) => { let wrapper_struct = value.into_struct_value(); - build_inc_list(env, layout_ids, layout, wrapper_struct); - } - List(MemoryMode::Unique, _element_layout) => { - // do nothing + if element_layout.contains_refcounted() { + use crate::llvm::build_list::{incrementing_elem_loop, load_list}; + use inkwell::types::BasicType; + + let ptr_type = + basic_type_from_layout(env.arena, env.context, element_layout, env.ptr_bytes) + .ptr_type(AddressSpace::Generic); + + let (len, ptr) = load_list(env.builder, wrapper_struct, ptr_type); + + let loop_fn = |_index, element| { + increment_refcount_layout(env, parent, layout_ids, element, element_layout); + }; + + incrementing_elem_loop( + env.builder, + env.context, + parent, + ptr, + len, + "inc_index", + loop_fn, + ); + } + + if let MemoryMode::Refcounted = memory_mode { + build_inc_list(env, layout_ids, layout, wrapper_struct); + } } Set(element_layout) => { if element_layout.contains_refcounted() {