mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 06:44:46 +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::compare::build_eq;
|
||||||
use crate::llvm::convert::{basic_type_from_layout, collection, get_ptr_type, ptr_int};
|
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::builder::Builder;
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::types::{BasicTypeEnum, PointerType};
|
use inkwell::types::{BasicTypeEnum, PointerType};
|
||||||
|
@ -1894,53 +1897,13 @@ pub fn allocate_list<'a, 'ctx, 'env>(
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
let ctx = env.context;
|
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();
|
let len_type = env.ptr_int();
|
||||||
// bytes per element
|
let elem_bytes = elem_layout.stack_size(env.ptr_bytes) as u64;
|
||||||
let bytes_len = len_type.const_int(elem_bytes, false);
|
let bytes_per_element = len_type.const_int(elem_bytes, false);
|
||||||
let offset = (env.ptr_bytes as u64).max(elem_bytes);
|
|
||||||
|
|
||||||
let ptr = {
|
let number_of_data_bytes = builder.build_int_mul(bytes_per_element, length, "data_length");
|
||||||
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");
|
|
||||||
|
|
||||||
env.builder
|
let rc1 = match inplace {
|
||||||
.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 {
|
|
||||||
InPlace::InPlace => length,
|
InPlace::InPlace => length,
|
||||||
InPlace::Clone => {
|
InPlace::Clone => {
|
||||||
// the refcount of a new list is initially 1
|
// 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);
|
allocate_with_refcount_help(env, elem_layout, number_of_data_bytes, rc1)
|
||||||
|
|
||||||
list_element_ptr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store_list<'a, 'ctx, 'env>(
|
pub fn store_list<'a, 'ctx, 'env>(
|
||||||
|
|
|
@ -56,9 +56,11 @@ pub fn str_split<'a, 'ctx, 'env>(
|
||||||
)
|
)
|
||||||
.into_int_value();
|
.into_int_value();
|
||||||
|
|
||||||
|
// a pointer to the elements
|
||||||
let ret_list_ptr =
|
let ret_list_ptr =
|
||||||
allocate_list(env, inplace, &Layout::Builtin(Builtin::Str), segment_count);
|
allocate_list(env, inplace, &Layout::Builtin(Builtin::Str), segment_count);
|
||||||
|
|
||||||
|
// convert `*mut RocStr` to `*mut i128`
|
||||||
let ret_list_ptr_u128s = builder.build_bitcast(
|
let ret_list_ptr_u128s = builder.build_bitcast(
|
||||||
ret_list_ptr,
|
ret_list_ptr,
|
||||||
ctx.i128_type().ptr_type(AddressSpace::Generic),
|
ctx.i128_type().ptr_type(AddressSpace::Generic),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue