Merge pull request #3945 from roc-lang/i3942

Adds lambda set layout interning
This commit is contained in:
Folkert de Vries 2022-09-02 21:08:30 +02:00 committed by GitHub
commit 93ace1d6f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1869 additions and 775 deletions

View file

@ -247,7 +247,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) {
let basic_type = basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
let argument = if layout.is_passed_by_reference(env.target_info) {
let argument = if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
env.builder
.build_pointer_cast(
argument_ptr.into_pointer_value(),
@ -268,8 +268,10 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
}
match (
closure_data_layout.is_represented().is_some(),
closure_data_layout.runtime_representation(),
closure_data_layout
.is_represented(env.layout_interner)
.is_some(),
closure_data_layout.runtime_representation(env.layout_interner),
) {
(false, _) => {
// the function doesn't expect a closure argument, nothing to add
@ -402,7 +404,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
let value_type = basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
let value = if layout.is_passed_by_reference(env.target_info) {
let value = if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
env.builder
.build_pointer_cast(value_ptr, value_type, "cast_ptr_to_tag_build_rc_wrapper")
.into()
@ -590,29 +592,30 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
let default = [value1.into(), value2.into()];
let arguments_cast = match closure_data_layout.runtime_representation() {
Layout::Struct {
field_layouts: &[], ..
} => {
// nothing to add
&default
}
other => {
let closure_type =
basic_type_from_layout(env, &other).ptr_type(AddressSpace::Generic);
let arguments_cast =
match closure_data_layout.runtime_representation(env.layout_interner) {
Layout::Struct {
field_layouts: &[], ..
} => {
// nothing to add
&default
}
other => {
let closure_type =
basic_type_from_layout(env, &other).ptr_type(AddressSpace::Generic);
let closure_cast = env
.builder
.build_bitcast(closure_ptr, closure_type, "load_opaque")
.into_pointer_value();
let closure_cast = env
.builder
.build_bitcast(closure_ptr, closure_type, "load_opaque")
.into_pointer_value();
let closure_data = env.builder.build_load(closure_cast, "load_opaque");
let closure_data = env.builder.build_load(closure_cast, "load_opaque");
env.arena
.alloc([value1.into(), value2.into(), closure_data.into()])
as &[_]
}
};
env.arena
.alloc([value1.into(), value2.into(), closure_data.into()])
as &[_]
}
};
let call = env.builder.build_call(
roc_function,

View file

@ -57,7 +57,7 @@ use roc_mono::ir::{
};
use roc_mono::layout::{
Builtin, CapturesNiche, LambdaName, LambdaSet, Layout, LayoutIds, RawFunctionLayout,
TagIdIntType, UnionLayout,
STLayoutInterner, TagIdIntType, UnionLayout,
};
use roc_std::RocDec;
use roc_target::{PtrWidth, TargetInfo};
@ -203,6 +203,7 @@ impl LlvmBackendMode {
pub struct Env<'a, 'ctx, 'env> {
pub arena: &'a Bump,
pub layout_interner: &'env STLayoutInterner<'a>,
pub context: &'ctx Context,
pub builder: &'env Builder<'ctx>,
pub dibuilder: &'env DebugInfoBuilder<'ctx>,
@ -311,7 +312,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
}
pub fn alignment_intvalue(&self, element_layout: &Layout<'a>) -> BasicValueEnum<'ctx> {
let alignment = element_layout.alignment_bytes(self.target_info);
let alignment = element_layout.alignment_bytes(self.layout_interner, self.target_info);
let alignment_iv = self.alignment_const(alignment);
alignment_iv.into()
@ -880,7 +881,9 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx, 'env>(
let roc_main_fn_result = call_roc_function(env, roc_main_fn, &top_level.result, &[]);
// For consistency, we always return with a heap-allocated value
let (size, alignment) = top_level.result.stack_size_and_alignment(env.target_info);
let (size, alignment) = top_level
.result
.stack_size_and_alignment(env.layout_interner, env.target_info);
let number_of_bytes = env.ptr_int().const_int(size as _, false);
let void_ptr = env.call_alloc(number_of_bytes, alignment);
@ -1249,8 +1252,8 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
let allocation = reserve_with_refcount_help(
env,
basic_type,
layout.stack_size(env.target_info),
layout.alignment_bytes(env.target_info),
layout.stack_size(env.layout_interner, env.target_info),
layout.alignment_bytes(env.layout_interner, env.target_info),
);
store_roc_value(env, *layout, allocation, value);
@ -1328,7 +1331,7 @@ pub fn build_exp_expr<'a, 'ctx, 'env>(
let (value, layout) = load_symbol_and_layout(scope, structure);
let layout = if let Layout::LambdaSet(lambda_set) = layout {
lambda_set.runtime_representation()
lambda_set.runtime_representation(env.layout_interner)
} else {
*layout
};
@ -1600,7 +1603,7 @@ fn build_tag_field_value<'a, 'ctx, 'env>(
env.context.i64_type().ptr_type(AddressSpace::Generic),
"cast_recursive_pointer",
)
} else if tag_field_layout.is_passed_by_reference(env.target_info) {
} else if tag_field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
debug_assert!(value.is_pointer_value());
// NOTE: we rely on this being passed to `store_roc_value` so that
@ -1661,7 +1664,7 @@ fn build_struct<'a, 'ctx, 'env>(
if !field_layout.is_dropped_because_empty() {
field_types.push(basic_type_from_layout(env, field_layout));
if field_layout.is_passed_by_reference(env.target_info) {
if field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let field_value = env
.builder
.build_load(field_expr.into_pointer_value(), "load_tag_to_put_in_struct");
@ -1697,7 +1700,12 @@ fn build_tag<'a, 'ctx, 'env>(
let data = build_struct(env, scope, arguments);
let roc_union = RocUnion::tagged_from_slices(env.context, tags, env.target_info);
let roc_union = RocUnion::tagged_from_slices(
env.layout_interner,
env.context,
tags,
env.target_info,
);
let value = roc_union.as_struct_value(env, data, Some(tag_id as _));
let alloca = create_entry_block_alloca(
@ -1788,8 +1796,12 @@ fn build_tag<'a, 'ctx, 'env>(
nullable_id,
other_fields,
} => {
let roc_union =
RocUnion::untagged_from_slices(env.context, &[other_fields], env.target_info);
let roc_union = RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
&[other_fields],
env.target_info,
);
if tag_id == *nullable_id as _ {
let output_type = roc_union.struct_type().ptr_type(AddressSpace::Generic);
@ -2104,8 +2116,8 @@ pub fn reserve_with_refcount<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: &Layout<'a>,
) -> PointerValue<'ctx> {
let stack_size = layout.stack_size(env.target_info);
let alignment_bytes = layout.alignment_bytes(env.target_info);
let stack_size = layout.stack_size(env.layout_interner, env.target_info);
let alignment_bytes = layout.alignment_bytes(env.layout_interner, env.target_info);
let basic_type = basic_type_from_layout(env, layout);
@ -2120,9 +2132,9 @@ fn reserve_with_refcount_union_as_block_of_memory<'a, 'ctx, 'env>(
let ptr_bytes = env.target_info;
let roc_union = if union_layout.stores_tag_id_as_data(ptr_bytes) {
RocUnion::tagged_from_slices(env.context, fields, env.target_info)
RocUnion::tagged_from_slices(env.layout_interner, env.context, fields, env.target_info)
} else {
RocUnion::untagged_from_slices(env.context, fields, env.target_info)
RocUnion::untagged_from_slices(env.layout_interner, env.context, fields, env.target_info)
};
reserve_with_refcount_help(
@ -2211,10 +2223,10 @@ fn list_literal<'a, 'ctx, 'env>(
// if element_type.is_int_type() {
if false {
let element_type = element_type.into_int_type();
let element_width = element_layout.stack_size(env.target_info);
let element_width = element_layout.stack_size(env.layout_interner, env.target_info);
let size = list_length * element_width as usize;
let alignment = element_layout
.alignment_bytes(env.target_info)
.alignment_bytes(env.layout_interner, env.target_info)
.max(env.target_info.ptr_width() as u32);
let mut is_all_constant = true;
@ -2351,7 +2363,7 @@ pub fn load_roc_value<'a, 'ctx, 'env>(
source: PointerValue<'ctx>,
name: &str,
) -> BasicValueEnum<'ctx> {
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let alloca = entry_block_alloca_zerofill(env, basic_type_from_layout(env, &layout), name);
store_roc_value(env, layout, alloca, source.into());
@ -2368,7 +2380,7 @@ pub fn use_roc_value<'a, 'ctx, 'env>(
source: BasicValueEnum<'ctx>,
name: &str,
) -> BasicValueEnum<'ctx> {
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let alloca = entry_block_alloca_zerofill(env, basic_type_from_layout(env, &layout), name);
env.builder.build_store(alloca, source);
@ -2399,15 +2411,16 @@ pub fn store_roc_value<'a, 'ctx, 'env>(
destination: PointerValue<'ctx>,
value: BasicValueEnum<'ctx>,
) {
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
debug_assert!(value.is_pointer_value());
let align_bytes = layout.alignment_bytes(env.target_info);
let align_bytes = layout.alignment_bytes(env.layout_interner, env.target_info);
if align_bytes > 0 {
let size = env
.ptr_int()
.const_int(layout.stack_size(env.target_info) as u64, false);
let size = env.ptr_int().const_int(
layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
env.builder
.build_memcpy(
@ -2502,8 +2515,9 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
// store_roc_value(env, *layout, out_parameter.into_pointer_value(), value);
let destination = out_parameter.into_pointer_value();
if layout.is_passed_by_reference(env.target_info) {
let align_bytes = layout.alignment_bytes(env.target_info);
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let align_bytes =
layout.alignment_bytes(env.layout_interner, env.target_info);
if align_bytes > 0 {
debug_assert!(
@ -2534,7 +2548,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
// Hence, we explicitly memcpy source to destination, and rely on
// LLVM optimizing away any inefficiencies.
let target_info = env.target_info;
let width = layout.stack_size(target_info);
let width = layout.stack_size(env.layout_interner, target_info);
let size = env.ptr_int().const_int(width as _, false);
env.builder
@ -2614,7 +2628,10 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
for param in parameters.iter() {
let basic_type = basic_type_from_layout(env, &param.layout);
let phi_type = if param.layout.is_passed_by_reference(env.target_info) {
let phi_type = if param
.layout
.is_passed_by_reference(env.layout_interner, env.target_info)
{
basic_type.ptr_type(AddressSpace::Generic).into()
} else {
basic_type
@ -2697,7 +2714,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
let (value, layout) = load_symbol_and_layout(scope, symbol);
let layout = *layout;
if layout.contains_refcounted() {
if layout.contains_refcounted(env.layout_interner) {
increment_refcount_layout(
env,
parent,
@ -2713,7 +2730,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
Dec(symbol) => {
let (value, layout) = load_symbol_and_layout(scope, symbol);
if layout.contains_refcounted() {
if layout.contains_refcounted(env.layout_interner) {
decrement_refcount_layout(env, parent, layout_ids, value, layout);
}
@ -2726,7 +2743,8 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::Str) => todo!(),
Layout::Builtin(Builtin::List(element_layout)) => {
debug_assert!(value.is_struct_value());
let alignment = element_layout.alignment_bytes(env.target_info);
let alignment = element_layout
.alignment_bytes(env.layout_interner, env.target_info);
build_list::decref(env, value.into_struct_value(), alignment);
}
@ -4155,7 +4173,7 @@ fn make_good_roc_result<'a, 'ctx, 'env>(
.build_insert_value(v1, context.i64_type().const_zero(), 0, "set_no_error")
.unwrap();
let v3 = if return_layout.is_passed_by_reference(env.target_info) {
let v3 = if return_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let loaded = env.builder.build_load(
return_value.into_pointer_value(),
"load_call_result_passed_by_ptr",
@ -4418,10 +4436,12 @@ fn build_procedures_help<'a, 'ctx, 'env>(
let it = procedures.iter().map(|x| x.1);
let solutions = match roc_alias_analysis::spec_program(opt_level, opt_entry_point, it) {
Err(e) => panic!("Error in alias analysis: {}", e),
Ok(solutions) => solutions,
};
let solutions =
match roc_alias_analysis::spec_program(env.layout_interner, opt_level, opt_entry_point, it)
{
Err(e) => panic!("Error in alias analysis: {}", e),
Ok(solutions) => solutions,
};
let solutions = env.arena.alloc(solutions);
@ -4687,7 +4707,8 @@ fn build_closure_caller<'a, 'ctx, 'env>(
}
let closure_argument_type = {
let basic_type = basic_type_from_layout(env, &lambda_set.runtime_representation());
let basic_type =
basic_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner));
basic_type.ptr_type(AddressSpace::Generic)
};
@ -4734,10 +4755,12 @@ fn build_closure_caller<'a, 'ctx, 'env>(
// NOTE this may be incorrect in the long run
// here we load any argument that is a pointer
let closure_layout = lambda_set.runtime_representation();
let closure_layout = lambda_set.runtime_representation(env.layout_interner);
let layouts_it = arguments.iter().chain(std::iter::once(&closure_layout));
for (param, layout) in evaluator_arguments.iter_mut().zip(layouts_it) {
if param.is_pointer_value() && !layout.is_passed_by_reference(env.target_info) {
if param.is_pointer_value()
&& !layout.is_passed_by_reference(env.layout_interner, env.target_info)
{
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
}
@ -4755,13 +4778,14 @@ fn build_closure_caller<'a, 'ctx, 'env>(
} else {
let call_result = call_roc_function(env, evaluator, return_layout, &evaluator_arguments);
if return_layout.is_passed_by_reference(env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.target_info);
if return_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let align_bytes = return_layout.alignment_bytes(env.layout_interner, env.target_info);
if align_bytes > 0 {
let size = env
.ptr_int()
.const_int(return_layout.stack_size(env.target_info) as u64, false);
let size = env.ptr_int().const_int(
return_layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
env.builder
.build_memcpy(
@ -4788,7 +4812,7 @@ fn build_closure_caller<'a, 'ctx, 'env>(
env,
def_name,
alias_symbol,
lambda_set.runtime_representation(),
lambda_set.runtime_representation(env.layout_interner),
);
}
@ -5058,7 +5082,7 @@ pub fn call_roc_function<'a, 'ctx, 'env>(
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
call.set_call_convention(FAST_CALL_CONV);
if result_layout.is_passed_by_reference(env.target_info) {
if result_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
result_alloca.into()
} else {
env.builder
@ -5140,10 +5164,13 @@ fn roc_function_call<'a, 'ctx, 'env>(
.as_global_value()
.as_pointer_value();
let inc_closure_data =
build_inc_n_wrapper(env, layout_ids, &lambda_set.runtime_representation())
.as_global_value()
.as_pointer_value();
let inc_closure_data = build_inc_n_wrapper(
env,
layout_ids,
&lambda_set.runtime_representation(env.layout_interner),
)
.as_global_value()
.as_pointer_value();
let closure_data_is_owned = env
.context
@ -6482,7 +6509,7 @@ fn to_cc_type<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: &Layout<'a>,
) -> BasicTypeEnum<'ctx> {
match layout.runtime_representation() {
match layout.runtime_representation(env.layout_interner) {
Layout::Builtin(builtin) => to_cc_type_builtin(env, &builtin),
layout => {
// TODO this is almost certainly incorrect for bigger structs
@ -6524,7 +6551,11 @@ enum RocReturn {
}
impl RocReturn {
fn roc_return_by_pointer(target_info: TargetInfo, layout: Layout) -> bool {
fn roc_return_by_pointer(
interner: &STLayoutInterner,
target_info: TargetInfo,
layout: Layout,
) -> bool {
match layout {
Layout::Builtin(builtin) => {
use Builtin::*;
@ -6539,15 +6570,17 @@ impl RocReturn {
}
}
Layout::Union(UnionLayout::NonRecursive(_)) => true,
Layout::LambdaSet(lambda_set) => {
RocReturn::roc_return_by_pointer(target_info, lambda_set.runtime_representation())
}
Layout::LambdaSet(lambda_set) => RocReturn::roc_return_by_pointer(
interner,
target_info,
lambda_set.runtime_representation(interner),
),
_ => false,
}
}
fn from_layout<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) -> Self {
if Self::roc_return_by_pointer(env.target_info, *layout) {
if Self::roc_return_by_pointer(env.layout_interner, env.target_info, *layout) {
RocReturn::ByPointer
} else {
RocReturn::Return
@ -6685,7 +6718,7 @@ impl<'ctx> FunctionSpec<'ctx> {
/// According to the C ABI, how should we return a value with the given layout?
pub fn to_cc_return<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) -> CCReturn {
let return_size = layout.stack_size(env.target_info);
let return_size = layout.stack_size(env.layout_interner, env.target_info);
let pass_result_by_pointer = return_size > 2 * env.target_info.ptr_width() as u32;
if return_size == 0 {

View file

@ -82,7 +82,10 @@ pub(crate) fn layout_width<'a, 'ctx, 'env>(
layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
env.ptr_int()
.const_int(layout.stack_size(env.target_info) as u64, false)
.const_int(
layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
)
.into()
}
@ -317,7 +320,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
// the list has the same alignment as a usize / ptr. The element comes first in the struct if
// its alignment is bigger than that of a list.
let element_align = element_layout.alignment_bytes(env.target_info);
let element_align = element_layout.alignment_bytes(env.layout_interner, env.target_info);
let element_first = element_align > env.target_info.ptr_width() as u32;
let fields = if element_first {
@ -715,13 +718,13 @@ pub(crate) fn allocate_list<'a, 'ctx, 'env>(
let builder = env.builder;
let len_type = env.ptr_int();
let elem_bytes = elem_layout.stack_size(env.target_info) as u64;
let elem_bytes = elem_layout.stack_size(env.layout_interner, env.target_info) as u64;
let bytes_per_element = len_type.const_int(elem_bytes, false);
let number_of_data_bytes =
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
let basic_type = basic_type_from_layout(env, elem_layout);
let alignment_bytes = elem_layout.alignment_bytes(env.target_info);
let alignment_bytes = elem_layout.alignment_bytes(env.layout_interner, env.target_info);
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
}

View file

@ -5,7 +5,7 @@ use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
use inkwell::values::StructValue;
use inkwell::AddressSpace;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_mono::layout::{round_up_to_alignment, Builtin, Layout, UnionLayout};
use roc_mono::layout::{round_up_to_alignment, Builtin, Layout, STLayoutInterner, UnionLayout};
use roc_target::TargetInfo;
fn basic_type_from_record<'a, 'ctx, 'env>(
@ -34,7 +34,9 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
field_layouts: sorted_fields,
..
} => basic_type_from_record(env, sorted_fields),
LambdaSet(lambda_set) => basic_type_from_layout(env, &lambda_set.runtime_representation()),
LambdaSet(lambda_set) => {
basic_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner))
}
Boxed(inner_layout) => {
let inner_type = basic_type_from_layout(env, inner_layout);
@ -60,7 +62,7 @@ pub fn basic_type_from_union_layout<'a, 'ctx, 'env>(
match union_layout {
NonRecursive(tags) => {
//
RocUnion::tagged_from_slices(env.context, tags, env.target_info)
RocUnion::tagged_from_slices(env.layout_interner, env.context, tags, env.target_info)
.struct_type()
.into()
}
@ -69,29 +71,45 @@ pub fn basic_type_from_union_layout<'a, 'ctx, 'env>(
other_tags: tags, ..
} => {
if union_layout.stores_tag_id_as_data(env.target_info) {
RocUnion::tagged_from_slices(env.context, tags, env.target_info)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into()
RocUnion::tagged_from_slices(
env.layout_interner,
env.context,
tags,
env.target_info,
)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into()
} else {
RocUnion::untagged_from_slices(env.context, tags, env.target_info)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into()
RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
tags,
env.target_info,
)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into()
}
}
NullableUnwrapped { other_fields, .. } => {
RocUnion::untagged_from_slices(env.context, &[other_fields], env.target_info)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into()
}
NonNullableUnwrapped(fields) => {
RocUnion::untagged_from_slices(env.context, &[fields], env.target_info)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into()
}
NullableUnwrapped { other_fields, .. } => RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
&[other_fields],
env.target_info,
)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into(),
NonNullableUnwrapped(fields) => RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
&[fields],
env.target_info,
)
.struct_type()
.ptr_type(AddressSpace::Generic)
.into(),
}
}
@ -132,13 +150,13 @@ pub fn argument_type_from_layout<'a, 'ctx, 'env>(
match layout {
LambdaSet(lambda_set) => {
argument_type_from_layout(env, &lambda_set.runtime_representation())
argument_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner))
}
Union(union_layout) => argument_type_from_union_layout(env, union_layout),
Builtin(_) => {
let base = basic_type_from_layout(env, layout);
if layout.is_passed_by_reference(env.target_info) {
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
base.ptr_type(AddressSpace::Generic).into()
} else {
base
@ -275,6 +293,7 @@ impl<'ctx> RocUnion<'ctx> {
}
pub fn tagged_from_slices(
interner: &STLayoutInterner,
context: &'ctx Context,
layouts: &[&[Layout<'_>]],
target_info: TargetInfo,
@ -285,18 +304,19 @@ impl<'ctx> RocUnion<'ctx> {
};
let (data_width, data_align) =
Layout::stack_size_and_alignment_slices(layouts, target_info);
Layout::stack_size_and_alignment_slices(interner, layouts, target_info);
Self::new(context, target_info, data_align, data_width, Some(tag_type))
}
pub fn untagged_from_slices(
interner: &STLayoutInterner,
context: &'ctx Context,
layouts: &[&[Layout<'_>]],
target_info: TargetInfo,
) -> Self {
let (data_width, data_align) =
Layout::stack_size_and_alignment_slices(layouts, target_info);
Layout::stack_size_and_alignment_slices(interner, layouts, target_info);
Self::new(context, target_info, data_align, data_width, None)
}

View file

@ -137,9 +137,10 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
let (value, layout) = load_symbol_and_layout(scope, lookup);
let stack_size = env
.ptr_int()
.const_int(layout.stack_size(env.target_info) as u64, false);
let stack_size = env.ptr_int().const_int(
layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
let mut extra_offset = env.builder.build_int_add(offset, stack_size, "offset");
@ -221,7 +222,7 @@ fn build_clone<'a, 'ctx, 'env>(
Layout::LambdaSet(_) => unreachable!("cannot compare closures"),
Layout::Union(union_layout) => {
if layout.safe_to_memcpy() {
if layout.safe_to_memcpy(env.layout_interner) {
let ptr = unsafe {
env.builder
.build_in_bounds_gep(ptr, &[cursors.offset], "at_current_offset")
@ -255,9 +256,10 @@ fn build_clone<'a, 'ctx, 'env>(
let source = value.into_pointer_value();
let value = load_roc_value(env, *inner_layout, source, "inner");
let inner_width = env
.ptr_int()
.const_int(inner_layout.stack_size(env.target_info) as u64, false);
let inner_width = env.ptr_int().const_int(
inner_layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
let new_extra = env
.builder
@ -318,7 +320,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
) -> IntValue<'ctx> {
let layout = Layout::struct_no_name_order(field_layouts);
if layout.safe_to_memcpy() {
if layout.safe_to_memcpy(env.layout_interner) {
build_copy(env, ptr, cursors.offset, value)
} else {
let mut cursors = cursors;
@ -343,9 +345,10 @@ fn build_clone_struct<'a, 'ctx, 'env>(
when_recursive,
);
let field_width = env
.ptr_int()
.const_int(field_layout.stack_size(env.target_info) as u64, false);
let field_width = env.ptr_int().const_int(
field_layout.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
cursors.extra_offset = new_extra;
cursors.offset = env
@ -576,7 +579,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let data = env.builder.build_load(data_ptr, "load_data");
let (width, _) = union_layout.data_size_and_alignment(env.target_info);
let (width, _) =
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
let cursors = Cursors {
offset: extra_offset,
@ -618,7 +622,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let layout = Layout::struct_no_name_order(fields);
let basic_type = basic_type_from_layout(env, &layout);
let (width, _) = union_layout.data_size_and_alignment(env.target_info);
let (width, _) =
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
let cursors = Cursors {
offset: extra_offset,
@ -686,7 +691,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let layout = Layout::struct_no_name_order(fields);
let basic_type = basic_type_from_layout(env, &layout);
let (width, _) = union_layout.data_size_and_alignment(env.target_info);
let (width, _) =
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
let cursors = Cursors {
offset: extra_offset,
@ -776,8 +782,10 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
offset: extra_offset,
extra_offset: env.builder.build_int_add(
extra_offset,
env.ptr_int()
.const_int(layout.stack_size(env.target_info) as _, false),
env.ptr_int().const_int(
layout.stack_size(env.layout_interner, env.target_info) as _,
false,
),
"new_offset",
),
};
@ -907,12 +915,13 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
offset = build_copy(env, ptr, offset, len.into());
offset = build_copy(env, ptr, offset, len.into());
let (element_width, _element_align) = elem.stack_size_and_alignment(env.target_info);
let (element_width, _element_align) =
elem.stack_size_and_alignment(env.layout_interner, env.target_info);
let element_width = env.ptr_int().const_int(element_width as _, false);
let elements_width = bd.build_int_mul(element_width, len, "elements_width");
if elem.safe_to_memcpy() {
if elem.safe_to_memcpy(env.layout_interner) {
// NOTE we are not actually sure the dest is properly aligned
let dest = pointer_at_offset(bd, ptr, offset);
let src = bd.build_pointer_cast(
@ -936,9 +945,10 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
// if the element has any pointers, we clone them to this offset
let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset");
let element_stack_size = env
.ptr_int()
.const_int(elem.stack_size(env.target_info) as u64, false);
let element_stack_size = env.ptr_int().const_int(
elem.stack_size(env.layout_interner, env.target_info) as u64,
false,
);
let rest_start_offset = bd.build_int_add(
cursors.extra_offset,
bd.build_int_mul(len, element_stack_size, "elements_width"),

View file

@ -16,7 +16,7 @@ use inkwell::values::{
use inkwell::{AddressSpace, IntPredicate};
use roc_module::symbol::Interns;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
use roc_mono::layout::{Builtin, Layout, LayoutIds, STLayoutInterner, UnionLayout};
use super::build::{load_roc_value, FunctionSpec};
use super::convert::{argument_type_from_layout, argument_type_from_union_layout};
@ -124,7 +124,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
let alignment = layout
.allocation_alignment_bytes(env.target_info)
.allocation_alignment_bytes(env.layout_interner, env.target_info)
.max(env.target_info.ptr_width() as u32);
let context = env.context;
@ -332,7 +332,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
let wrapper_struct = arg_val.into_struct_value();
for (i, field_layout) in layouts.iter().enumerate() {
if field_layout.contains_refcounted() {
if field_layout.contains_refcounted(env.layout_interner) {
let raw_value = env
.builder
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
@ -613,7 +613,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
when_recursive,
&lambda_set.runtime_representation(),
&lambda_set.runtime_representation(env.layout_interner),
),
}
}
@ -717,7 +717,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
builder.position_at_end(modification_block);
if element_layout.contains_refcounted() {
if element_layout.contains_refcounted(env.layout_interner) {
let ptr_type = basic_type_from_layout(env, element_layout).ptr_type(AddressSpace::Generic);
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
@ -818,7 +818,9 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
let parent = fn_val;
let arg_val = if Layout::Builtin(Builtin::Str).is_passed_by_reference(env.target_info) {
let arg_val = if Layout::Builtin(Builtin::Str)
.is_passed_by_reference(env.layout_interner, env.target_info)
{
env.builder
.build_load(arg_val.into_pointer_value(), "load_str_to_stack")
} else {
@ -1178,10 +1180,10 @@ enum DecOrReuse {
Reuse,
}
fn fields_need_no_refcounting(field_layouts: &[Layout]) -> bool {
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[Layout]) -> bool {
!field_layouts
.iter()
.any(|x| x.is_refcounted() || x.contains_refcounted())
.any(|x| x.is_refcounted() || x.contains_refcounted(interner))
}
#[allow(clippy::too_many_arguments)]
@ -1211,7 +1213,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
for (tag_id, field_layouts) in tags.iter().enumerate() {
// if none of the fields are or contain anything refcounted, just move on
if fields_need_no_refcounting(field_layouts) {
if fields_need_no_refcounting(env.layout_interner, field_layouts) {
continue;
}
@ -1256,7 +1258,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
deferred_rec.push(recursive_field_ptr);
} else if field_layout.contains_refcounted() {
} else if field_layout.contains_refcounted(env.layout_interner) {
let elem_pointer = env
.builder
.build_struct_gep(struct_ptr, i as u32, "gep_recursive_pointer")
@ -1620,7 +1622,7 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
// if none of the fields are or contain anything refcounted, just move on
if !field_layouts
.iter()
.any(|x| x.is_refcounted() || x.contains_refcounted())
.any(|x| x.is_refcounted() || x.contains_refcounted(env.layout_interner))
{
continue;
}
@ -1678,17 +1680,18 @@ fn modify_refcount_union_help<'a, 'ctx, 'env>(
recursive_ptr_field_value,
&Layout::RecursivePointer,
)
} else if field_layout.contains_refcounted() {
} else if field_layout.contains_refcounted(env.layout_interner) {
let field_ptr = env
.builder
.build_struct_gep(cast_tag_data_pointer, i as u32, "modify_tag_field")
.unwrap();
let field_value = if field_layout.is_passed_by_reference(env.target_info) {
field_ptr.into()
} else {
env.builder.build_load(field_ptr, "field_value")
};
let field_value =
if field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
field_ptr.into()
} else {
env.builder.build_load(field_ptr, "field_value")
};
modify_refcount_layout_help(
env,