diff --git a/compiler/gen/src/llvm/build_list.rs b/compiler/gen/src/llvm/build_list.rs index 77ee9909bc..ab0e766f0e 100644 --- a/compiler/gen/src/llvm/build_list.rs +++ b/compiler/gen/src/llvm/build_list.rs @@ -1,6 +1,9 @@ -use crate::llvm::build::{build_num_binop, Env, InPlace}; +use crate::llvm::build::{ + allocate_with_refcount_help, build_num_binop, cast_basic_basic, Env, InPlace, +}; use crate::llvm::compare::build_eq; use crate::llvm::convert::{basic_type_from_layout, collection, get_ptr_type, ptr_int}; +use crate::llvm::refcounting::PointerToRefcount; use inkwell::builder::Builder; use inkwell::context::Context; use inkwell::types::{BasicTypeEnum, PointerType}; @@ -1894,53 +1897,13 @@ pub fn allocate_list<'a, 'ctx, 'env>( let builder = env.builder; let ctx = env.context; - let elem_type = basic_type_from_layout(env.arena, ctx, elem_layout, env.ptr_bytes); - let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64; - let len_type = env.ptr_int(); - // bytes per element - let bytes_len = len_type.const_int(elem_bytes, false); - let offset = (env.ptr_bytes as u64).max(elem_bytes); + let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64; + let bytes_per_element = len_type.const_int(elem_bytes, false); - let ptr = { - let len = builder.build_int_mul(bytes_len, length, "data_length"); - let len = - builder.build_int_add(len, len_type.const_int(offset, false), "add_refcount_space"); + let number_of_data_bytes = builder.build_int_mul(bytes_per_element, length, "data_length"); - env.builder - .build_array_malloc(ctx.i8_type(), len, "create_list_ptr") - .unwrap() - - // TODO check if malloc returned null; if so, runtime error for OOM! - }; - - // We must return a pointer to the first element: - let ptr_bytes = env.ptr_bytes; - let int_type = ptr_int(ctx, ptr_bytes); - let ptr_as_int = builder.build_ptr_to_int(ptr, int_type, "list_cast_ptr"); - let incremented = builder.build_int_add( - ptr_as_int, - ctx.i64_type().const_int(offset, false), - "increment_list_ptr", - ); - - let ptr_type = get_ptr_type(&elem_type, AddressSpace::Generic); - let list_element_ptr = builder.build_int_to_ptr(incremented, ptr_type, "list_cast_ptr"); - - // subtract ptr_size, to access the refcount - let refcount_ptr = builder.build_int_sub( - incremented, - ctx.i64_type().const_int(env.ptr_bytes as u64, false), - "refcount_ptr", - ); - - let refcount_ptr = builder.build_int_to_ptr( - refcount_ptr, - int_type.ptr_type(AddressSpace::Generic), - "make ptr", - ); - - let ref_count_one = match inplace { + let rc1 = match inplace { InPlace::InPlace => length, InPlace::Clone => { // the refcount of a new list is initially 1 @@ -1949,9 +1912,7 @@ pub fn allocate_list<'a, 'ctx, 'env>( } }; - builder.build_store(refcount_ptr, ref_count_one); - - list_element_ptr + allocate_with_refcount_help(env, elem_layout, number_of_data_bytes, rc1) } pub fn store_list<'a, 'ctx, 'env>( diff --git a/compiler/gen/src/llvm/build_str.rs b/compiler/gen/src/llvm/build_str.rs index 24b18a5943..24092ed851 100644 --- a/compiler/gen/src/llvm/build_str.rs +++ b/compiler/gen/src/llvm/build_str.rs @@ -56,9 +56,11 @@ pub fn str_split<'a, 'ctx, 'env>( ) .into_int_value(); + // a pointer to the elements let ret_list_ptr = allocate_list(env, inplace, &Layout::Builtin(Builtin::Str), segment_count); + // convert `*mut RocStr` to `*mut i128` let ret_list_ptr_u128s = builder.build_bitcast( ret_list_ptr, ctx.i128_type().ptr_type(AddressSpace::Generic),