mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
improve list allocation
This commit is contained in:
parent
b61f5d02b9
commit
45c62dfa3c
2 changed files with 11 additions and 48 deletions
|
@ -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>(
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue