mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Update LLVM to properly increment and decrement lists
This commit is contained in:
parent
255cc31ad9
commit
3c842196fa
12 changed files with 337 additions and 176 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
pub const packages = struct {};
|
||||||
|
pub const root_deps: []const struct { []const u8, []const u8 } = &.{};
|
|
@ -10,7 +10,7 @@ use std::{env, path::PathBuf, process::Command};
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
/// To debug the zig code with debug prints, we need to disable the wasm code gen
|
/// To debug the zig code with debug prints, we need to disable the wasm code gen
|
||||||
const DEBUG: bool = false;
|
const DEBUG: bool = true;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
|
@ -10,7 +10,7 @@ use std::{env, path::PathBuf, process::Command};
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
/// To debug the zig code with debug prints, we need to disable the wasm code gen
|
/// To debug the zig code with debug prints, we need to disable the wasm code gen
|
||||||
const DEBUG: bool = false;
|
const DEBUG: bool = true;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
|
@ -129,14 +129,24 @@ pub const RocList = extern struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: expose these both to roc and ensure lists always call them.
|
// This needs to be called when creating seamless slices from unique list.
|
||||||
|
// It will put the allocation size on the heap to enable the seamless slice to free the underlying allocation.
|
||||||
|
fn setAllocationElementCount(self: RocList, elements_refcounted: bool) void {
|
||||||
|
if (elements_refcounted) {
|
||||||
|
// - 1 is refcount.
|
||||||
|
// - 2 is size on heap.
|
||||||
|
const ptr = @as([*]usize, @alignCast(@ptrCast(self.getAllocationPtr()))) - 2;
|
||||||
|
ptr[0] = self.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn incref(self: RocList, amount: isize, elements_refcounted: bool) void {
|
pub fn incref(self: RocList, amount: isize, elements_refcounted: bool) void {
|
||||||
// If the list is unique and not a seamless slice, the length needs to be store on the heap if the elements are refcounted.
|
// If the list is unique and not a seamless slice, the length needs to be store on the heap if the elements are refcounted.
|
||||||
if (elements_refcounted and self.isUnique() and !self.isSeamlessSlice()) {
|
if (elements_refcounted and self.isUnique() and !self.isSeamlessSlice()) {
|
||||||
// - 1 is refcount.
|
// - 1 is refcount.
|
||||||
// - 2 is size on heap.
|
// - 2 is size on heap.
|
||||||
const ptr = @as([*]usize, self.getAllocationPtr()) - 2;
|
const ptr = @as([*]usize, @alignCast(@ptrCast(self.getAllocationPtr()))) - 2;
|
||||||
ptr.* = self.length;
|
ptr[0] = self.length;
|
||||||
}
|
}
|
||||||
utils.increfDataPtrC(self.getAllocationPtr(), amount);
|
utils.increfDataPtrC(self.getAllocationPtr(), amount);
|
||||||
}
|
}
|
||||||
|
@ -327,6 +337,14 @@ pub const RocList = extern struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn listIncref(list: RocList, amount: isize, elements_refcounted: bool) callconv(.C) void {
|
||||||
|
list.incref(amount, elements_refcounted);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn listDecref(list: RocList, alignment: u32, element_width: usize, elements_refcounted: bool, dec: Dec) callconv(.C) void {
|
||||||
|
list.decref(alignment, element_width, elements_refcounted, dec);
|
||||||
|
}
|
||||||
|
|
||||||
const Caller0 = *const fn (?[*]u8, ?[*]u8) callconv(.C) void;
|
const Caller0 = *const fn (?[*]u8, ?[*]u8) callconv(.C) void;
|
||||||
const Caller1 = *const fn (?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
const Caller1 = *const fn (?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||||
const Caller2 = *const fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
const Caller2 = *const fn (?[*]u8, ?[*]u8, ?[*]u8, ?[*]u8) callconv(.C) void;
|
||||||
|
@ -686,6 +704,10 @@ pub fn listSwap(
|
||||||
dec: Dec,
|
dec: Dec,
|
||||||
update_mode: UpdateMode,
|
update_mode: UpdateMode,
|
||||||
) callconv(.C) RocList {
|
) callconv(.C) RocList {
|
||||||
|
// Early exit to avoid swapping the same element.
|
||||||
|
if (index_1 == index_2)
|
||||||
|
return list;
|
||||||
|
|
||||||
const size = @as(u64, @intCast(list.len()));
|
const size = @as(u64, @intCast(list.len()));
|
||||||
if (index_1 == index_2 or index_1 >= size or index_2 >= size) {
|
if (index_1 == index_2 or index_1 >= size or index_2 >= size) {
|
||||||
// Either one index was out of bounds, or both indices were the same; just return
|
// Either one index was out of bounds, or both indices were the same; just return
|
||||||
|
@ -742,7 +764,6 @@ pub fn listSublist(
|
||||||
// This cast is lossless because we would have early-returned already
|
// This cast is lossless because we would have early-returned already
|
||||||
// if `start_u64` were greater than `size`, and `size` fits in usize.
|
// if `start_u64` were greater than `size`, and `size` fits in usize.
|
||||||
const start: usize = @intCast(start_u64);
|
const start: usize = @intCast(start_u64);
|
||||||
const drop_start_len = start;
|
|
||||||
|
|
||||||
// (size - start) can't overflow because we would have early-returned already
|
// (size - start) can't overflow because we would have early-returned already
|
||||||
// if `start` were greater than `size`.
|
// if `start` were greater than `size`.
|
||||||
|
@ -753,32 +774,23 @@ pub fn listSublist(
|
||||||
// than something that fit in usize.
|
// than something that fit in usize.
|
||||||
const keep_len = @as(usize, @intCast(@min(len_u64, @as(u64, @intCast(size_minus_start)))));
|
const keep_len = @as(usize, @intCast(@min(len_u64, @as(u64, @intCast(size_minus_start)))));
|
||||||
|
|
||||||
// This can't overflow because if len > size_minus_start,
|
|
||||||
// then keep_len == size_minus_start and this will be 0.
|
|
||||||
// Alternatively, if len <= size_minus_start, then keep_len will
|
|
||||||
// be equal to len, meaning keep_len <= size_minus_start too,
|
|
||||||
// which in turn means this won't overflow.
|
|
||||||
const drop_end_len = size_minus_start - keep_len;
|
|
||||||
|
|
||||||
// Decrement the reference counts of elements before `start`.
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < drop_start_len) : (i += 1) {
|
|
||||||
const element = source_ptr + i * element_width;
|
|
||||||
dec(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrement the reference counts of elements after `start + keep_len`.
|
|
||||||
i = 0;
|
|
||||||
while (i < drop_end_len) : (i += 1) {
|
|
||||||
const element = source_ptr + (start + keep_len + i) * element_width;
|
|
||||||
dec(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (start == 0 and list.isUnique()) {
|
if (start == 0 and list.isUnique()) {
|
||||||
|
// The list is unique, we actually have to decrement refcounts to elements we aren't keeping around.
|
||||||
|
// Decrement the reference counts of elements after `start + keep_len`.
|
||||||
|
const drop_end_len = size_minus_start - keep_len;
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < drop_end_len) : (i += 1) {
|
||||||
|
const element = source_ptr + (start + keep_len + i) * element_width;
|
||||||
|
dec(element);
|
||||||
|
}
|
||||||
|
|
||||||
var output = list;
|
var output = list;
|
||||||
output.length = keep_len;
|
output.length = keep_len;
|
||||||
return output;
|
return output;
|
||||||
} else {
|
} else {
|
||||||
|
if (list.isUnique()) {
|
||||||
|
list.setAllocationElementCount(elements_refcounted);
|
||||||
|
}
|
||||||
const list_alloc_ptr = (@intFromPtr(source_ptr) >> 1) | SEAMLESS_SLICE_BIT;
|
const list_alloc_ptr = (@intFromPtr(source_ptr) >> 1) | SEAMLESS_SLICE_BIT;
|
||||||
const slice_alloc_ptr = list.capacity_or_alloc_ptr;
|
const slice_alloc_ptr = list.capacity_or_alloc_ptr;
|
||||||
const slice_mask = list.seamlessSliceMask();
|
const slice_mask = list.seamlessSliceMask();
|
||||||
|
|
|
@ -86,6 +86,8 @@ comptime {
|
||||||
exportListFn(list.listAllocationPtr, "allocation_ptr");
|
exportListFn(list.listAllocationPtr, "allocation_ptr");
|
||||||
exportListFn(list.listReleaseExcessCapacity, "release_excess_capacity");
|
exportListFn(list.listReleaseExcessCapacity, "release_excess_capacity");
|
||||||
exportListFn(list.listConcatUtf8, "concat_utf8");
|
exportListFn(list.listConcatUtf8, "concat_utf8");
|
||||||
|
exportListFn(list.listIncref, "incref");
|
||||||
|
exportListFn(list.listDecref, "decref");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Num Module
|
// Num Module
|
||||||
|
|
|
@ -391,6 +391,8 @@ pub const LIST_CAPACITY: &str = "roc_builtins.list.capacity";
|
||||||
pub const LIST_ALLOCATION_PTR: &str = "roc_builtins.list.allocation_ptr";
|
pub const LIST_ALLOCATION_PTR: &str = "roc_builtins.list.allocation_ptr";
|
||||||
pub const LIST_RELEASE_EXCESS_CAPACITY: &str = "roc_builtins.list.release_excess_capacity";
|
pub const LIST_RELEASE_EXCESS_CAPACITY: &str = "roc_builtins.list.release_excess_capacity";
|
||||||
pub const LIST_CONCAT_UTF8: &str = "roc_builtins.list.concat_utf8";
|
pub const LIST_CONCAT_UTF8: &str = "roc_builtins.list.concat_utf8";
|
||||||
|
pub const LIST_INCREF: &str = "roc_builtins.list.incref";
|
||||||
|
pub const LIST_DECREF: &str = "roc_builtins.list.decref";
|
||||||
|
|
||||||
pub const DEC_ABS: &str = "roc_builtins.dec.abs";
|
pub const DEC_ABS: &str = "roc_builtins.dec.abs";
|
||||||
pub const DEC_ACOS: &str = "roc_builtins.dec.acos";
|
pub const DEC_ACOS: &str = "roc_builtins.dec.acos";
|
||||||
|
|
|
@ -1113,6 +1113,57 @@ pub(crate) fn call_str_bitcode_fn<'ctx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn call_void_list_bitcode_fn<'ctx>(
|
||||||
|
env: &Env<'_, 'ctx, '_>,
|
||||||
|
lists: &[StructValue<'ctx>],
|
||||||
|
other_arguments: &[BasicValueEnum<'ctx>],
|
||||||
|
fn_name: &str,
|
||||||
|
) {
|
||||||
|
use bumpalo::collections::Vec;
|
||||||
|
use roc_target::Architecture::*;
|
||||||
|
|
||||||
|
match env.target.architecture() {
|
||||||
|
Aarch32 | X86_32 => {
|
||||||
|
let mut arguments: Vec<BasicValueEnum> =
|
||||||
|
Vec::with_capacity_in(other_arguments.len() + 2 * lists.len(), env.arena);
|
||||||
|
|
||||||
|
for list in lists {
|
||||||
|
let (a, b) = pass_list_or_string_to_zig_32bit(env, *list);
|
||||||
|
arguments.push(a.into());
|
||||||
|
arguments.push(b.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.extend(other_arguments);
|
||||||
|
|
||||||
|
call_void_bitcode_fn(env, &arguments, fn_name);
|
||||||
|
}
|
||||||
|
X86_64 | Aarch64 => {
|
||||||
|
let capacity = other_arguments.len() + lists.len();
|
||||||
|
let mut arguments: Vec<BasicValueEnum> = Vec::with_capacity_in(capacity, env.arena);
|
||||||
|
|
||||||
|
for list in lists {
|
||||||
|
arguments.push(pass_list_to_zig_64bit(env, (*list).into()).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.extend(other_arguments);
|
||||||
|
|
||||||
|
call_void_bitcode_fn(env, &arguments, fn_name);
|
||||||
|
}
|
||||||
|
Wasm32 => {
|
||||||
|
let capacity = other_arguments.len() + lists.len();
|
||||||
|
let mut arguments: Vec<BasicValueEnum> = Vec::with_capacity_in(capacity, env.arena);
|
||||||
|
|
||||||
|
for list in lists {
|
||||||
|
arguments.push(pass_list_to_zig_wasm(env, (*list).into()).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
arguments.extend(other_arguments);
|
||||||
|
|
||||||
|
call_void_bitcode_fn(env, &arguments, fn_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn call_list_bitcode_fn<'ctx>(
|
pub(crate) fn call_list_bitcode_fn<'ctx>(
|
||||||
env: &Env<'_, 'ctx, '_>,
|
env: &Env<'_, 'ctx, '_>,
|
||||||
lists: &[StructValue<'ctx>],
|
lists: &[StructValue<'ctx>],
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::llvm::bitcode::call_bitcode_fn;
|
use crate::llvm::bitcode::{build_dec_wrapper, call_bitcode_fn, call_void_list_bitcode_fn};
|
||||||
use crate::llvm::build_list::{self, allocate_list, empty_polymorphic_list};
|
use crate::llvm::build_list::{
|
||||||
|
allocate_list, empty_polymorphic_list, layout_refcounted, layout_width,
|
||||||
|
};
|
||||||
use crate::llvm::convert::{
|
use crate::llvm::convert::{
|
||||||
argument_type_from_layout, basic_type_from_builtin, basic_type_from_layout, zig_str_type,
|
argument_type_from_layout, basic_type_from_builtin, basic_type_from_layout, zig_str_type,
|
||||||
};
|
};
|
||||||
|
@ -2860,19 +2862,6 @@ fn union_field_ptr_at_index<'a, 'ctx>(
|
||||||
.into_pointer_value()
|
.into_pointer_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_with_refcount<'a, 'ctx>(
|
|
||||||
env: &Env<'a, 'ctx, '_>,
|
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
|
||||||
layout: InLayout<'a>,
|
|
||||||
) -> PointerValue<'ctx> {
|
|
||||||
let stack_size = layout_interner.stack_size(layout);
|
|
||||||
let alignment_bytes = layout_interner.alignment_bytes(layout);
|
|
||||||
|
|
||||||
let basic_type = basic_type_from_layout(env, layout_interner, layout_interner.get_repr(layout));
|
|
||||||
|
|
||||||
reserve_with_refcount_help(env, basic_type, stack_size, alignment_bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
|
fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
@ -2887,7 +2876,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
|
||||||
RocUnion::untagged_from_slices(layout_interner, env.context, fields)
|
RocUnion::untagged_from_slices(layout_interner, env.context, fields)
|
||||||
};
|
};
|
||||||
|
|
||||||
reserve_with_refcount_help(
|
reserve_union_with_refcount_help(
|
||||||
env,
|
env,
|
||||||
roc_union.struct_type(),
|
roc_union.struct_type(),
|
||||||
roc_union.tag_width(),
|
roc_union.tag_width(),
|
||||||
|
@ -2895,7 +2884,7 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reserve_with_refcount_help<'a, 'ctx, 'env>(
|
fn reserve_union_with_refcount_help<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
basic_type: impl BasicType<'ctx>,
|
basic_type: impl BasicType<'ctx>,
|
||||||
stack_size: u32,
|
stack_size: u32,
|
||||||
|
@ -2905,21 +2894,15 @@ fn reserve_with_refcount_help<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let value_bytes_intvalue = len_type.const_int(stack_size as u64, false);
|
let value_bytes_intvalue = len_type.const_int(stack_size as u64, false);
|
||||||
|
|
||||||
allocate_with_refcount_help(env, basic_type, alignment_bytes, value_bytes_intvalue)
|
// elem_refcounted does not apply to unions, only lists.
|
||||||
}
|
let elem_refcounted = env.context.bool_type().const_zero().into();
|
||||||
|
allocate_with_refcount_help(
|
||||||
pub fn allocate_with_refcount<'a, 'ctx>(
|
env,
|
||||||
env: &Env<'a, 'ctx, '_>,
|
basic_type,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
alignment_bytes,
|
||||||
layout: InLayout<'a>,
|
value_bytes_intvalue,
|
||||||
value: BasicValueEnum<'ctx>,
|
elem_refcounted,
|
||||||
) -> PointerValue<'ctx> {
|
)
|
||||||
let data_ptr = reserve_with_refcount(env, layout_interner, layout);
|
|
||||||
|
|
||||||
// store the value in the pointer
|
|
||||||
env.builder.new_build_store(data_ptr, value);
|
|
||||||
|
|
||||||
data_ptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
||||||
|
@ -2927,12 +2910,14 @@ pub fn allocate_with_refcount_help<'a, 'ctx, 'env>(
|
||||||
value_type: impl BasicType<'ctx>,
|
value_type: impl BasicType<'ctx>,
|
||||||
alignment_bytes: u32,
|
alignment_bytes: u32,
|
||||||
number_of_data_bytes: IntValue<'ctx>,
|
number_of_data_bytes: IntValue<'ctx>,
|
||||||
|
elem_refcounted: BasicValueEnum<'ctx>,
|
||||||
) -> PointerValue<'ctx> {
|
) -> PointerValue<'ctx> {
|
||||||
let ptr = call_bitcode_fn(
|
let ptr = call_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
number_of_data_bytes.into(),
|
number_of_data_bytes.into(),
|
||||||
env.alignment_const(alignment_bytes).into(),
|
env.alignment_const(alignment_bytes).into(),
|
||||||
|
elem_refcounted,
|
||||||
],
|
],
|
||||||
roc_builtins::bitcode::UTILS_ALLOCATE_WITH_REFCOUNT,
|
roc_builtins::bitcode::UTILS_ALLOCATE_WITH_REFCOUNT,
|
||||||
)
|
)
|
||||||
|
@ -3473,10 +3458,19 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
||||||
LayoutRepr::Builtin(Builtin::Str) => todo!(),
|
LayoutRepr::Builtin(Builtin::Str) => todo!(),
|
||||||
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
|
LayoutRepr::Builtin(Builtin::List(element_layout)) => {
|
||||||
debug_assert!(value.is_struct_value());
|
debug_assert!(value.is_struct_value());
|
||||||
let element_layout = layout_interner.get_repr(element_layout);
|
let dec_element_fn =
|
||||||
let alignment = element_layout.alignment_bytes(layout_interner);
|
build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
call_void_list_bitcode_fn(
|
||||||
build_list::decref(env, value.into_struct_value(), alignment);
|
env,
|
||||||
|
&[value.into_struct_value()],
|
||||||
|
&[
|
||||||
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
],
|
||||||
|
bitcode::LIST_DECREF,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
other_layout if other_layout.is_refcounted(layout_interner) => {
|
other_layout if other_layout.is_refcounted(layout_interner) => {
|
||||||
|
@ -3546,7 +3540,8 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
||||||
debug_assert!(value.is_pointer_value());
|
debug_assert!(value.is_pointer_value());
|
||||||
let value = value.into_pointer_value();
|
let value = value.into_pointer_value();
|
||||||
|
|
||||||
let clear_tag_id = match layout_interner.runtime_representation(layout) {
|
let runtime_layout = layout_interner.runtime_representation(layout);
|
||||||
|
let clear_tag_id = match runtime_layout {
|
||||||
LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target),
|
LayoutRepr::Union(union) => union.stores_tag_id_in_pointer(env.target),
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -3558,7 +3553,7 @@ pub(crate) fn build_exp_stmt<'a, 'ctx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let rc_ptr = PointerToRefcount::from_ptr_to_data(env, ptr);
|
let rc_ptr = PointerToRefcount::from_ptr_to_data(env, ptr);
|
||||||
rc_ptr.deallocate(env, alignment);
|
rc_ptr.deallocate(env, alignment, runtime_layout);
|
||||||
|
|
||||||
build_exp_stmt(
|
build_exp_stmt(
|
||||||
env,
|
env,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use roc_mono::layout::{
|
||||||
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
|
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, LayoutRepr, STLayoutInterner,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::bitcode::{call_list_bitcode_fn, BitcodeReturns};
|
use super::bitcode::{build_inc_wrapper, call_list_bitcode_fn, BitcodeReturns};
|
||||||
use super::build::{
|
use super::build::{
|
||||||
create_entry_block_alloca, load_roc_value, store_roc_value, use_roc_value, BuilderExt,
|
create_entry_block_alloca, load_roc_value, store_roc_value, use_roc_value, BuilderExt,
|
||||||
};
|
};
|
||||||
|
@ -97,6 +97,20 @@ pub(crate) fn layout_width<'a, 'ctx>(
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn layout_refcounted<'a, 'ctx>(
|
||||||
|
env: &Env<'a, 'ctx, '_>,
|
||||||
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout: InLayout<'a>,
|
||||||
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let is_refcounted = layout_interner
|
||||||
|
.get_repr(layout)
|
||||||
|
.is_refcounted(layout_interner);
|
||||||
|
env.context
|
||||||
|
.bool_type()
|
||||||
|
.const_int(is_refcounted as u64, false)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn pass_as_opaque<'ctx>(
|
pub(crate) fn pass_as_opaque<'ctx>(
|
||||||
env: &Env<'_, 'ctx, '_>,
|
env: &Env<'_, 'ctx, '_>,
|
||||||
ptr: PointerValue<'ctx>,
|
ptr: PointerValue<'ctx>,
|
||||||
|
@ -113,9 +127,11 @@ pub(crate) fn pass_as_opaque<'ctx>(
|
||||||
pub(crate) fn list_with_capacity<'a, 'ctx>(
|
pub(crate) fn list_with_capacity<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
capacity: IntValue<'ctx>,
|
capacity: IntValue<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
call_list_bitcode_fn(
|
call_list_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[],
|
&[],
|
||||||
|
@ -123,6 +139,8 @@ pub(crate) fn list_with_capacity<'a, 'ctx>(
|
||||||
capacity.into(),
|
capacity.into(),
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
],
|
],
|
||||||
BitcodeReturns::List,
|
BitcodeReturns::List,
|
||||||
bitcode::LIST_WITH_CAPACITY,
|
bitcode::LIST_WITH_CAPACITY,
|
||||||
|
@ -173,11 +191,13 @@ pub(crate) fn list_get_unsafe<'a, 'ctx>(
|
||||||
pub(crate) fn list_reserve<'a, 'ctx>(
|
pub(crate) fn list_reserve<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
list: BasicValueEnum<'ctx>,
|
list: BasicValueEnum<'ctx>,
|
||||||
spare: BasicValueEnum<'ctx>,
|
spare: BasicValueEnum<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
update_mode: UpdateMode,
|
update_mode: UpdateMode,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
call_list_bitcode_fn_1(
|
call_list_bitcode_fn_1(
|
||||||
env,
|
env,
|
||||||
list.into_struct_value(),
|
list.into_struct_value(),
|
||||||
|
@ -185,6 +205,8 @@ pub(crate) fn list_reserve<'a, 'ctx>(
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
spare,
|
spare,
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
pass_update_mode(env, update_mode),
|
pass_update_mode(env, update_mode),
|
||||||
],
|
],
|
||||||
bitcode::LIST_RESERVE,
|
bitcode::LIST_RESERVE,
|
||||||
|
@ -195,16 +217,20 @@ pub(crate) fn list_reserve<'a, 'ctx>(
|
||||||
pub(crate) fn list_release_excess_capacity<'a, 'ctx>(
|
pub(crate) fn list_release_excess_capacity<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
list: BasicValueEnum<'ctx>,
|
list: BasicValueEnum<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
update_mode: UpdateMode,
|
update_mode: UpdateMode,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
call_list_bitcode_fn_1(
|
call_list_bitcode_fn_1(
|
||||||
env,
|
env,
|
||||||
list.into_struct_value(),
|
list.into_struct_value(),
|
||||||
&[
|
&[
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
pass_update_mode(env, update_mode),
|
pass_update_mode(env, update_mode),
|
||||||
],
|
],
|
||||||
bitcode::LIST_RELEASE_EXCESS_CAPACITY,
|
bitcode::LIST_RELEASE_EXCESS_CAPACITY,
|
||||||
|
@ -234,10 +260,12 @@ pub(crate) fn list_append_unsafe<'a, 'ctx>(
|
||||||
pub(crate) fn list_prepend<'a, 'ctx>(
|
pub(crate) fn list_prepend<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
original_wrapper: StructValue<'ctx>,
|
original_wrapper: StructValue<'ctx>,
|
||||||
element: BasicValueEnum<'ctx>,
|
element: BasicValueEnum<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
call_list_bitcode_fn_1(
|
call_list_bitcode_fn_1(
|
||||||
env,
|
env,
|
||||||
original_wrapper,
|
original_wrapper,
|
||||||
|
@ -245,21 +273,50 @@ pub(crate) fn list_prepend<'a, 'ctx>(
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
],
|
],
|
||||||
bitcode::LIST_PREPEND,
|
bitcode::LIST_PREPEND,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn list_clone<'a, 'ctx>(
|
||||||
|
env: &Env<'a, 'ctx, '_>,
|
||||||
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
|
list: StructValue<'ctx>,
|
||||||
|
element_layout: InLayout<'a>,
|
||||||
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
call_list_bitcode_fn_1(
|
||||||
|
env,
|
||||||
|
list,
|
||||||
|
&[
|
||||||
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
],
|
||||||
|
bitcode::LIST_CLONE,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// List.swap : List elem, U64, U64 -> List elem
|
/// List.swap : List elem, U64, U64 -> List elem
|
||||||
pub(crate) fn list_swap<'a, 'ctx>(
|
pub(crate) fn list_swap<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
original_wrapper: StructValue<'ctx>,
|
original_wrapper: StructValue<'ctx>,
|
||||||
index_1: IntValue<'ctx>,
|
index_1: IntValue<'ctx>,
|
||||||
index_2: IntValue<'ctx>,
|
index_2: IntValue<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
update_mode: UpdateMode,
|
update_mode: UpdateMode,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
|
||||||
call_list_bitcode_fn_1(
|
call_list_bitcode_fn_1(
|
||||||
env,
|
env,
|
||||||
original_wrapper,
|
original_wrapper,
|
||||||
|
@ -268,6 +325,9 @@ pub(crate) fn list_swap<'a, 'ctx>(
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
index_1.into(),
|
index_1.into(),
|
||||||
index_2.into(),
|
index_2.into(),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
pass_update_mode(env, update_mode),
|
pass_update_mode(env, update_mode),
|
||||||
],
|
],
|
||||||
bitcode::LIST_SWAP,
|
bitcode::LIST_SWAP,
|
||||||
|
@ -291,6 +351,7 @@ pub(crate) fn list_sublist<'a, 'ctx>(
|
||||||
&[
|
&[
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
start.into(),
|
start.into(),
|
||||||
len.into(),
|
len.into(),
|
||||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
@ -315,6 +376,7 @@ pub(crate) fn list_drop_at<'a, 'ctx>(
|
||||||
&[
|
&[
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
count.into(),
|
count.into(),
|
||||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
],
|
],
|
||||||
|
@ -326,7 +388,7 @@ pub(crate) fn list_drop_at<'a, 'ctx>(
|
||||||
pub(crate) fn list_replace_unsafe<'a, 'ctx>(
|
pub(crate) fn list_replace_unsafe<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
_layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
list: BasicValueEnum<'ctx>,
|
list: BasicValueEnum<'ctx>,
|
||||||
index: IntValue<'ctx>,
|
index: IntValue<'ctx>,
|
||||||
element: BasicValueEnum<'ctx>,
|
element: BasicValueEnum<'ctx>,
|
||||||
|
@ -356,18 +418,27 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx>(
|
||||||
],
|
],
|
||||||
bitcode::LIST_REPLACE_IN_PLACE,
|
bitcode::LIST_REPLACE_IN_PLACE,
|
||||||
),
|
),
|
||||||
UpdateMode::Immutable => call_list_bitcode_fn_1(
|
UpdateMode::Immutable => {
|
||||||
env,
|
let inc_element_fn =
|
||||||
list.into_struct_value(),
|
build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
&[
|
let dec_element_fn =
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
index.into(),
|
call_list_bitcode_fn_1(
|
||||||
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
env,
|
||||||
layout_width(env, layout_interner, element_layout),
|
list.into_struct_value(),
|
||||||
pass_as_opaque(env, element_ptr),
|
&[
|
||||||
],
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
bitcode::LIST_REPLACE,
|
index.into(),
|
||||||
),
|
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
||||||
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
pass_as_opaque(env, element_ptr),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
],
|
||||||
|
bitcode::LIST_REPLACE,
|
||||||
|
)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load the element and returned list into a struct.
|
// Load the element and returned list into a struct.
|
||||||
|
@ -493,11 +564,14 @@ pub(crate) fn destructure<'ctx>(
|
||||||
pub(crate) fn list_sort_with<'a, 'ctx>(
|
pub(crate) fn list_sort_with<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
roc_function_call: RocFunctionCall<'ctx>,
|
roc_function_call: RocFunctionCall<'ctx>,
|
||||||
compare_wrapper: PointerValue<'ctx>,
|
compare_wrapper: PointerValue<'ctx>,
|
||||||
list: BasicValueEnum<'ctx>,
|
list: BasicValueEnum<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
call_list_bitcode_fn_1(
|
call_list_bitcode_fn_1(
|
||||||
env,
|
env,
|
||||||
list.into_struct_value(),
|
list.into_struct_value(),
|
||||||
|
@ -508,6 +582,9 @@ pub(crate) fn list_sort_with<'a, 'ctx>(
|
||||||
roc_function_call.data_is_owned.into(),
|
roc_function_call.data_is_owned.into(),
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
],
|
],
|
||||||
bitcode::LIST_SORT_WITH,
|
bitcode::LIST_SORT_WITH,
|
||||||
)
|
)
|
||||||
|
@ -533,6 +610,7 @@ pub(crate) fn list_map<'a, 'ctx>(
|
||||||
env.alignment_intvalue(layout_interner, return_layout),
|
env.alignment_intvalue(layout_interner, return_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, return_layout),
|
layout_width(env, layout_interner, return_layout),
|
||||||
|
layout_refcounted(env, layout_interner, return_layout),
|
||||||
],
|
],
|
||||||
bitcode::LIST_MAP,
|
bitcode::LIST_MAP,
|
||||||
)
|
)
|
||||||
|
@ -566,6 +644,7 @@ pub(crate) fn list_map2<'a, 'ctx>(
|
||||||
layout_width(env, layout_interner, return_layout),
|
layout_width(env, layout_interner, return_layout),
|
||||||
dec_a.as_global_value().as_pointer_value().into(),
|
dec_a.as_global_value().as_pointer_value().into(),
|
||||||
dec_b.as_global_value().as_pointer_value().into(),
|
dec_b.as_global_value().as_pointer_value().into(),
|
||||||
|
layout_refcounted(env, layout_interner, return_layout),
|
||||||
],
|
],
|
||||||
BitcodeReturns::List,
|
BitcodeReturns::List,
|
||||||
bitcode::LIST_MAP2,
|
bitcode::LIST_MAP2,
|
||||||
|
@ -609,6 +688,7 @@ pub(crate) fn list_map3<'a, 'ctx>(
|
||||||
dec_a.as_global_value().as_pointer_value().into(),
|
dec_a.as_global_value().as_pointer_value().into(),
|
||||||
dec_b.as_global_value().as_pointer_value().into(),
|
dec_b.as_global_value().as_pointer_value().into(),
|
||||||
dec_c.as_global_value().as_pointer_value().into(),
|
dec_c.as_global_value().as_pointer_value().into(),
|
||||||
|
layout_refcounted(env, layout_interner, result_layout),
|
||||||
],
|
],
|
||||||
BitcodeReturns::List,
|
BitcodeReturns::List,
|
||||||
bitcode::LIST_MAP3,
|
bitcode::LIST_MAP3,
|
||||||
|
@ -658,6 +738,7 @@ pub(crate) fn list_map4<'a, 'ctx>(
|
||||||
dec_b.as_global_value().as_pointer_value().into(),
|
dec_b.as_global_value().as_pointer_value().into(),
|
||||||
dec_c.as_global_value().as_pointer_value().into(),
|
dec_c.as_global_value().as_pointer_value().into(),
|
||||||
dec_d.as_global_value().as_pointer_value().into(),
|
dec_d.as_global_value().as_pointer_value().into(),
|
||||||
|
layout_refcounted(env, layout_interner, result_layout),
|
||||||
],
|
],
|
||||||
BitcodeReturns::List,
|
BitcodeReturns::List,
|
||||||
bitcode::LIST_MAP4,
|
bitcode::LIST_MAP4,
|
||||||
|
@ -668,16 +749,22 @@ pub(crate) fn list_map4<'a, 'ctx>(
|
||||||
pub(crate) fn list_concat<'a, 'ctx>(
|
pub(crate) fn list_concat<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
list1: BasicValueEnum<'ctx>,
|
list1: BasicValueEnum<'ctx>,
|
||||||
list2: BasicValueEnum<'ctx>,
|
list2: BasicValueEnum<'ctx>,
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let inc_element_fn = build_inc_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
|
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
call_list_bitcode_fn(
|
call_list_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[list1.into_struct_value(), list2.into_struct_value()],
|
&[list1.into_struct_value(), list2.into_struct_value()],
|
||||||
&[
|
&[
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
layout_width(env, layout_interner, element_layout),
|
layout_width(env, layout_interner, element_layout),
|
||||||
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
|
inc_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
],
|
],
|
||||||
BitcodeReturns::List,
|
BitcodeReturns::List,
|
||||||
bitcode::LIST_CONCAT,
|
bitcode::LIST_CONCAT,
|
||||||
|
@ -838,7 +925,14 @@ pub(crate) fn allocate_list<'a, 'ctx>(
|
||||||
let basic_type =
|
let basic_type =
|
||||||
basic_type_from_layout(env, layout_interner, layout_interner.get_repr(elem_layout));
|
basic_type_from_layout(env, layout_interner, layout_interner.get_repr(elem_layout));
|
||||||
let alignment_bytes = layout_interner.alignment_bytes(elem_layout);
|
let alignment_bytes = layout_interner.alignment_bytes(elem_layout);
|
||||||
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
|
let elem_refcounted = layout_refcounted(env, layout_interner, elem_layout);
|
||||||
|
allocate_with_refcount_help(
|
||||||
|
env,
|
||||||
|
basic_type,
|
||||||
|
alignment_bytes,
|
||||||
|
number_of_data_bytes,
|
||||||
|
elem_refcounted,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn store_list<'ctx>(
|
pub(crate) fn store_list<'ctx>(
|
||||||
|
@ -860,13 +954,3 @@ pub(crate) fn store_list<'ctx>(
|
||||||
.into_iter(),
|
.into_iter(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn decref<'ctx>(
|
|
||||||
env: &Env<'_, 'ctx, '_>,
|
|
||||||
wrapper_struct: StructValue<'ctx>,
|
|
||||||
alignment: u32,
|
|
||||||
) {
|
|
||||||
let refcount_ptr = list_allocation_ptr(env, wrapper_struct);
|
|
||||||
|
|
||||||
crate::llvm::refcounting::decref_pointer_check_null(env, refcount_ptr, alignment);
|
|
||||||
}
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ use crate::llvm::{
|
||||||
BuilderExt, FuncBorrowSpec, RocReturn,
|
BuilderExt, FuncBorrowSpec, RocReturn,
|
||||||
},
|
},
|
||||||
build_list::{
|
build_list::{
|
||||||
layout_width, list_append_unsafe, list_concat, list_drop_at, list_get_unsafe,
|
list_append_unsafe, list_clone, list_concat, list_drop_at, list_get_unsafe,
|
||||||
list_len_usize, list_map, list_map2, list_map3, list_map4, list_prepend,
|
list_len_usize, list_map, list_map2, list_map3, list_map4, list_prepend,
|
||||||
list_release_excess_capacity, list_replace_unsafe, list_reserve, list_sort_with,
|
list_release_excess_capacity, list_replace_unsafe, list_reserve, list_sort_with,
|
||||||
list_sublist, list_swap, list_symbol_to_c_abi, list_with_capacity, pass_update_mode,
|
list_sublist, list_swap, list_symbol_to_c_abi, list_with_capacity, pass_update_mode,
|
||||||
|
@ -645,6 +645,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
list_with_capacity(
|
list_with_capacity(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
list_len.into_int_value(),
|
list_len.into_int_value(),
|
||||||
list_element_layout!(layout_interner, result_layout),
|
list_element_layout!(layout_interner, result_layout),
|
||||||
)
|
)
|
||||||
|
@ -661,6 +662,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
list_concat(
|
list_concat(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
first_list,
|
first_list,
|
||||||
second_list,
|
second_list,
|
||||||
element_layout,
|
element_layout,
|
||||||
|
@ -682,7 +684,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
let original_wrapper = scope.load_symbol(&args[0]).into_struct_value();
|
let original_wrapper = scope.load_symbol(&args[0]).into_struct_value();
|
||||||
let (elem, elem_layout) = scope.load_symbol_and_layout(&args[1]);
|
let (elem, elem_layout) = scope.load_symbol_and_layout(&args[1]);
|
||||||
|
|
||||||
list_prepend(env, layout_interner, original_wrapper, elem, elem_layout)
|
list_prepend(
|
||||||
|
env,
|
||||||
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
|
original_wrapper,
|
||||||
|
elem,
|
||||||
|
elem_layout,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ListReserve => {
|
ListReserve => {
|
||||||
// List.reserve : List elem, U64 -> List elem
|
// List.reserve : List elem, U64 -> List elem
|
||||||
|
@ -695,6 +704,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
list_reserve(
|
list_reserve(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
list,
|
list,
|
||||||
spare,
|
spare,
|
||||||
element_layout,
|
element_layout,
|
||||||
|
@ -708,7 +718,14 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
let (list, list_layout) = scope.load_symbol_and_layout(&args[0]);
|
let (list, list_layout) = scope.load_symbol_and_layout(&args[0]);
|
||||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||||
|
|
||||||
list_release_excess_capacity(env, layout_interner, list, element_layout, update_mode)
|
list_release_excess_capacity(
|
||||||
|
env,
|
||||||
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
|
list,
|
||||||
|
element_layout,
|
||||||
|
update_mode,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ListSwap => {
|
ListSwap => {
|
||||||
// List.swap : List elem, U64, U64 -> List elem
|
// List.swap : List elem, U64, U64 -> List elem
|
||||||
|
@ -724,6 +741,7 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
list_swap(
|
list_swap(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
original_wrapper,
|
original_wrapper,
|
||||||
index_1.into_int_value(),
|
index_1.into_int_value(),
|
||||||
index_2.into_int_value(),
|
index_2.into_int_value(),
|
||||||
|
@ -826,19 +844,13 @@ pub(crate) fn run_low_level<'a, 'ctx>(
|
||||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||||
|
|
||||||
match update_mode {
|
match update_mode {
|
||||||
UpdateMode::Immutable => {
|
UpdateMode::Immutable => list_clone(
|
||||||
//
|
env,
|
||||||
call_list_bitcode_fn(
|
layout_interner,
|
||||||
env,
|
layout_ids,
|
||||||
&[list.into_struct_value()],
|
list.into_struct_value(),
|
||||||
&[
|
element_layout,
|
||||||
env.alignment_intvalue(layout_interner, element_layout),
|
),
|
||||||
layout_width(env, layout_interner, element_layout),
|
|
||||||
],
|
|
||||||
BitcodeReturns::List,
|
|
||||||
bitcode::LIST_CLONE,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
UpdateMode::InPlace => {
|
UpdateMode::InPlace => {
|
||||||
// we statically know the list is unique
|
// we statically know the list is unique
|
||||||
list
|
list
|
||||||
|
@ -3030,6 +3042,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx>(
|
||||||
list_sort_with(
|
list_sort_with(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
|
layout_ids,
|
||||||
roc_function_call,
|
roc_function_call,
|
||||||
compare_wrapper,
|
compare_wrapper,
|
||||||
list,
|
list,
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
use crate::debug_info_init;
|
use crate::debug_info_init;
|
||||||
use crate::llvm::bitcode::call_void_bitcode_fn;
|
use crate::llvm::bitcode::{build_dec_wrapper, call_void_bitcode_fn, call_void_list_bitcode_fn};
|
||||||
use crate::llvm::build::BuilderExt;
|
use crate::llvm::build::BuilderExt;
|
||||||
use crate::llvm::build::{
|
use crate::llvm::build::{
|
||||||
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, Env, FAST_CALL_CONV,
|
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, Env, FAST_CALL_CONV,
|
||||||
};
|
};
|
||||||
use crate::llvm::build_list::{
|
use crate::llvm::build_list::{layout_refcounted, layout_width};
|
||||||
incrementing_elem_loop, list_allocation_ptr, list_capacity_or_ref_ptr, load_list,
|
|
||||||
};
|
|
||||||
use crate::llvm::build_str::str_allocation_ptr;
|
use crate::llvm::build_str::str_allocation_ptr;
|
||||||
use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion};
|
use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion};
|
||||||
use crate::llvm::struct_::RocStruct;
|
use crate::llvm::struct_::RocStruct;
|
||||||
|
@ -16,6 +14,7 @@ use inkwell::module::Linkage;
|
||||||
use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
|
use inkwell::types::{AnyTypeEnum, BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
|
||||||
use inkwell::values::{BasicValueEnum, FunctionValue, InstructionValue, IntValue, PointerValue};
|
use inkwell::values::{BasicValueEnum, FunctionValue, InstructionValue, IntValue, PointerValue};
|
||||||
use inkwell::{AddressSpace, IntPredicate};
|
use inkwell::{AddressSpace, IntPredicate};
|
||||||
|
use roc_builtins::bitcode;
|
||||||
use roc_module::symbol::Interns;
|
use roc_module::symbol::Interns;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_mono::ir::ErasedField;
|
use roc_mono::ir::ErasedField;
|
||||||
|
@ -111,13 +110,18 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
) {
|
) {
|
||||||
match mode {
|
match mode {
|
||||||
CallMode::Inc(inc_amount) => self.increment(inc_amount, env),
|
CallMode::Inc(inc_amount) => self.increment(inc_amount, env, layout),
|
||||||
CallMode::Dec => self.decrement(env, layout_interner, layout),
|
CallMode::Dec => self.decrement(env, layout_interner, layout),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn increment<'a, 'env>(&self, amount: IntValue<'ctx>, env: &Env<'a, 'ctx, 'env>) {
|
fn increment<'a, 'env>(
|
||||||
incref_pointer(env, self.value, amount);
|
&self,
|
||||||
|
amount: IntValue<'ctx>,
|
||||||
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
layout: LayoutRepr<'a>,
|
||||||
|
) {
|
||||||
|
incref_pointer(env, self.value, amount, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrement<'a, 'env>(
|
pub fn decrement<'a, 'env>(
|
||||||
|
@ -158,7 +162,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||||
|
|
||||||
debug_info_init!(env, function_value);
|
debug_info_init!(env, function_value);
|
||||||
|
|
||||||
Self::build_decrement_function_body(env, function_value, alignment);
|
Self::build_decrement_function_body(env, function_value, alignment, layout);
|
||||||
|
|
||||||
function_value
|
function_value
|
||||||
}
|
}
|
||||||
|
@ -180,6 +184,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
parent: FunctionValue<'ctx>,
|
parent: FunctionValue<'ctx>,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
layout: LayoutRepr<'a>,
|
||||||
) {
|
) {
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
let ctx = env.context;
|
let ctx = env.context;
|
||||||
|
@ -193,6 +198,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||||
env,
|
env,
|
||||||
parent.get_nth_param(0).unwrap().into_pointer_value(),
|
parent.get_nth_param(0).unwrap().into_pointer_value(),
|
||||||
alignment,
|
alignment,
|
||||||
|
layout,
|
||||||
);
|
);
|
||||||
|
|
||||||
builder.new_build_return(None);
|
builder.new_build_return(None);
|
||||||
|
@ -202,16 +208,23 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
||||||
&self,
|
&self,
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
layout: LayoutRepr<'a>,
|
||||||
) -> InstructionValue<'ctx> {
|
) -> InstructionValue<'ctx> {
|
||||||
free_pointer(env, self.value, alignment)
|
free_pointer(env, self.value, alignment, layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn debug_assert_not_list(layout: LayoutRepr<'_>) {
|
||||||
|
debug_assert!(!matches!(layout, LayoutRepr::Builtin(Builtin::List(_))), "List are no longer safe to refcount through pointer alone. They must go through the zig bitcode functions");
|
||||||
|
}
|
||||||
|
|
||||||
fn incref_pointer<'ctx>(
|
fn incref_pointer<'ctx>(
|
||||||
env: &Env<'_, 'ctx, '_>,
|
env: &Env<'_, 'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
amount: IntValue<'ctx>,
|
amount: IntValue<'ctx>,
|
||||||
|
layout: LayoutRepr<'_>,
|
||||||
) {
|
) {
|
||||||
|
debug_assert_not_list(layout);
|
||||||
call_void_bitcode_fn(
|
call_void_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
&[
|
&[
|
||||||
|
@ -232,7 +245,9 @@ fn free_pointer<'ctx>(
|
||||||
env: &Env<'_, 'ctx, '_>,
|
env: &Env<'_, 'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
layout: LayoutRepr<'_>,
|
||||||
) -> InstructionValue<'ctx> {
|
) -> InstructionValue<'ctx> {
|
||||||
|
debug_assert_not_list(layout);
|
||||||
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
||||||
call_void_bitcode_fn(
|
call_void_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
|
@ -245,12 +260,19 @@ fn free_pointer<'ctx>(
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
alignment.into(),
|
alignment.into(),
|
||||||
|
env.context.bool_type().const_int(0, false).into(),
|
||||||
],
|
],
|
||||||
roc_builtins::bitcode::UTILS_FREE_RC_PTR,
|
roc_builtins::bitcode::UTILS_FREE_RC_PTR,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decref_pointer<'ctx>(env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, alignment: u32) {
|
fn decref_pointer<'ctx>(
|
||||||
|
env: &Env<'_, 'ctx, '_>,
|
||||||
|
pointer: PointerValue<'ctx>,
|
||||||
|
alignment: u32,
|
||||||
|
layout: LayoutRepr<'_>,
|
||||||
|
) {
|
||||||
|
debug_assert_not_list(layout);
|
||||||
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
||||||
call_void_bitcode_fn(
|
call_void_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
|
@ -263,6 +285,7 @@ fn decref_pointer<'ctx>(env: &Env<'_, 'ctx, '_>, pointer: PointerValue<'ctx>, al
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
alignment.into(),
|
alignment.into(),
|
||||||
|
env.context.bool_type().const_int(0, false).into(),
|
||||||
],
|
],
|
||||||
roc_builtins::bitcode::UTILS_DECREF_RC_PTR,
|
roc_builtins::bitcode::UTILS_DECREF_RC_PTR,
|
||||||
);
|
);
|
||||||
|
@ -273,7 +296,9 @@ pub fn decref_pointer_check_null<'ctx>(
|
||||||
env: &Env<'_, 'ctx, '_>,
|
env: &Env<'_, 'ctx, '_>,
|
||||||
pointer: PointerValue<'ctx>,
|
pointer: PointerValue<'ctx>,
|
||||||
alignment: u32,
|
alignment: u32,
|
||||||
|
layout: LayoutRepr<'_>,
|
||||||
) {
|
) {
|
||||||
|
debug_assert_not_list(layout);
|
||||||
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
let alignment = env.context.i32_type().const_int(alignment as _, false);
|
||||||
call_void_bitcode_fn(
|
call_void_bitcode_fn(
|
||||||
env,
|
env,
|
||||||
|
@ -286,6 +311,7 @@ pub fn decref_pointer_check_null<'ctx>(
|
||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
alignment.into(),
|
alignment.into(),
|
||||||
|
env.context.bool_type().const_int(0, false).into(),
|
||||||
],
|
],
|
||||||
roc_builtins::bitcode::UTILS_DECREF_CHECK_NULL,
|
roc_builtins::bitcode::UTILS_DECREF_CHECK_NULL,
|
||||||
);
|
);
|
||||||
|
@ -764,7 +790,6 @@ fn modify_refcount_list<'a, 'ctx>(
|
||||||
layout_interner,
|
layout_interner,
|
||||||
layout_ids,
|
layout_ids,
|
||||||
mode,
|
mode,
|
||||||
list_layout,
|
|
||||||
element_layout,
|
element_layout,
|
||||||
function_value,
|
function_value,
|
||||||
);
|
);
|
||||||
|
@ -791,7 +816,6 @@ fn modify_refcount_list_help<'a, 'ctx>(
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
layout_ids: &mut LayoutIds<'a>,
|
layout_ids: &mut LayoutIds<'a>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
layout: LayoutRepr<'a>,
|
|
||||||
element_layout: InLayout<'a>,
|
element_layout: InLayout<'a>,
|
||||||
fn_val: FunctionValue<'ctx>,
|
fn_val: FunctionValue<'ctx>,
|
||||||
) {
|
) {
|
||||||
|
@ -807,73 +831,49 @@ fn modify_refcount_list_help<'a, 'ctx>(
|
||||||
|
|
||||||
// Add args to scope
|
// Add args to scope
|
||||||
let arg_symbol = Symbol::ARG_1;
|
let arg_symbol = Symbol::ARG_1;
|
||||||
let arg_val = fn_val.get_param_iter().next().unwrap();
|
let mut param_iter = fn_val.get_param_iter();
|
||||||
|
let arg_val = param_iter.next().unwrap();
|
||||||
|
|
||||||
arg_val.set_name(arg_symbol.as_str(&env.interns));
|
arg_val.set_name(arg_symbol.as_str(&env.interns));
|
||||||
|
|
||||||
let parent = fn_val;
|
|
||||||
let original_wrapper = arg_val.into_struct_value();
|
let original_wrapper = arg_val.into_struct_value();
|
||||||
|
|
||||||
// We use the raw capacity to ensure we always decrement the refcount of seamless slices.
|
// List incrementing and decrementing is more complex now.
|
||||||
let capacity = list_capacity_or_ref_ptr(builder, original_wrapper);
|
// Always go through zig.
|
||||||
|
match mode {
|
||||||
let is_non_empty = builder.new_build_int_compare(
|
Mode::Dec => {
|
||||||
IntPredicate::UGT,
|
let dec_element_fn =
|
||||||
capacity,
|
build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||||
env.ptr_int().const_zero(),
|
call_void_list_bitcode_fn(
|
||||||
"cap > 0",
|
|
||||||
);
|
|
||||||
|
|
||||||
// build blocks
|
|
||||||
let modification_list_block = ctx.append_basic_block(parent, "modification_list_block");
|
|
||||||
let cont_block = ctx.append_basic_block(parent, "modify_rc_list_cont");
|
|
||||||
|
|
||||||
builder.new_build_conditional_branch(is_non_empty, modification_list_block, cont_block);
|
|
||||||
|
|
||||||
builder.position_at_end(modification_list_block);
|
|
||||||
|
|
||||||
if layout_interner.contains_refcounted(element_layout) {
|
|
||||||
let ptr_type = basic_type_from_layout(
|
|
||||||
env,
|
|
||||||
layout_interner,
|
|
||||||
layout_interner.get_repr(element_layout),
|
|
||||||
)
|
|
||||||
.ptr_type(AddressSpace::default());
|
|
||||||
|
|
||||||
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
|
|
||||||
|
|
||||||
let loop_fn = |layout_interner, _index, element| {
|
|
||||||
modify_refcount_layout_help(
|
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
&[original_wrapper],
|
||||||
layout_ids,
|
&[
|
||||||
mode.to_call_mode(fn_val),
|
env.alignment_intvalue(layout_interner, element_layout),
|
||||||
element,
|
layout_width(env, layout_interner, element_layout),
|
||||||
element_layout,
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
);
|
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||||
};
|
],
|
||||||
|
bitcode::LIST_DECREF,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Mode::Inc => {
|
||||||
|
let inc_amount_symbol = Symbol::ARG_2;
|
||||||
|
let inc_amount_val = param_iter.next().unwrap();
|
||||||
|
|
||||||
incrementing_elem_loop(
|
inc_amount_val.set_name(inc_amount_symbol.as_str(&env.interns));
|
||||||
env,
|
|
||||||
layout_interner,
|
call_void_list_bitcode_fn(
|
||||||
parent,
|
env,
|
||||||
element_layout,
|
&[original_wrapper],
|
||||||
ptr,
|
&[
|
||||||
len,
|
inc_amount_val.into_int_value().into(),
|
||||||
"modify_rc_index",
|
layout_refcounted(env, layout_interner, element_layout),
|
||||||
loop_fn,
|
],
|
||||||
);
|
bitcode::LIST_INCREF,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let refcount_ptr =
|
|
||||||
PointerToRefcount::from_ptr_to_data(env, list_allocation_ptr(env, original_wrapper));
|
|
||||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
|
||||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
|
||||||
|
|
||||||
builder.new_build_unconditional_branch(cont_block);
|
|
||||||
|
|
||||||
builder.position_at_end(cont_block);
|
|
||||||
|
|
||||||
// this function returns void
|
// this function returns void
|
||||||
builder.new_build_return(None);
|
builder.new_build_return(None);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue