mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
allocate taking alignment into account
This commit is contained in:
parent
e02cc3af2f
commit
9198638c23
2 changed files with 45 additions and 35 deletions
|
@ -989,57 +989,54 @@ pub fn allocate_with_refcount<'a, 'ctx, 'env>(
|
||||||
// bytes per element
|
// bytes per element
|
||||||
let bytes_len = len_type.const_int(value_bytes, false);
|
let bytes_len = len_type.const_int(value_bytes, false);
|
||||||
|
|
||||||
let offset = crate::llvm::refcounting::refcount_offset(env, layout);
|
let extra_bytes = layout.alignment_bytes(env.ptr_bytes);
|
||||||
|
let extra_bytes_intvalue = len_type.const_int(extra_bytes as u64, false);
|
||||||
|
|
||||||
let ptr = {
|
let ptr = {
|
||||||
let len = bytes_len;
|
let len = bytes_len;
|
||||||
let len =
|
let len = builder.build_int_add(len, extra_bytes_intvalue, "add_alignment_space");
|
||||||
builder.build_int_add(len, len_type.const_int(offset, false), "add_refcount_space");
|
|
||||||
|
|
||||||
env.builder
|
env.builder
|
||||||
.build_array_malloc(ctx.i8_type(), len, "create_list_ptr")
|
.build_array_malloc(ctx.i8_type(), len, "create_ptr")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
||||||
// TODO check if malloc returned null; if so, runtime error for OOM!
|
// TODO check if malloc returned null; if so, runtime error for OOM!
|
||||||
};
|
};
|
||||||
|
|
||||||
// We must return a pointer to the first element:
|
// We must return a pointer to the first element:
|
||||||
let ptr_bytes = env.ptr_bytes;
|
let data_ptr = {
|
||||||
let int_type = ptr_int(ctx, ptr_bytes);
|
let int_type = ptr_int(ctx, env.ptr_bytes);
|
||||||
let ptr_as_int = builder.build_ptr_to_int(ptr, int_type, "allocate_refcount_pti");
|
let ptr_as_int = builder.build_ptr_to_int(ptr, int_type, "calculate_data_ptr_pti");
|
||||||
let incremented = builder.build_int_add(
|
let incremented = builder.build_int_add(
|
||||||
ptr_as_int,
|
ptr_as_int,
|
||||||
ctx.i64_type().const_int(offset, false),
|
extra_bytes_intvalue,
|
||||||
"increment_list_ptr",
|
"calculate_data_ptr_increment",
|
||||||
);
|
);
|
||||||
|
|
||||||
let ptr_type = get_ptr_type(&value_type, AddressSpace::Generic);
|
let ptr_type = get_ptr_type(&value_type, AddressSpace::Generic);
|
||||||
let list_element_ptr = builder.build_int_to_ptr(incremented, ptr_type, "allocate_refcount_itp");
|
builder.build_int_to_ptr(incremented, ptr_type, "calculate_data_ptr")
|
||||||
|
};
|
||||||
|
|
||||||
// subtract ptr_size, to access the refcount
|
let refcount_ptr = match extra_bytes {
|
||||||
let refcount_ptr = builder.build_int_sub(
|
n if n == env.ptr_bytes => {
|
||||||
incremented,
|
// the malloced pointer is the same as the refcounted pointer
|
||||||
ctx.i64_type().const_int(env.ptr_bytes as u64, false),
|
unsafe { PointerToRefcount::from_ptr(env, ptr) }
|
||||||
"refcount_ptr",
|
}
|
||||||
);
|
n if n == 2 * env.ptr_bytes => {
|
||||||
|
// the refcount is stored just before the start of the actual data
|
||||||
|
// but in this case (because of alignment) not at the start of the malloced buffer
|
||||||
|
PointerToRefcount::from_ptr_to_data(env, data_ptr)
|
||||||
|
}
|
||||||
|
n => unreachable!("invalid extra_bytes {}", n),
|
||||||
|
};
|
||||||
|
|
||||||
let refcount_ptr = builder.build_int_to_ptr(
|
let rc1 = crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes);
|
||||||
refcount_ptr,
|
refcount_ptr.set_refcount(env, rc1);
|
||||||
int_type.ptr_type(AddressSpace::Generic),
|
|
||||||
"make ptr",
|
|
||||||
);
|
|
||||||
|
|
||||||
// the refcount of a new allocation is initially 1
|
|
||||||
// we assume that the allocation is indeed used (dead variables are eliminated)
|
|
||||||
builder.build_store(
|
|
||||||
refcount_ptr,
|
|
||||||
crate::llvm::refcounting::refcount_1(ctx, env.ptr_bytes),
|
|
||||||
);
|
|
||||||
|
|
||||||
// store the value in the pointer
|
// store the value in the pointer
|
||||||
builder.build_store(list_element_ptr, value);
|
builder.build_store(data_ptr, value);
|
||||||
|
|
||||||
list_element_ptr
|
data_ptr
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_literal<'a, 'ctx, 'env>(
|
fn list_literal<'a, 'ctx, 'env>(
|
||||||
|
|
|
@ -5,7 +5,6 @@ use crate::llvm::build::{
|
||||||
use crate::llvm::build_list::list_len;
|
use crate::llvm::build_list::list_len;
|
||||||
use crate::llvm::convert::{basic_type_from_layout, block_of_memory, ptr_int};
|
use crate::llvm::convert::{basic_type_from_layout, block_of_memory, ptr_int};
|
||||||
use bumpalo::collections::Vec;
|
use bumpalo::collections::Vec;
|
||||||
use inkwell::basic_block::BasicBlock;
|
|
||||||
use inkwell::context::Context;
|
use inkwell::context::Context;
|
||||||
use inkwell::module::Linkage;
|
use inkwell::module::Linkage;
|
||||||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue};
|
||||||
|
@ -33,6 +32,20 @@ pub struct PointerToRefcount<'ctx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> PointerToRefcount<'ctx> {
|
impl<'ctx> PointerToRefcount<'ctx> {
|
||||||
|
pub unsafe fn from_ptr<'a, 'env>(env: &Env<'a, 'ctx, 'env>, ptr: PointerValue<'ctx>) -> Self {
|
||||||
|
// must make sure it's a pointer to usize
|
||||||
|
let refcount_type = ptr_int(env.context, env.ptr_bytes);
|
||||||
|
|
||||||
|
let value = cast_basic_basic(
|
||||||
|
env.builder,
|
||||||
|
ptr.into(),
|
||||||
|
refcount_type.ptr_type(AddressSpace::Generic).into(),
|
||||||
|
)
|
||||||
|
.into_pointer_value();
|
||||||
|
|
||||||
|
Self { value }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_ptr_to_data<'a, 'env>(
|
pub fn from_ptr_to_data<'a, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
data_ptr: PointerValue<'ctx>,
|
data_ptr: PointerValue<'ctx>,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue