Push mutable layout interner through llvm backend

This commit is contained in:
Ayaz Hafiz 2022-12-29 10:04:43 -06:00
parent e4b5252e51
commit 512a1721ae
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
8 changed files with 1289 additions and 555 deletions

View file

@ -17,7 +17,7 @@ use inkwell::values::{
use inkwell::AddressSpace;
use roc_error_macros::internal_error;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds};
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner};
use super::build::{create_entry_block_alloca, BuilderExt};
use super::convert::zig_list_type;
@ -95,13 +95,14 @@ fn call_bitcode_fn_help<'a, 'ctx, 'env>(
pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
bitcode_return_type: StructType<'ctx>,
args: &[BasicValueEnum<'ctx>],
return_layout: &Layout<'_>,
return_layout: &Layout<'a>,
fn_name: &str,
) -> BasicValueEnum<'ctx> {
// Calling zig bitcode, so we must follow C calling conventions.
let cc_return = to_cc_return(env, return_layout);
let cc_return = to_cc_return(env, layout_interner, return_layout);
match cc_return {
CCReturn::Return => {
// We'll get a return value
@ -109,7 +110,7 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
}
CCReturn::ByPointer => {
// We need to pass the return value by pointer.
let roc_return_type = basic_type_from_layout(env, return_layout);
let roc_return_type = basic_type_from_layout(env, layout_interner, return_layout);
let cc_return_type: BasicTypeEnum<'ctx> = bitcode_return_type.into();
@ -164,6 +165,7 @@ const ARGUMENT_SYMBOLS: [Symbol; 8] = [
pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>,
argument_layouts: &[Layout<'a>],
@ -178,6 +180,7 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
Some(function_value) => function_value,
None => build_transform_caller_help(
env,
layout_interner,
function,
closure_data_layout,
argument_layouts,
@ -189,6 +192,7 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
fn build_transform_caller_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>,
argument_layouts: &[Layout<'a>],
@ -237,7 +241,8 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
bumpalo::collections::Vec::with_capacity_in(arguments.len(), env.arena);
for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) {
let basic_type = basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
let basic_type =
basic_type_from_layout(env, layout_interner, layout).ptr_type(AddressSpace::Generic);
let cast_ptr = env.builder.build_pointer_cast(
argument_ptr.into_pointer_value(),
@ -245,28 +250,36 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
"cast_ptr_to_tag_build_transform_caller_help",
);
let argument = load_roc_value(env, *layout, cast_ptr, "zig_helper_load_opaque");
let argument = load_roc_value(
env,
layout_interner,
*layout,
cast_ptr,
"zig_helper_load_opaque",
);
arguments_cast.push(argument);
}
match (
closure_data_layout
.is_represented(env.layout_interner)
.is_represented(layout_interner)
.is_some(),
closure_data_layout.runtime_representation(env.layout_interner),
closure_data_layout.runtime_representation(layout_interner),
) {
(false, _) => {
// the function doesn't expect a closure argument, nothing to add
}
(true, layout) => {
let closure_type = basic_type_from_layout(env, &layout).ptr_type(AddressSpace::Generic);
let closure_type = basic_type_from_layout(env, layout_interner, &layout)
.ptr_type(AddressSpace::Generic);
let closure_cast =
env.builder
.build_pointer_cast(closure_ptr, closure_type, "cast_opaque_closure");
let closure_data = load_roc_value(env, layout, closure_cast, "load_closure");
let closure_data =
load_roc_value(env, layout_interner, layout, closure_cast, "load_closure");
arguments_cast.push(closure_data);
}
@ -274,6 +287,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
let result = crate::llvm::build::call_roc_function(
env,
layout_interner,
roc_function,
&result_layout,
arguments_cast.as_slice(),
@ -284,7 +298,13 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
.unwrap()
.into_pointer_value();
crate::llvm::build::store_roc_value_opaque(env, result_layout, result_u8_ptr, result);
crate::llvm::build::store_roc_value_opaque(
env,
layout_interner,
result_layout,
result_u8_ptr,
result,
);
env.builder.build_return(None);
env.builder.position_at_end(block);
@ -303,31 +323,35 @@ enum Mode {
/// a function that accepts two arguments: the value to increment, and an amount to increment by
pub fn build_inc_n_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>,
) -> FunctionValue<'ctx> {
build_rc_wrapper(env, layout_ids, layout, Mode::IncN)
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::IncN)
}
/// a function that accepts two arguments: the value to increment; increments by 1
pub fn build_inc_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>,
) -> FunctionValue<'ctx> {
build_rc_wrapper(env, layout_ids, layout, Mode::Inc)
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Inc)
}
pub fn build_dec_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>,
) -> FunctionValue<'ctx> {
build_rc_wrapper(env, layout_ids, layout, Mode::Dec)
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Dec)
}
fn build_rc_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>,
rc_operation: Mode,
@ -384,7 +408,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
generic_value_ptr.set_name(Symbol::ARG_1.as_str(&env.interns));
let value_type = basic_type_from_layout(env, layout);
let value_type = basic_type_from_layout(env, layout_interner, layout);
let value_ptr_type = value_type.ptr_type(AddressSpace::Generic);
let value_ptr =
env.builder
@ -393,7 +417,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
// even though this looks like a `load_roc_value`, that gives segfaults in practice.
// I suspect it has something to do with the lifetime of the alloca that is created by
// `load_roc_value`
let value = if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
let value = if layout.is_passed_by_reference(layout_interner, env.target_info) {
value_ptr.into()
} else {
env.builder
@ -403,16 +427,16 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
match rc_operation {
Mode::Inc => {
let n = 1;
increment_refcount_layout(env, layout_ids, n, value, layout);
increment_refcount_layout(env, layout_interner, layout_ids, n, value, layout);
}
Mode::IncN => {
let n = it.next().unwrap().into_int_value();
n.set_name(Symbol::ARG_2.as_str(&env.interns));
increment_n_refcount_layout(env, layout_ids, n, value, layout);
increment_n_refcount_layout(env, layout_interner, layout_ids, n, value, layout);
}
Mode::Dec => {
decrement_refcount_layout(env, layout_ids, value, layout);
decrement_refcount_layout(env, layout_interner, layout_ids, value, layout);
}
}
@ -431,6 +455,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
pub fn build_eq_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>,
) -> FunctionValue<'ctx> {
@ -474,7 +499,8 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
value_ptr1.set_name(Symbol::ARG_1.as_str(&env.interns));
value_ptr2.set_name(Symbol::ARG_2.as_str(&env.interns));
let value_type = basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
let value_type = basic_type_from_layout(env, layout_interner, layout)
.ptr_type(AddressSpace::Generic);
let value_cast1 = env
.builder
@ -485,11 +511,18 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
.build_pointer_cast(value_ptr2, value_type, "load_opaque");
// load_roc_value(env, *element_layout, elem_ptr, "get_elem")
let value1 = load_roc_value(env, *layout, value_cast1, "load_opaque");
let value2 = load_roc_value(env, *layout, value_cast2, "load_opaque");
let value1 = load_roc_value(env, layout_interner, *layout, value_cast1, "load_opaque");
let value2 = load_roc_value(env, layout_interner, *layout, value_cast2, "load_opaque");
let result =
crate::llvm::compare::generic_eq(env, layout_ids, value1, value2, layout, layout);
let result = crate::llvm::compare::generic_eq(
env,
layout_interner,
layout_ids,
value1,
value2,
layout,
layout,
);
env.builder.build_return(Some(&result));
@ -506,6 +539,7 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
pub fn build_compare_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>,
layout: &Layout<'a>,
@ -555,7 +589,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
value_ptr1.set_name(Symbol::ARG_2.as_str(&env.interns));
value_ptr2.set_name(Symbol::ARG_3.as_str(&env.interns));
let value_type = basic_type_from_layout(env, layout);
let value_type = basic_type_from_layout(env, layout_interner, layout);
let value_ptr_type = value_type.ptr_type(AddressSpace::Generic);
let value_cast1 =
@ -575,33 +609,32 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
let default = [value1.into(), value2.into()];
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);
let closure_ptr_type = closure_type.ptr_type(AddressSpace::Generic);
let arguments_cast = match closure_data_layout.runtime_representation(layout_interner) {
Layout::Struct {
field_layouts: &[], ..
} => {
// nothing to add
&default
}
other => {
let closure_type = basic_type_from_layout(env, layout_interner, &other);
let closure_ptr_type = closure_type.ptr_type(AddressSpace::Generic);
let closure_cast = env.builder.build_pointer_cast(
closure_ptr,
closure_ptr_type,
"load_opaque",
);
let closure_cast = env.builder.build_pointer_cast(
closure_ptr,
closure_ptr_type,
"load_opaque",
);
let closure_data =
env.builder
.new_build_load(closure_type, closure_cast, "load_opaque");
let closure_data =
env.builder
.new_build_load(closure_type, 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,

File diff suppressed because it is too large Load diff

View file

@ -13,7 +13,7 @@ use morphic_lib::UpdateMode;
use roc_builtins::bitcode;
use roc_intern::Interner;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds};
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner};
use super::bitcode::{call_list_bitcode_fn, BitcodeReturns};
use super::build::{
@ -63,14 +63,15 @@ pub(crate) fn pass_update_mode<'a, 'ctx, 'env>(
fn pass_element_as_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
element: BasicValueEnum<'ctx>,
layout: Layout<'a>,
) -> BasicValueEnum<'ctx> {
let element_type = basic_type_from_layout(env, &layout);
let element_type = basic_type_from_layout(env, layout_interner, &layout);
let element_ptr = env
.builder
.build_alloca(element_type, "element_to_pass_as_opaque");
store_roc_value(env, layout, element_ptr, element);
store_roc_value(env, layout_interner, layout, element_ptr, element);
env.builder
.build_pointer_cast(
@ -83,11 +84,12 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
pub(crate) fn layout_width<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
env.ptr_int()
.const_int(
layout.stack_size(env.layout_interner, env.target_info) as u64,
layout.stack_size(layout_interner, env.target_info) as u64,
false,
)
.into()
@ -108,17 +110,18 @@ pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>(
pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
capacity: IntValue<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout);
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn(
env,
&[],
&[
capacity.into(),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
],
BitcodeReturns::List,
bitcode::LIST_WITH_CAPACITY,
@ -127,6 +130,7 @@ pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
element_layout: InLayout<'a>,
elem_index: IntValue<'ctx>,
@ -134,8 +138,8 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> {
let builder = env.builder;
let element_layout = env.layout_interner.get(element_layout);
let elem_type = basic_type_from_layout(env, element_layout);
let element_layout = layout_interner.get(element_layout);
let elem_type = basic_type_from_layout(env, layout_interner, element_layout);
let ptr_type = elem_type.ptr_type(AddressSpace::Generic);
// Load the pointer to the array data
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type);
@ -151,9 +155,15 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
)
};
let result = load_roc_value(env, *element_layout, elem_ptr, "list_get_load_element");
let result = load_roc_value(
env,
layout_interner,
*element_layout,
elem_ptr,
"list_get_load_element",
);
increment_refcount_layout(env, layout_ids, 1, result, element_layout);
increment_refcount_layout(env, layout_interner, layout_ids, 1, result, element_layout);
result
}
@ -161,19 +171,20 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
/// List.reserve : List elem, Nat -> List elem
pub(crate) fn list_reserve<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
list: BasicValueEnum<'ctx>,
spare: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout);
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn_1(
env,
list.into_struct_value(),
&[
env.alignment_intvalue(element_layout),
env.alignment_intvalue(layout_interner, element_layout),
spare,
layout_width(env, element_layout),
layout_width(env, layout_interner, element_layout),
pass_update_mode(env, update_mode),
],
bitcode::LIST_RESERVE,
@ -183,6 +194,7 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
/// List.appendUnsafe : List elem, elem -> List elem
pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
@ -191,8 +203,8 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
env,
original_wrapper,
&[
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, layout_interner, element_layout),
],
bitcode::LIST_APPEND_UNSAFE,
)
@ -201,6 +213,7 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
/// List.prepend : List elem, elem -> List elem
pub(crate) fn list_prepend<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
@ -209,9 +222,9 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
env,
original_wrapper,
&[
env.alignment_intvalue(element_layout),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, layout_interner, element_layout),
],
bitcode::LIST_PREPEND,
)
@ -220,19 +233,20 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
/// List.swap : List elem, Nat, Nat -> List elem
pub(crate) fn list_swap<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
index_1: IntValue<'ctx>,
index_2: IntValue<'ctx>,
element_layout: InLayout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout);
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
index_1.into(),
index_2.into(),
pass_update_mode(env, update_mode),
@ -244,20 +258,21 @@ pub(crate) fn list_swap<'a, 'ctx, 'env>(
/// List.sublist : List elem, { start : Nat, len : Nat } -> List elem
pub(crate) fn list_sublist<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
start: IntValue<'ctx>,
len: IntValue<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
let element_layout = layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
start.into(),
len.into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
@ -269,19 +284,20 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>(
/// List.dropAt : List elem, Nat -> List elem
pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
let element_layout = layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
count.into(),
dec_element_fn.as_global_value().as_pointer_value().into(),
],
@ -292,6 +308,7 @@ pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
/// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem }
pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
_layout_ids: &mut LayoutIds<'a>,
list: BasicValueEnum<'ctx>,
index: IntValue<'ctx>,
@ -299,7 +316,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
element_layout: &Layout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_type = basic_type_from_layout(env, element_layout);
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
let element_ptr = env
.builder
.build_alloca(element_type, "output_element_as_opaque");
@ -312,8 +329,8 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
list.into_struct_value(),
&[
index.into(),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, layout_interner, element_layout),
pass_as_opaque(env, element_ptr),
],
bitcode::LIST_REPLACE_IN_PLACE,
@ -322,10 +339,10 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
env,
list.into_struct_value(),
&[
env.alignment_intvalue(element_layout),
env.alignment_intvalue(layout_interner, element_layout),
index.into(),
pass_element_as_opaque(env, element, *element_layout),
layout_width(env, element_layout),
pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, layout_interner, element_layout),
pass_as_opaque(env, element_ptr),
],
bitcode::LIST_REPLACE,
@ -339,7 +356,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.layout_interner, env.target_info);
let element_align = element_layout.alignment_bytes(layout_interner, env.target_info);
let element_first = element_align > env.target_info.ptr_width() as u32;
let fields = if element_first {
@ -424,6 +441,7 @@ pub(crate) fn destructure<'ctx>(
/// List.sortWith : List a, (a, a -> Ordering) -> List a
pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>,
compare_wrapper: PointerValue<'ctx>,
list: BasicValueEnum<'ctx>,
@ -437,8 +455,8 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(),
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
],
bitcode::LIST_SORT_WITH,
)
@ -447,6 +465,7 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
/// List.map : List before, (before -> after) -> List after
pub(crate) fn list_map<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
@ -460,9 +479,9 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(),
env.alignment_intvalue(return_layout),
layout_width(env, element_layout),
layout_width(env, return_layout),
env.alignment_intvalue(layout_interner, return_layout),
layout_width(env, layout_interner, element_layout),
layout_width(env, layout_interner, return_layout),
],
bitcode::LIST_MAP,
)
@ -470,6 +489,7 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
pub(crate) fn list_map2<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>,
@ -478,8 +498,8 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
element2_layout: &Layout<'a>,
return_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout);
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
call_list_bitcode_fn(
env,
@ -489,10 +509,10 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(),
env.alignment_intvalue(return_layout),
layout_width(env, element1_layout),
layout_width(env, element2_layout),
layout_width(env, return_layout),
env.alignment_intvalue(layout_interner, return_layout),
layout_width(env, layout_interner, element1_layout),
layout_width(env, layout_interner, element2_layout),
layout_width(env, layout_interner, return_layout),
dec_a.as_global_value().as_pointer_value().into(),
dec_b.as_global_value().as_pointer_value().into(),
],
@ -503,6 +523,7 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
pub(crate) fn list_map3<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>,
@ -513,9 +534,9 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
element3_layout: &Layout<'a>,
result_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout);
let dec_c = build_dec_wrapper(env, layout_ids, element3_layout);
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
let dec_c = build_dec_wrapper(env, layout_interner, layout_ids, element3_layout);
call_list_bitcode_fn(
env,
@ -529,11 +550,11 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(),
env.alignment_intvalue(result_layout),
layout_width(env, element1_layout),
layout_width(env, element2_layout),
layout_width(env, element3_layout),
layout_width(env, result_layout),
env.alignment_intvalue(layout_interner, result_layout),
layout_width(env, layout_interner, element1_layout),
layout_width(env, layout_interner, element2_layout),
layout_width(env, layout_interner, element3_layout),
layout_width(env, layout_interner, result_layout),
dec_a.as_global_value().as_pointer_value().into(),
dec_b.as_global_value().as_pointer_value().into(),
dec_c.as_global_value().as_pointer_value().into(),
@ -545,6 +566,7 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
pub(crate) fn list_map4<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>,
@ -557,10 +579,10 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
element4_layout: &Layout<'a>,
result_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> {
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout);
let dec_c = build_dec_wrapper(env, layout_ids, element3_layout);
let dec_d = build_dec_wrapper(env, layout_ids, element4_layout);
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
let dec_c = build_dec_wrapper(env, layout_interner, layout_ids, element3_layout);
let dec_d = build_dec_wrapper(env, layout_interner, layout_ids, element4_layout);
call_list_bitcode_fn(
env,
@ -575,12 +597,12 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(),
env.alignment_intvalue(result_layout),
layout_width(env, element1_layout),
layout_width(env, element2_layout),
layout_width(env, element3_layout),
layout_width(env, element4_layout),
layout_width(env, result_layout),
env.alignment_intvalue(layout_interner, result_layout),
layout_width(env, layout_interner, element1_layout),
layout_width(env, layout_interner, element2_layout),
layout_width(env, layout_interner, element3_layout),
layout_width(env, layout_interner, element4_layout),
layout_width(env, layout_interner, result_layout),
dec_a.as_global_value().as_pointer_value().into(),
dec_b.as_global_value().as_pointer_value().into(),
dec_c.as_global_value().as_pointer_value().into(),
@ -594,25 +616,27 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
/// List.concat : List elem, List elem -> List elem
pub(crate) fn list_concat<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
list1: BasicValueEnum<'ctx>,
list2: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout);
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn(
env,
&[list1.into_struct_value(), list2.into_struct_value()],
&[
env.alignment_intvalue(element_layout),
layout_width(env, element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
],
BitcodeReturns::List,
bitcode::LIST_CONCAT,
)
}
pub(crate) fn incrementing_elem_loop<'a, 'ctx, 'env, LoopFn>(
pub(crate) fn incrementing_elem_loop<'a, 'r, 'ctx, 'env, LoopFn>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &'r mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
element_layout: Layout<'a>,
ptr: PointerValue<'ctx>,
@ -621,39 +645,49 @@ pub(crate) fn incrementing_elem_loop<'a, 'ctx, 'env, LoopFn>(
mut loop_fn: LoopFn,
) -> PointerValue<'ctx>
where
LoopFn: FnMut(IntValue<'ctx>, BasicValueEnum<'ctx>),
LoopFn: FnMut(&'r mut STLayoutInterner<'a>, IntValue<'ctx>, BasicValueEnum<'ctx>),
{
let builder = env.builder;
let element_type = basic_type_from_layout(env, &element_layout);
let element_type = basic_type_from_layout(env, layout_interner, &element_layout);
incrementing_index_loop(env, parent, len, index_name, |index| {
// The pointer to the element in the list
let element_ptr =
unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index], "load_index") };
incrementing_index_loop(
env,
layout_interner,
parent,
len,
index_name,
|layout_interner, index| {
// The pointer to the element in the list
let element_ptr = unsafe {
builder.new_build_in_bounds_gep(element_type, ptr, &[index], "load_index")
};
let elem = load_roc_value(
env,
element_layout,
element_ptr,
"incrementing_element_loop_load",
);
let elem = load_roc_value(
env,
layout_interner,
element_layout,
element_ptr,
"incrementing_element_loop_load",
);
loop_fn(index, elem);
})
loop_fn(layout_interner, index, elem);
},
)
}
// This helper simulates a basic for loop, where
// and index increments up from 0 to some end value
pub(crate) fn incrementing_index_loop<'a, 'ctx, 'env, LoopFn>(
pub(crate) fn incrementing_index_loop<'a, 'r, 'ctx, 'env, LoopFn>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &'r mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
end: IntValue<'ctx>,
index_name: &str,
mut loop_fn: LoopFn,
) -> PointerValue<'ctx>
where
LoopFn: FnMut(IntValue<'ctx>),
LoopFn: FnMut(&'r mut STLayoutInterner<'a>, IntValue<'ctx>),
{
let ctx = env.context;
let builder = env.builder;
@ -682,7 +716,7 @@ where
builder.build_store(index_alloca, next_index);
// The body of the loop
loop_fn(current_index);
loop_fn(layout_interner, current_index);
// #index < end
let loop_end_cond = bounds_check_comparison(builder, next_index, end);
@ -737,19 +771,20 @@ pub(crate) fn load_list_ptr<'ctx>(
pub(crate) fn allocate_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
elem_layout: &Layout<'a>,
number_of_elements: IntValue<'ctx>,
) -> PointerValue<'ctx> {
let builder = env.builder;
let len_type = env.ptr_int();
let elem_bytes = elem_layout.stack_size(env.layout_interner, env.target_info) as u64;
let elem_bytes = elem_layout.stack_size(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.layout_interner, env.target_info);
let basic_type = basic_type_from_layout(env, layout_interner, elem_layout);
let alignment_bytes = elem_layout.alignment_bytes(layout_interner, env.target_info);
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
}

View file

@ -14,7 +14,7 @@ use roc_builtins::bitcode;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_intern::Interner;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, UnionLayout};
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner, UnionLayout};
use super::build::{load_roc_value, use_roc_value, BuilderExt};
use super::convert::argument_type_from_union_layout;
@ -22,6 +22,7 @@ use super::lowlevel::dec_binop_with_unchecked;
pub fn generic_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
@ -30,6 +31,7 @@ pub fn generic_eq<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> {
build_eq(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
@ -41,6 +43,7 @@ pub fn generic_eq<'a, 'ctx, 'env>(
pub fn generic_neq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
@ -49,6 +52,7 @@ pub fn generic_neq<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> {
build_neq(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
@ -60,6 +64,7 @@ pub fn generic_neq<'a, 'ctx, 'env>(
fn build_eq_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
@ -125,6 +130,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
Builtin::Str => str_equal(env, lhs_val, rhs_val),
Builtin::List(elem) => build_list_eq(
env,
layout_interner,
layout_ids,
&Layout::Builtin(*builtin),
*elem,
@ -137,6 +143,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
fn build_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
@ -144,8 +151,8 @@ fn build_eq<'a, 'ctx, 'env>(
rhs_layout: &Layout<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
let lhs_layout = &lhs_layout.runtime_representation(env.layout_interner);
let rhs_layout = &rhs_layout.runtime_representation(env.layout_interner);
let lhs_layout = &lhs_layout.runtime_representation(layout_interner);
let rhs_layout = &rhs_layout.runtime_representation(layout_interner);
if lhs_layout != rhs_layout {
panic!(
"Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}",
@ -154,12 +161,19 @@ fn build_eq<'a, 'ctx, 'env>(
}
match lhs_layout {
Layout::Builtin(builtin) => {
build_eq_builtin(env, layout_ids, lhs_val, rhs_val, builtin, when_recursive)
}
Layout::Builtin(builtin) => build_eq_builtin(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
builtin,
when_recursive,
),
Layout::Struct { field_layouts, .. } => build_struct_eq(
env,
layout_interner,
layout_ids,
field_layouts,
when_recursive,
@ -171,6 +185,7 @@ fn build_eq<'a, 'ctx, 'env>(
Layout::Union(union_layout) => build_tag_eq(
env,
layout_interner,
layout_ids,
when_recursive,
union_layout,
@ -180,6 +195,7 @@ fn build_eq<'a, 'ctx, 'env>(
Layout::Boxed(inner_layout) => build_box_eq(
env,
layout_interner,
layout_ids,
when_recursive,
lhs_layout,
@ -196,7 +212,7 @@ fn build_eq<'a, 'ctx, 'env>(
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(union_layout);
let bt = basic_type_from_layout(env, &layout);
let bt = basic_type_from_layout(env, layout_interner, &layout);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
@ -213,6 +229,7 @@ fn build_eq<'a, 'ctx, 'env>(
build_tag_eq(
env,
layout_interner,
layout_ids,
WhenRecursive::Loop(union_layout),
&union_layout,
@ -226,6 +243,7 @@ fn build_eq<'a, 'ctx, 'env>(
fn build_neq_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
@ -297,6 +315,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
Builtin::List(elem) => {
let is_equal = build_list_eq(
env,
layout_interner,
layout_ids,
&Layout::Builtin(*builtin),
*elem,
@ -315,6 +334,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
fn build_neq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
@ -330,13 +350,20 @@ fn build_neq<'a, 'ctx, 'env>(
}
match lhs_layout {
Layout::Builtin(builtin) => {
build_neq_builtin(env, layout_ids, lhs_val, rhs_val, builtin, when_recursive)
}
Layout::Builtin(builtin) => build_neq_builtin(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
builtin,
when_recursive,
),
Layout::Struct { field_layouts, .. } => {
let is_equal = build_struct_eq(
env,
layout_interner,
layout_ids,
field_layouts,
when_recursive,
@ -353,6 +380,7 @@ fn build_neq<'a, 'ctx, 'env>(
Layout::Union(union_layout) => {
let is_equal = build_tag_eq(
env,
layout_interner,
layout_ids,
when_recursive,
union_layout,
@ -369,6 +397,7 @@ fn build_neq<'a, 'ctx, 'env>(
Layout::Boxed(inner_layout) => {
let is_equal = build_box_eq(
env,
layout_interner,
layout_ids,
when_recursive,
lhs_layout,
@ -392,6 +421,7 @@ fn build_neq<'a, 'ctx, 'env>(
fn build_list_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
list_layout: &Layout<'a>,
element_layout: InLayout<'a>,
@ -403,7 +433,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
let di_location = env.builder.get_current_debug_location().unwrap();
let symbol = Symbol::LIST_EQ;
let element_layout = env.layout_interner.get(element_layout);
let element_layout = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
let fn_name = layout_ids
.get(symbol, &element_layout)
@ -412,7 +442,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let arg_type = basic_type_from_layout(env, list_layout);
let arg_type = basic_type_from_layout(env, layout_interner, list_layout);
let function_value = crate::llvm::refcounting::build_header_help(
env,
@ -423,6 +453,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
build_list_eq_help(
env,
layout_interner,
layout_ids,
when_recursive,
function_value,
@ -447,6 +478,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
fn build_list_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
@ -509,7 +541,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(then_block);
let builder = env.builder;
let element_type = basic_type_from_layout(env, element_layout);
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
let ptr_type = element_type.ptr_type(AddressSpace::Generic);
let ptr1 = load_list_ptr(env.builder, list1, ptr_type);
let ptr2 = load_list_ptr(env.builder, list2, ptr_type);
@ -549,18 +581,19 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
let elem_ptr = unsafe {
builder.new_build_in_bounds_gep(element_type, ptr1, &[curr_index], "load_index")
};
load_roc_value(env, *element_layout, elem_ptr, "get_elem")
load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem")
};
let elem2 = {
let elem_ptr = unsafe {
builder.new_build_in_bounds_gep(element_type, ptr2, &[curr_index], "load_index")
};
load_roc_value(env, *element_layout, elem_ptr, "get_elem")
load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem")
};
let are_equal = build_eq(
env,
layout_interner,
layout_ids,
elem1,
elem2,
@ -605,6 +638,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
fn build_struct_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
field_layouts: &'a [Layout<'a>],
when_recursive: WhenRecursive<'a>,
@ -624,7 +658,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let arg_type = basic_type_from_layout(env, &struct_layout);
let arg_type = basic_type_from_layout(env, layout_interner, &struct_layout);
let function_value = crate::llvm::refcounting::build_header_help(
env,
@ -635,6 +669,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
build_struct_eq_help(
env,
layout_interner,
layout_ids,
function_value,
when_recursive,
@ -659,6 +694,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
fn build_struct_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
when_recursive: WhenRecursive<'a>,
@ -727,7 +763,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
WhenRecursive::Loop(union_layout) => {
let field_layout = Layout::Union(*union_layout);
let bt = basic_type_from_layout(env, &field_layout);
let bt = basic_type_from_layout(env, layout_interner, &field_layout);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
@ -744,6 +780,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
build_eq(
env,
layout_interner,
layout_ids,
field1_cast.into(),
field2_cast.into(),
@ -755,11 +792,14 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
}
}
} else {
let lhs = use_roc_value(env, layout_interner, *field_layout, field1, "field1");
let rhs = use_roc_value(env, layout_interner, *field_layout, field2, "field2");
build_eq(
env,
layout_interner,
layout_ids,
use_roc_value(env, *field_layout, field1, "field1"),
use_roc_value(env, *field_layout, field2, "field2"),
lhs,
rhs,
field_layout,
field_layout,
when_recursive,
@ -791,6 +831,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
fn build_tag_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
union_layout: &UnionLayout<'a>,
@ -809,7 +850,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let arg_type = argument_type_from_union_layout(env, union_layout);
let arg_type = argument_type_from_union_layout(env, layout_interner, union_layout);
let function_value = crate::llvm::refcounting::build_header_help(
env,
@ -820,6 +861,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
build_tag_eq_help(
env,
layout_interner,
layout_ids,
when_recursive,
function_value,
@ -844,6 +886,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
fn build_tag_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
@ -924,8 +967,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(compare_tag_ids);
let id1 = get_tag_id(env, parent, union_layout, tag1);
let id2 = get_tag_id(env, parent, union_layout, tag2);
let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
let id2 = get_tag_id(env, layout_interner, parent, union_layout, tag2);
// clear the tag_id so we get a pointer to the actual data
let tag1 = tag1.into_pointer_value();
@ -952,6 +995,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct(
env,
layout_interner,
layout_ids,
union_layout,
Some(when_recursive),
@ -994,8 +1038,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(compare_tag_ids);
let id1 = get_tag_id(env, parent, union_layout, tag1);
let id2 = get_tag_id(env, parent, union_layout, tag2);
let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
let id2 = get_tag_id(env, layout_interner, parent, union_layout, tag2);
// clear the tag_id so we get a pointer to the actual data
let tag1 = tag_pointer_clear_tag_id(env, tag1.into_pointer_value());
@ -1022,6 +1066,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct(
env,
layout_interner,
layout_ids,
union_layout,
None,
@ -1082,6 +1127,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct(
env,
layout_interner,
layout_ids,
union_layout,
None,
@ -1150,8 +1196,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(compare_other);
let id1 = get_tag_id(env, parent, union_layout, tag1);
let id2 = get_tag_id(env, parent, union_layout, tag2);
let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
let id2 = get_tag_id(env, layout_interner, parent, union_layout, tag2);
// clear the tag_id so we get a pointer to the actual data
let tag1 = tag_pointer_clear_tag_id(env, tag1.into_pointer_value());
@ -1179,6 +1225,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct(
env,
layout_interner,
layout_ids,
union_layout,
None,
@ -1217,6 +1264,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct(
env,
layout_interner,
layout_ids,
union_layout,
None,
@ -1232,6 +1280,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
fn eq_ptr_to_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: &UnionLayout<'a>,
opt_when_recursive: Option<WhenRecursive<'a>>,
@ -1241,7 +1290,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
) -> IntValue<'ctx> {
let struct_layout = Layout::struct_no_name_order(field_layouts);
let wrapper_type = basic_type_from_layout(env, &struct_layout);
let wrapper_type = basic_type_from_layout(env, layout_interner, &struct_layout);
debug_assert!(wrapper_type.is_struct_type());
// cast the opaque pointer to a pointer of the correct shape
@ -1269,6 +1318,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
build_struct_eq(
env,
layout_interner,
layout_ids,
field_layouts,
opt_when_recursive.unwrap_or(WhenRecursive::Loop(*union_layout)),
@ -1282,6 +1332,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
fn build_box_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
box_layout: &Layout<'a>,
@ -1300,7 +1351,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let arg_type = basic_type_from_layout(env, box_layout);
let arg_type = basic_type_from_layout(env, layout_interner, box_layout);
let function_value = crate::llvm::refcounting::build_header_help(
env,
@ -1311,6 +1362,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
build_box_eq_help(
env,
layout_interner,
layout_ids,
when_recursive,
function_value,
@ -1335,6 +1387,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
fn build_box_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
@ -1402,13 +1455,14 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
let box1 = box1.into_pointer_value();
let box2 = box2.into_pointer_value();
let inner_layout = env.layout_interner.get(inner_layout);
let inner_layout = layout_interner.get(inner_layout);
let value1 = load_roc_value(env, *inner_layout, box1, "load_box1");
let value2 = load_roc_value(env, *inner_layout, box2, "load_box2");
let value1 = load_roc_value(env, layout_interner, *inner_layout, box1, "load_box1");
let value2 = load_roc_value(env, layout_interner, *inner_layout, box2, "load_box2");
let is_equal = build_eq(
env,
layout_interner,
layout_ids,
value1,
value2,

View file

@ -11,12 +11,13 @@ use roc_target::TargetInfo;
fn basic_type_from_record<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
fields: &[Layout<'_>],
) -> BasicTypeEnum<'ctx> {
let mut field_types = Vec::with_capacity_in(fields.len(), env.arena);
for field_layout in fields.iter() {
field_types.push(basic_type_from_layout(env, field_layout));
field_types.push(basic_type_from_layout(env, layout_interner, field_layout));
}
env.context
@ -26,6 +27,7 @@ fn basic_type_from_record<'a, 'ctx, 'env>(
pub fn basic_type_from_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &'env mut STLayoutInterner<'a>,
layout: &Layout<'_>,
) -> BasicTypeEnum<'ctx> {
use Layout::*;
@ -34,17 +36,19 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
Struct {
field_layouts: sorted_fields,
..
} => basic_type_from_record(env, sorted_fields),
LambdaSet(lambda_set) => {
basic_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner))
}
} => basic_type_from_record(env, layout_interner, sorted_fields),
LambdaSet(lambda_set) => basic_type_from_layout(
env,
layout_interner,
&lambda_set.runtime_representation(layout_interner),
),
Boxed(inner_layout) => {
let inner_layout = env.layout_interner.get(*inner_layout);
let inner_type = basic_type_from_layout(env, inner_layout);
let inner_layout = layout_interner.get(*inner_layout);
let inner_type = basic_type_from_layout(env, layout_interner, inner_layout);
inner_type.ptr_type(AddressSpace::Generic).into()
}
Union(union_layout) => basic_type_from_union_layout(env, union_layout),
Union(union_layout) => basic_type_from_union_layout(env, layout_interner, union_layout),
RecursivePointer => env
.context
.i64_type()
@ -57,13 +61,14 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
pub fn struct_type_from_union_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>,
) -> StructType<'ctx> {
use UnionLayout::*;
match union_layout {
NonRecursive(tags) => {
RocUnion::tagged_from_slices(env.layout_interner, env.context, tags, env.target_info)
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
.struct_type()
}
Recursive(tags)
@ -71,47 +76,35 @@ pub fn struct_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.layout_interner,
env.context,
tags,
env.target_info,
)
.struct_type()
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
.struct_type()
} else {
RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
tags,
env.target_info,
)
.struct_type()
RocUnion::untagged_from_slices(layout_interner, env.context, tags, env.target_info)
.struct_type()
}
}
NullableUnwrapped { other_fields, .. } => RocUnion::untagged_from_slices(
env.layout_interner,
layout_interner,
env.context,
&[other_fields],
env.target_info,
)
.struct_type(),
NonNullableUnwrapped(fields) => RocUnion::untagged_from_slices(
env.layout_interner,
env.context,
&[fields],
env.target_info,
)
.struct_type(),
NonNullableUnwrapped(fields) => {
RocUnion::untagged_from_slices(layout_interner, env.context, &[fields], env.target_info)
.struct_type()
}
}
}
pub fn basic_type_from_union_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>,
) -> BasicTypeEnum<'ctx> {
use UnionLayout::*;
let struct_type = struct_type_from_union_layout(env, union_layout);
let struct_type = struct_type_from_union_layout(env, layout_interner, union_layout);
match union_layout {
NonRecursive(_) => struct_type.into(),
@ -153,34 +146,38 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
/// is not currently implemented
pub fn argument_type_from_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'_>,
) -> BasicTypeEnum<'ctx> {
use Layout::*;
match layout {
LambdaSet(lambda_set) => {
argument_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner))
}
Union(union_layout) => argument_type_from_union_layout(env, union_layout),
LambdaSet(lambda_set) => argument_type_from_layout(
env,
layout_interner,
&lambda_set.runtime_representation(layout_interner),
),
Union(union_layout) => argument_type_from_union_layout(env, layout_interner, union_layout),
Builtin(_) => {
let base = basic_type_from_layout(env, layout);
let base = basic_type_from_layout(env, layout_interner, layout);
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
if layout.is_passed_by_reference(layout_interner, env.target_info) {
base.ptr_type(AddressSpace::Generic).into()
} else {
base
}
}
other => basic_type_from_layout(env, other),
other => basic_type_from_layout(env, layout_interner, other),
}
}
/// Non-recursive tag unions are stored on the stack, but passed by-reference
pub fn argument_type_from_union_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: &UnionLayout<'_>,
) -> BasicTypeEnum<'ctx> {
let heap_type = basic_type_from_union_layout(env, union_layout);
let heap_type = basic_type_from_union_layout(env, layout_interner, union_layout);
if let UnionLayout::NonRecursive(_) = union_layout {
heap_type.ptr_type(AddressSpace::Generic).into()

View file

@ -12,7 +12,7 @@ use roc_builtins::bitcode;
use roc_intern::Interner;
use roc_module::symbol::Symbol;
use roc_mono::ir::LookupType;
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
use roc_mono::layout::{Builtin, Layout, LayoutIds, STLayoutInterner, UnionLayout};
use roc_region::all::Region;
use super::build::BuilderExt;
@ -167,6 +167,7 @@ pub(crate) fn notify_parent_dbg(env: &Env, shared_memory: &SharedMemoryPointer)
#[allow(clippy::too_many_arguments)]
pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
scope: &Scope<'a, 'ctx>,
layout_ids: &mut LayoutIds<'a>,
shared_memory: &SharedMemoryPointer<'ctx>,
@ -201,7 +202,7 @@ 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.layout_interner, env.target_info) as u64,
layout.stack_size(layout_interner, env.target_info) as u64,
false,
);
@ -214,6 +215,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
extra_offset = build_clone(
env,
layout_interner,
layout_ids,
original_ptr,
cursors,
@ -280,6 +282,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_clone<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>,
cursors: Cursors<'ctx>,
@ -290,6 +293,7 @@ fn build_clone<'a, 'ctx, 'env>(
match layout {
Layout::Builtin(builtin) => build_clone_builtin(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -300,6 +304,7 @@ fn build_clone<'a, 'ctx, 'env>(
Layout::Struct { field_layouts, .. } => build_clone_struct(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -313,7 +318,7 @@ fn build_clone<'a, 'ctx, 'env>(
Layout::LambdaSet(_) => cursors.extra_offset,
Layout::Union(union_layout) => {
if layout.safe_to_memcpy(env.layout_interner) {
if layout.safe_to_memcpy(layout_interner) {
let ptr = unsafe {
env.builder.new_build_in_bounds_gep(
env.context.i8_type(),
@ -328,12 +333,13 @@ fn build_clone<'a, 'ctx, 'env>(
.builder
.build_pointer_cast(ptr, ptr_type, "cast_ptr_type");
store_roc_value(env, layout, ptr, value);
store_roc_value(env, layout_interner, layout, ptr, value);
cursors.extra_offset
} else {
build_clone_tag(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -349,11 +355,11 @@ fn build_clone<'a, 'ctx, 'env>(
build_copy(env, ptr, cursors.offset, cursors.extra_offset.into());
let source = value.into_pointer_value();
let inner_layout = env.layout_interner.get(inner_layout);
let value = load_roc_value(env, *inner_layout, source, "inner");
let inner_layout = layout_interner.get(inner_layout);
let value = load_roc_value(env, layout_interner, *inner_layout, source, "inner");
let inner_width = env.ptr_int().const_int(
inner_layout.stack_size(env.layout_interner, env.target_info) as u64,
inner_layout.stack_size(layout_interner, env.target_info) as u64,
false,
);
@ -368,6 +374,7 @@ fn build_clone<'a, 'ctx, 'env>(
build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -385,7 +392,7 @@ fn build_clone<'a, 'ctx, 'env>(
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(union_layout);
let bt = basic_type_from_layout(env, &layout);
let bt = basic_type_from_layout(env, layout_interner, &layout);
// cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast(
@ -396,6 +403,7 @@ fn build_clone<'a, 'ctx, 'env>(
build_clone_tag(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -411,6 +419,7 @@ fn build_clone<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_clone_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>,
cursors: Cursors<'ctx>,
@ -420,7 +429,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
) -> IntValue<'ctx> {
let layout = Layout::struct_no_name_order(field_layouts);
if layout.safe_to_memcpy(env.layout_interner) {
if layout.safe_to_memcpy(layout_interner) {
build_copy(env, ptr, cursors.offset, value)
} else {
let mut cursors = cursors;
@ -433,10 +442,11 @@ fn build_clone_struct<'a, 'ctx, 'env>(
.build_extract_value(structure, i as _, "extract")
.unwrap();
let field = use_roc_value(env, *field_layout, field, "field");
let field = use_roc_value(env, layout_interner, *field_layout, field, "field");
let new_extra = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -446,7 +456,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
);
let field_width = env.ptr_int().const_int(
field_layout.stack_size(env.layout_interner, env.target_info) as u64,
field_layout.stack_size(layout_interner, env.target_info) as u64,
false,
);
@ -463,6 +473,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_clone_tag<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>,
cursors: Cursors<'ctx>,
@ -505,6 +516,7 @@ fn build_clone_tag<'a, 'ctx, 'env>(
build_clone_tag_help(
env,
layout_interner,
layout_ids,
union_layout,
when_recursive,
@ -539,11 +551,12 @@ fn build_clone_tag<'a, 'ctx, 'env>(
fn load_tag_data<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
union_layout: UnionLayout<'a>,
tag_value: PointerValue<'ctx>,
tag_type: BasicTypeEnum<'ctx>,
) -> BasicValueEnum<'ctx> {
let union_struct_type = struct_type_from_union_layout(env, &union_layout);
let union_struct_type = struct_type_from_union_layout(env, layout_interner, &union_layout);
let raw_data_ptr = env
.builder
@ -567,6 +580,7 @@ fn load_tag_data<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_clone_tag_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>,
when_recursive: WhenRecursive<'a>,
@ -612,7 +626,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
env.builder.build_unreachable();
}
NonRecursive(tags) => {
let id = get_tag_id(env, parent, &union_layout, tag_value);
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
let switch_block = env.context.append_basic_block(parent, "switch_block");
env.builder.build_unconditional_branch(switch_block);
@ -628,16 +642,25 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
env.arena.alloc([layout, union_layout.tag_id_layout()]),
);
let basic_type = basic_type_from_layout(env, &layout);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let data = load_tag_data(
env,
layout_interner,
union_layout,
tag_value.into_pointer_value(),
basic_type,
);
let answer =
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
env.builder.build_return(Some(&answer));
@ -657,7 +680,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
}
}
Recursive(tags) => {
let id = get_tag_id(env, parent, &union_layout, tag_value);
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
let switch_block = env.context.append_basic_block(parent, "switch_block");
env.builder.build_unconditional_branch(switch_block);
@ -682,11 +705,11 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
)
};
let basic_type = basic_type_from_layout(env, &layout);
let data = load_tag_data(env, union_layout, tag_value, basic_type);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
let (width, _) =
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
union_layout.data_size_and_alignment(layout_interner, env.target_info);
let cursors = Cursors {
offset: extra_offset,
@ -698,8 +721,16 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
};
let when_recursive = WhenRecursive::Loop(union_layout);
let answer =
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
env.builder.build_return(Some(&answer));
@ -724,10 +755,9 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
build_copy(env, ptr, offset, extra_offset.into());
let layout = Layout::struct_no_name_order(fields);
let basic_type = basic_type_from_layout(env, &layout);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let (width, _) =
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
let cursors = Cursors {
offset: extra_offset,
@ -738,10 +768,19 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
),
};
let data = load_tag_data(env, union_layout, tag_value, basic_type);
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
let when_recursive = WhenRecursive::Loop(union_layout);
let answer = build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
env.builder.build_return(Some(&answer));
}
@ -752,7 +791,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let switch_block = env.context.append_basic_block(parent, "switch_block");
let null_block = env.context.append_basic_block(parent, "null_block");
let id = get_tag_id(env, parent, &union_layout, tag_value);
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
let comparison = env
.builder
@ -782,10 +821,10 @@ 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 basic_type = basic_type_from_layout(env, layout_interner, &layout);
let (width, _) =
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
union_layout.data_size_and_alignment(layout_interner, env.target_info);
let cursors = Cursors {
offset: extra_offset,
@ -797,11 +836,20 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
};
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
let data = load_tag_data(env, union_layout, tag_value, basic_type);
let data =
load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
let when_recursive = WhenRecursive::Loop(union_layout);
let answer =
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
env.builder.build_return(Some(&answer));
@ -857,14 +905,14 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
build_copy(env, ptr, offset, extra_offset.into());
let layout = Layout::struct_no_name_order(other_fields);
let basic_type = basic_type_from_layout(env, &layout);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let cursors = Cursors {
offset: extra_offset,
extra_offset: env.builder.build_int_add(
extra_offset,
env.ptr_int().const_int(
layout.stack_size(env.layout_interner, env.target_info) as _,
layout.stack_size(layout_interner, env.target_info) as _,
false,
),
"new_offset",
@ -873,14 +921,23 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let data = load_tag_data(
env,
layout_interner,
union_layout,
tag_value.into_pointer_value(),
basic_type,
);
let when_recursive = WhenRecursive::Loop(union_layout);
let answer =
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
let answer = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
data,
layout,
when_recursive,
);
env.builder.build_return(Some(&answer));
}
@ -945,6 +1002,7 @@ fn build_copy<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_clone_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
ptr: PointerValue<'ctx>,
cursors: Cursors<'ctx>,
@ -990,14 +1048,14 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
offset = build_copy(env, ptr, offset, len.into());
offset = build_copy(env, ptr, offset, len.into());
let elem = env.layout_interner.get(elem);
let elem = layout_interner.get(elem);
let (element_width, _element_align) =
elem.stack_size_and_alignment(env.layout_interner, env.target_info);
elem.stack_size_and_alignment(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(env.layout_interner) {
if elem.safe_to_memcpy(layout_interner) {
// NOTE we are not actually sure the dest is properly aligned
let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, offset);
let src = bd.build_pointer_cast(
@ -1012,7 +1070,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
// We cloned the elements into the extra_offset address.
let elements_start_offset = cursors.extra_offset;
let element_type = basic_type_from_layout(env, elem);
let element_type = basic_type_from_layout(env, layout_interner, elem);
let elements = bd.build_pointer_cast(
elements,
element_type.ptr_type(AddressSpace::Generic),
@ -1023,7 +1081,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset");
let element_stack_size = env.ptr_int().const_int(
elem.stack_size(env.layout_interner, env.target_info) as u64,
elem.stack_size(layout_interner, env.target_info) as u64,
false,
);
let rest_start_offset = bd.build_int_add(
@ -1033,7 +1091,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
);
bd.build_store(rest_offset, rest_start_offset);
let body = |index, element| {
let body = |layout_interner, index, element| {
let current_offset =
bd.build_int_mul(element_stack_size, index, "current_offset");
let current_offset =
@ -1051,6 +1109,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
let new_offset = build_clone(
env,
layout_interner,
layout_ids,
ptr,
cursors,
@ -1068,7 +1127,16 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
.and_then(|b| b.get_parent())
.unwrap();
incrementing_elem_loop(env, parent, *elem, elements, len, "index", body);
incrementing_elem_loop(
env,
layout_interner,
parent,
*elem,
elements,
len,
"index",
body,
);
bd.new_build_load(env.ptr_int(), rest_offset, "rest_start_offset")
.into_int_value()

View file

@ -13,7 +13,7 @@ use roc_intern::Interner;
use roc_module::{low_level::LowLevel, symbol::Symbol};
use roc_mono::{
ir::HigherOrderLowLevel,
layout::{Builtin, LambdaSet, Layout, LayoutIds},
layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner},
};
use roc_target::PtrWidth;
@ -62,6 +62,7 @@ macro_rules! list_element_layout {
#[allow(clippy::too_many_arguments)]
pub(crate) fn run_low_level<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>,
parent: FunctionValue<'ctx>,
@ -256,7 +257,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
);
let roc_return_type =
basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
basic_type_from_layout(env, layout_interner, layout)
.ptr_type(AddressSpace::Generic);
let roc_return_alloca = env.builder.build_pointer_cast(
zig_return_alloca,
@ -264,7 +266,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
"cast_to_roc",
);
load_roc_value(env, *layout, roc_return_alloca, "str_to_num_result")
load_roc_value(
env,
layout_interner,
*layout,
roc_return_alloca,
"str_to_num_result",
)
}
}
}
@ -286,6 +294,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
call_bitcode_fn_fixing_for_convention(
env,
layout_interner,
bitcode_return_type,
&[string],
layout,
@ -298,7 +307,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
};
// zig passes the result as a packed integer sometimes, instead of a struct. So we cast
let expected_type = basic_type_from_layout(env, layout);
let expected_type = basic_type_from_layout(env, layout_interner, layout);
let actual_type = result.get_type();
if expected_type != actual_type {
@ -487,7 +496,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
bitcode::STR_GET_SCALAR_UNSAFE,
);
let return_type = basic_type_from_layout(env, layout);
let return_type = basic_type_from_layout(env, layout_interner, layout);
let cast_result = env.builder.build_pointer_cast(
result,
return_type.ptr_type(AddressSpace::Generic),
@ -510,7 +519,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
match env.target_info.ptr_width() {
PtrWidth::Bytes8 => result,
PtrWidth::Bytes4 => {
let to = basic_type_from_layout(env, layout);
let to = basic_type_from_layout(env, layout_interner, layout);
complex_bitcast_check_size(env, result, to, "to_roc_record")
}
}
@ -645,6 +654,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let result_layout = *layout;
list_with_capacity(
env,
layout_interner,
list_len.into_int_value(),
list_element_layout!(result_layout),
)
@ -658,7 +668,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let element_layout = list_element_layout!(list_layout);
list_concat(env, first_list, second_list, *element_layout)
list_concat(
env,
layout_interner,
first_list,
second_list,
*element_layout,
)
}
ListAppendUnsafe => {
// List.appendUnsafe : List elem, elem -> List elem
@ -667,7 +683,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
list_append_unsafe(env, original_wrapper, elem, elem_layout)
list_append_unsafe(env, layout_interner, original_wrapper, elem, elem_layout)
}
ListPrepend => {
// List.prepend : List elem, elem -> List elem
@ -676,7 +692,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
list_prepend(env, original_wrapper, elem, elem_layout)
list_prepend(env, layout_interner, original_wrapper, elem, elem_layout)
}
ListReserve => {
// List.reserve : List elem, Nat -> List elem
@ -686,7 +702,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let element_layout = list_element_layout!(list_layout);
let spare = load_symbol(scope, &args[1]);
list_reserve(env, list, spare, *element_layout, update_mode)
list_reserve(
env,
layout_interner,
list,
spare,
*element_layout,
update_mode,
)
}
ListSwap => {
// List.swap : List elem, Nat, Nat -> List elem
@ -701,6 +724,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let element_layout = list_element_layout!(list_layout);
list_swap(
env,
layout_interner,
original_wrapper,
index_1.into_int_value(),
index_2.into_int_value(),
@ -720,6 +744,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let element_layout = list_element_layout!(list_layout);
list_sublist(
env,
layout_interner,
layout_ids,
original_wrapper,
start.into_int_value(),
@ -739,6 +764,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let element_layout = list_element_layout!(list_layout);
list_drop_at(
env,
layout_interner,
layout_ids,
original_wrapper,
count.into_int_value(),
@ -763,6 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
list_get_unsafe(
env,
layout_interner,
layout_ids,
*list_element_layout!(list_layout),
element_index.into_int_value(),
@ -774,6 +801,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
list_replace_unsafe(
env,
layout_interner,
layout_ids,
list,
index.into_int_value(),
@ -844,6 +872,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let int_type = convert::int_type_from_int_width(env, *int_width);
build_int_unary_op(
env,
layout_interner,
parent,
arg.into_int_value(),
*int_width,
@ -1033,7 +1062,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
NumIntCast => {
arguments!(arg);
let to = basic_type_from_layout(env, layout).into_int_type();
let to = basic_type_from_layout(env, layout_interner, layout).into_int_type();
let to_signed = intwidth_from_layout(*layout).is_signed();
env.builder
@ -1047,7 +1076,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::Int(width)) => {
// Converting from int to float
let int_val = arg.into_int_value();
let dest = basic_type_from_layout(env, layout).into_float_type();
let dest =
basic_type_from_layout(env, layout_interner, layout).into_float_type();
if width.is_signed() {
env.builder
@ -1061,7 +1091,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
}
Layout::Builtin(Builtin::Float(_)) => {
// Converting from float to float - e.g. F64 to F32, or vice versa
let dest = basic_type_from_layout(env, layout).into_float_type();
let dest =
basic_type_from_layout(env, layout_interner, layout).into_float_type();
env.builder
.build_float_cast(arg.into_float_value(), dest, "cast_float_to_float")
@ -1083,12 +1114,28 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
Eq => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
generic_eq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
generic_eq(
env,
layout_interner,
layout_ids,
lhs_arg,
rhs_arg,
lhs_layout,
rhs_layout,
)
}
NotEq => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
generic_neq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
generic_neq(
env,
layout_interner,
layout_ids,
lhs_arg,
rhs_arg,
lhs_layout,
rhs_layout,
)
}
And => {
// The (&&) operator
@ -1137,13 +1184,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
unreachable!("Not used in LLVM backend: {:?}", op);
}
Unreachable => match RocReturn::from_layout(env, layout) {
Unreachable => match RocReturn::from_layout(env, layout_interner, layout) {
RocReturn::Return => {
let basic_type = basic_type_from_layout(env, layout);
let basic_type = basic_type_from_layout(env, layout_interner, layout);
basic_type.const_zero()
}
RocReturn::ByPointer => {
let basic_type = basic_type_from_layout(env, layout);
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let ptr = env.builder.build_alloca(basic_type, "unreachable_alloca");
env.builder.build_store(ptr, basic_type.const_zero());
@ -1817,6 +1864,7 @@ fn int_type_signed_min(int_type: IntType) -> IntValue {
fn build_int_unary_op<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
arg: IntValue<'ctx>,
arg_width: IntWidth,
@ -1887,8 +1935,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|| // Or if the two types are the same, they trivially fit.
arg_width == target_int_width;
let return_type =
convert::basic_type_from_layout(env, return_layout).into_struct_type();
let return_type = convert::basic_type_from_layout(env, layout_interner, return_layout)
.into_struct_type();
if arg_always_fits_in_target {
// This is guaranteed to succeed so we can just make it an int cast and let LLVM
@ -1958,8 +2006,9 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
intrinsic,
);
let roc_return_type = basic_type_from_layout(env, return_layout)
.ptr_type(AddressSpace::Generic);
let roc_return_type =
basic_type_from_layout(env, layout_interner, return_layout)
.ptr_type(AddressSpace::Generic);
let roc_return_alloca = env.builder.build_pointer_cast(
zig_return_alloca,
@ -1967,7 +2016,13 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
"cast_to_roc",
);
load_roc_value(env, *return_layout, roc_return_alloca, "num_to_int")
load_roc_value(
env,
layout_interner,
*return_layout,
roc_return_alloca,
"num_to_int",
)
}
}
}
@ -1978,6 +2033,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
call_bitcode_fn_fixing_for_convention(
env,
layout_interner,
bitcode_return_type,
&[arg.into()],
return_layout,
@ -2221,6 +2277,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>,
return_layout: &Layout<'a>,
@ -2276,13 +2333,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::List(element_layout)),
Layout::Builtin(Builtin::List(result_layout)),
) => {
let element_layout = env.layout_interner.get(*element_layout);
let result_layout = env.layout_interner.get(*result_layout);
let element_layout = layout_interner.get(*element_layout);
let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[*element_layout];
let roc_function_call = roc_function_call(
env,
layout_interner,
layout_ids,
function,
closure,
@ -2292,7 +2350,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
*result_layout,
);
list_map(env, roc_function_call, list, element_layout, result_layout)
list_map(
env,
layout_interner,
roc_function_call,
list,
element_layout,
result_layout,
)
}
_ => unreachable!("invalid list layout"),
}
@ -2309,14 +2374,15 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::List(element2_layout)),
Layout::Builtin(Builtin::List(result_layout)),
) => {
let element1_layout = env.layout_interner.get(*element1_layout);
let element2_layout = env.layout_interner.get(*element2_layout);
let result_layout = env.layout_interner.get(*result_layout);
let element1_layout = layout_interner.get(*element1_layout);
let element2_layout = layout_interner.get(*element2_layout);
let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[*element1_layout, *element2_layout];
let roc_function_call = roc_function_call(
env,
layout_interner,
layout_ids,
function,
closure,
@ -2328,6 +2394,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_map2(
env,
layout_interner,
layout_ids,
roc_function_call,
list1,
@ -2354,15 +2421,16 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::List(element3_layout)),
Layout::Builtin(Builtin::List(result_layout)),
) => {
let element1_layout = env.layout_interner.get(*element1_layout);
let element2_layout = env.layout_interner.get(*element2_layout);
let element3_layout = env.layout_interner.get(*element3_layout);
let result_layout = env.layout_interner.get(*result_layout);
let element1_layout = layout_interner.get(*element1_layout);
let element2_layout = layout_interner.get(*element2_layout);
let element3_layout = layout_interner.get(*element3_layout);
let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[*element1_layout, *element2_layout, *element3_layout];
let roc_function_call = roc_function_call(
env,
layout_interner,
layout_ids,
function,
closure,
@ -2374,6 +2442,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_map3(
env,
layout_interner,
layout_ids,
roc_function_call,
list1,
@ -2410,11 +2479,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::List(element4_layout)),
Layout::Builtin(Builtin::List(result_layout)),
) => {
let element1_layout = env.layout_interner.get(*element1_layout);
let element2_layout = env.layout_interner.get(*element2_layout);
let element3_layout = env.layout_interner.get(*element3_layout);
let element4_layout = env.layout_interner.get(*element4_layout);
let result_layout = env.layout_interner.get(*result_layout);
let element1_layout = layout_interner.get(*element1_layout);
let element2_layout = layout_interner.get(*element2_layout);
let element3_layout = layout_interner.get(*element3_layout);
let element4_layout = layout_interner.get(*element4_layout);
let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[
*element1_layout,
@ -2425,6 +2494,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let roc_function_call = roc_function_call(
env,
layout_interner,
layout_ids,
function,
closure,
@ -2436,6 +2506,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_map4(
env,
layout_interner,
layout_ids,
roc_function_call,
list1,
@ -2462,17 +2533,23 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::List(element_layout)) => {
use crate::llvm::bitcode::build_compare_wrapper;
let element_layout = env.layout_interner.get(*element_layout);
let element_layout = layout_interner.get(*element_layout);
let argument_layouts = &[*element_layout, *element_layout];
let compare_wrapper =
build_compare_wrapper(env, function, closure_layout, element_layout)
.as_global_value()
.as_pointer_value();
let compare_wrapper = build_compare_wrapper(
env,
layout_interner,
function,
closure_layout,
element_layout,
)
.as_global_value()
.as_pointer_value();
let roc_function_call = roc_function_call(
env,
layout_interner,
layout_ids,
function,
closure,
@ -2484,6 +2561,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_sort_with(
env,
layout_interner,
roc_function_call,
compare_wrapper,
list,

View file

@ -114,10 +114,11 @@ impl<'ctx> PointerToRefcount<'ctx> {
mode: CallMode<'ctx>,
layout: &Layout<'a>,
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
) {
match mode {
CallMode::Inc(inc_amount) => self.increment(inc_amount, env),
CallMode::Dec => self.decrement(env, layout),
CallMode::Dec => self.decrement(env, layout_interner, layout),
}
}
@ -125,9 +126,14 @@ impl<'ctx> PointerToRefcount<'ctx> {
incref_pointer(env, self.value, amount);
}
pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
pub fn decrement<'a, 'env>(
&self,
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'a>,
) {
let alignment = layout
.allocation_alignment_bytes(env.layout_interner, env.target_info)
.allocation_alignment_bytes(layout_interner, env.target_info)
.max(env.target_info.ptr_width() as u32);
let context = env.context;
@ -266,6 +272,7 @@ pub fn decref_pointer_check_null<'a, 'ctx, 'env>(
fn modify_refcount_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
layouts: &'a [Layout<'a>],
mode: Mode,
@ -288,11 +295,12 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let basic_type = basic_type_from_layout(env, &layout);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_struct_help(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
@ -314,6 +322,7 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn modify_refcount_struct_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -339,7 +348,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(env.layout_interner) {
if field_layout.contains_refcounted(layout_interner) {
let raw_value = env
.builder
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
@ -347,6 +356,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
let field_value = use_roc_value(
env,
layout_interner,
*field_layout,
raw_value,
"load_struct_tag_field_for_decrement",
@ -354,6 +364,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
@ -368,36 +379,54 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
pub fn increment_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
inc_amount: u64,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
) {
let amount = env.ptr_int().const_int(inc_amount, false);
increment_n_refcount_layout(env, layout_ids, amount, value, layout);
increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout);
}
pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
amount: IntValue<'ctx>,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
) {
modify_refcount_layout(env, layout_ids, CallMode::Inc(amount), value, layout);
modify_refcount_layout(
env,
layout_interner,
layout_ids,
CallMode::Inc(amount),
value,
layout,
);
}
pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
) {
modify_refcount_layout(env, layout_ids, CallMode::Dec, value, layout);
modify_refcount_layout(
env,
layout_interner,
layout_ids,
CallMode::Dec,
value,
layout,
);
}
fn modify_refcount_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -408,13 +437,25 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
match builtin {
List(element_layout) => {
let function =
modify_refcount_list(env, layout_ids, mode, when_recursive, *element_layout);
let function = modify_refcount_list(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
*element_layout,
);
Some(function)
}
Str => Some(modify_refcount_str(env, layout_ids, mode, layout)),
Str => Some(modify_refcount_str(
env,
layout_interner,
layout_ids,
mode,
layout,
)),
_ => {
debug_assert!(!builtin.is_refcounted());
@ -425,6 +466,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
fn modify_refcount_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>,
value: BasicValueEnum<'ctx>,
@ -432,6 +474,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
) {
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
call_mode,
&WhenRecursive::Unreachable,
@ -442,6 +485,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
fn modify_refcount_layout_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>,
when_recursive: &WhenRecursive<'a>,
@ -455,6 +499,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
let function = match modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
@ -472,7 +517,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(*union_layout);
let bt = basic_type_from_layout(env, &layout);
let bt = basic_type_from_layout(env, layout_interner, &layout);
// cast the i64 pointer to a pointer to block of memory
let field_cast = env.builder.build_pointer_cast(
@ -519,6 +564,7 @@ fn call_help<'a, 'ctx, 'env>(
fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -527,12 +573,18 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
use Layout::*;
match layout {
Builtin(builtin) => {
modify_refcount_builtin(env, layout_ids, mode, when_recursive, layout, builtin)
}
Builtin(builtin) => modify_refcount_builtin(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
layout,
builtin,
),
Boxed(inner) => {
let function = modify_refcount_boxed(env, layout_ids, mode, *inner);
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, *inner);
Some(function)
}
@ -547,8 +599,14 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
}
NonRecursive(tags) => {
let function =
modify_refcount_nonrecursive(env, layout_ids, mode, when_recursive, tags);
let function = modify_refcount_nonrecursive(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
tags,
);
Some(function)
}
@ -556,6 +614,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
_ => {
let function = build_rec_union(
env,
layout_interner,
layout_ids,
mode,
&WhenRecursive::Loop(*variant),
@ -568,8 +627,14 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
}
Struct { field_layouts, .. } => {
let function =
modify_refcount_struct(env, layout_ids, field_layouts, mode, when_recursive);
let function = modify_refcount_struct(
env,
layout_interner,
layout_ids,
field_layouts,
mode,
when_recursive,
);
Some(function)
}
@ -583,6 +648,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
let function = modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
@ -594,16 +660,18 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
},
LambdaSet(lambda_set) => modify_refcount_layout_build_function(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
&lambda_set.runtime_representation(env.layout_interner),
&lambda_set.runtime_representation(layout_interner),
),
}
}
fn modify_refcount_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -612,9 +680,9 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let element_layout = env.layout_interner.get(element_layout);
let element_layout = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
let element_layout = env.layout_interner.insert(env.arena.alloc(element_layout));
let element_layout = layout_interner.insert(env.arena.alloc(element_layout));
let list_layout = &Layout::Builtin(Builtin::List(element_layout));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -628,11 +696,12 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let basic_type = argument_type_from_layout(env, list_layout);
let basic_type = argument_type_from_layout(env, layout_interner, list_layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_list_help(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
@ -661,6 +730,7 @@ fn mode_to_call_mode(function: FunctionValue<'_>, mode: Mode) -> CallMode<'_> {
fn modify_refcount_list_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -704,15 +774,17 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
builder.position_at_end(modification_block);
let element_layout = env.layout_interner.get(element_layout);
if element_layout.contains_refcounted(env.layout_interner) {
let ptr_type = basic_type_from_layout(env, element_layout).ptr_type(AddressSpace::Generic);
let element_layout = layout_interner.get(element_layout);
if element_layout.contains_refcounted(layout_interner) {
let ptr_type = basic_type_from_layout(env, layout_interner, element_layout)
.ptr_type(AddressSpace::Generic);
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
let loop_fn = |_index, element| {
let loop_fn = |layout_interner, _index, element| {
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
@ -723,6 +795,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
incrementing_elem_loop(
env,
layout_interner,
parent,
*element_layout,
ptr,
@ -734,7 +807,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, original_wrapper);
let call_mode = mode_to_call_mode(fn_val, mode);
refcount_ptr.modify(call_mode, layout, env);
refcount_ptr.modify(call_mode, layout, env, layout_interner);
builder.build_unconditional_branch(cont_block);
@ -746,6 +819,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
fn modify_refcount_str<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
layout: &Layout<'a>,
@ -765,10 +839,10 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let basic_type = argument_type_from_layout(env, layout);
let basic_type = argument_type_from_layout(env, layout_interner, layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_str_help(env, mode, layout, function_value);
modify_refcount_str_help(env, layout_interner, mode, layout, function_value);
function_value
}
@ -783,6 +857,7 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
fn modify_refcount_str_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
mode: Mode,
layout: &Layout<'a>,
fn_val: FunctionValue<'ctx>,
@ -805,17 +880,16 @@ 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.layout_interner, env.target_info)
{
let str_type = zig_str_type(env);
env.builder
.new_build_load(str_type, arg_val.into_pointer_value(), "load_str_to_stack")
} else {
// it's already a struct, just do nothing
debug_assert!(arg_val.is_struct_value());
arg_val
};
let arg_val =
if Layout::Builtin(Builtin::Str).is_passed_by_reference(layout_interner, env.target_info) {
let str_type = zig_str_type(env);
env.builder
.new_build_load(str_type, arg_val.into_pointer_value(), "load_str_to_stack")
} else {
// it's already a struct, just do nothing
debug_assert!(arg_val.is_struct_value());
arg_val
};
let str_wrapper = arg_val.into_struct_value();
let capacity = builder
@ -841,7 +915,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, str_wrapper);
let call_mode = mode_to_call_mode(fn_val, mode);
refcount_ptr.modify(call_mode, layout, env);
refcount_ptr.modify(call_mode, layout, env, layout_interner);
builder.build_unconditional_branch(cont_block);
@ -853,6 +927,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
fn modify_refcount_boxed<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
inner_layout: InLayout<'a>,
@ -874,10 +949,10 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let basic_type = basic_type_from_layout(env, boxed_layout);
let basic_type = basic_type_from_layout(env, layout_interner, boxed_layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_box_help(env, mode, inner_layout, function_value);
modify_refcount_box_help(env, layout_interner, mode, inner_layout, function_value);
function_value
}
@ -892,6 +967,7 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
fn modify_refcount_box_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
mode: Mode,
inner_layout: InLayout<'a>,
fn_val: FunctionValue<'ctx>,
@ -915,7 +991,7 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
let call_mode = mode_to_call_mode(fn_val, mode);
let boxed_layout = Layout::Boxed(inner_layout);
refcount_ptr.modify(call_mode, &boxed_layout, env);
refcount_ptr.modify(call_mode, &boxed_layout, env, layout_interner);
// this function returns void
builder.build_return(None);
@ -1014,6 +1090,7 @@ enum CallMode<'ctx> {
fn build_rec_union<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -1036,11 +1113,12 @@ fn build_rec_union<'a, 'ctx, 'env>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let basic_type = basic_type_from_layout(env, &layout);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
build_rec_union_help(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
@ -1062,6 +1140,7 @@ fn build_rec_union<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_rec_union_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -1091,7 +1170,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
let parent = fn_val;
debug_assert!(arg_val.is_pointer_value());
let current_tag_id = get_tag_id(env, fn_val, &union_layout, arg_val);
let current_tag_id = get_tag_id(env, layout_interner, fn_val, &union_layout, arg_val);
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target_info) {
tag_pointer_clear_tag_id(env, arg_val.into_pointer_value())
} else {
@ -1128,7 +1207,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
match mode {
Mode::Inc => {
// inc is cheap; we never recurse
refcount_ptr.modify(call_mode, &layout, env);
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
env.builder.build_return(None);
}
@ -1145,7 +1224,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
{
env.builder.position_at_end(no_recurse_block);
refcount_ptr.modify(call_mode, &layout, env);
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
env.builder.build_return(None);
}
@ -1154,6 +1233,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
build_rec_union_recursive_decrement(
env,
layout_interner,
layout_ids,
when_recursive,
parent,
@ -1185,6 +1265,7 @@ fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[Layo
#[allow(clippy::too_many_arguments)]
fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: &WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
@ -1205,11 +1286,11 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
let tag_id_int_type =
basic_type_from_layout(env, &union_layout.tag_id_layout()).into_int_type();
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()).into_int_type();
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(env.layout_interner, field_layouts) {
if fields_need_no_refcounting(layout_interner, field_layouts) {
continue;
}
@ -1217,8 +1298,11 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
env.builder.position_at_end(block);
let wrapper_type =
basic_type_from_layout(env, &Layout::struct_no_name_order(field_layouts));
let wrapper_type = basic_type_from_layout(
env,
layout_interner,
&Layout::struct_no_name_order(field_layouts),
);
// cast the opaque pointer to a pointer of the correct shape
let struct_ptr = env.builder.build_pointer_cast(
@ -1254,11 +1338,12 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
// therefore we must cast it to our desired type
let union_type = basic_type_from_layout(env, &Layout::Union(union_layout));
let union_type =
basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout));
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(env.layout_interner) {
} else if field_layout.contains_refcounted(layout_interner) {
let elem_pointer = env
.builder
.new_build_struct_gep(
@ -1269,8 +1354,13 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
)
.unwrap();
let field =
load_roc_value(env, *field_layout, elem_pointer, "decrement_struct_field");
let field = load_roc_value(
env,
layout_interner,
*field_layout,
elem_pointer,
"decrement_struct_field",
);
deferred_nonrec.push((field, field_layout));
}
@ -1286,13 +1376,19 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
match decrement_or_reuse {
DecOrReuse::Reuse => {}
DecOrReuse::Dec => {
refcount_ptr.modify(call_mode, &Layout::Union(union_layout), env);
refcount_ptr.modify(
call_mode,
&Layout::Union(union_layout),
env,
layout_interner,
);
}
}
for (field, field_layout) in deferred_nonrec {
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
mode.to_call_mode(decrement_fn),
when_recursive,
@ -1338,7 +1434,12 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
// increment/decrement the cons-cell itself
if let DecOrReuse::Dec = decrement_or_reuse {
refcount_ptr.modify(call_mode, &Layout::Union(union_layout), env);
refcount_ptr.modify(
call_mode,
&Layout::Union(union_layout),
env,
layout_interner,
);
}
}
@ -1366,6 +1467,7 @@ fn union_layout_tags<'a>(
pub fn build_reset<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
union_layout: UnionLayout<'a>,
) -> FunctionValue<'ctx> {
@ -1376,7 +1478,14 @@ pub fn build_reset<'a, 'ctx, 'env>(
let fn_name = format!("{}_reset", fn_name);
let when_recursive = WhenRecursive::Loop(union_layout);
let dec_function = build_rec_union(env, layout_ids, Mode::Dec, &when_recursive, union_layout);
let dec_function = build_rec_union(
env,
layout_interner,
layout_ids,
Mode::Dec,
&when_recursive,
union_layout,
);
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
@ -1384,11 +1493,13 @@ pub fn build_reset<'a, 'ctx, 'env>(
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let basic_type = basic_type_from_layout(env, &Layout::Union(union_layout));
let basic_type =
basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout));
let function_value = build_header(env, basic_type, mode, &fn_name);
build_reuse_rec_union_help(
env,
layout_interner,
layout_ids,
&when_recursive,
union_layout,
@ -1410,6 +1521,7 @@ pub fn build_reset<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)]
fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: &WhenRecursive<'a>,
union_layout: UnionLayout<'a>,
@ -1440,7 +1552,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
let parent = reset_function;
debug_assert!(arg_val.is_pointer_value());
let current_tag_id = get_tag_id(env, reset_function, &union_layout, arg_val);
let current_tag_id = get_tag_id(env, layout_interner, reset_function, &union_layout, arg_val);
let value_ptr = tag_pointer_clear_tag_id(env, arg_val.into_pointer_value());
// to increment/decrement the cons-cell itself
@ -1478,7 +1590,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
{
env.builder.position_at_end(no_recurse_block);
refcount_ptr.modify(call_mode, &layout, env);
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
env.builder.build_return(None);
}
@ -1487,6 +1599,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
build_rec_union_recursive_decrement(
env,
layout_interner,
layout_ids,
when_recursive,
parent,
@ -1524,6 +1637,7 @@ fn function_name_from_mode<'a>(
fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -1547,11 +1661,12 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value,
None => {
let basic_type = argument_type_from_union_layout(env, &union_layout);
let basic_type = argument_type_from_union_layout(env, layout_interner, &union_layout);
let function_value = build_header(env, basic_type, mode, &fn_name);
modify_refcount_nonrecursive_help(
env,
layout_interner,
layout_ids,
mode,
when_recursive,
@ -1572,6 +1687,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
@ -1602,7 +1718,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
let union_layout = UnionLayout::NonRecursive(tags);
let layout = Layout::Union(union_layout);
let union_struct_type = basic_type_from_layout(env, &layout).into_struct_type();
let union_struct_type =
basic_type_from_layout(env, layout_interner, &layout).into_struct_type();
// read the tag_id
let tag_id_ptr = env
@ -1618,7 +1735,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
let tag_id = env
.builder
.new_build_load(
basic_type_from_layout(env, &union_layout.tag_id_layout()),
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()),
tag_id_ptr,
"load_tag_id",
)
@ -1639,7 +1756,7 @@ fn modify_refcount_nonrecursive_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(env.layout_interner))
.any(|x| x.is_refcounted() || x.contains_refcounted(layout_interner))
{
continue;
}
@ -1647,8 +1764,11 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
let block = env.context.append_basic_block(parent, "tag_id_modify");
env.builder.position_at_end(block);
let data_struct_type =
basic_type_from_layout(env, &Layout::struct_no_name_order(field_layouts));
let data_struct_type = basic_type_from_layout(
env,
layout_interner,
&Layout::struct_no_name_order(field_layouts),
);
debug_assert!(data_struct_type.is_struct_type());
let data_struct_type = data_struct_type.into_struct_type();
@ -1698,20 +1818,24 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
debug_assert!(field_value.is_pointer_value());
// therefore we must cast it to our desired type
let union_type =
basic_type_from_layout(env, &Layout::Union(*recursive_union_layout));
let union_type = basic_type_from_layout(
env,
layout_interner,
&Layout::Union(*recursive_union_layout),
);
let recursive_ptr_field_value =
cast_basic_basic(env.builder, field_value, union_type);
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,
recursive_ptr_field_value,
&Layout::RecursivePointer,
)
} else if field_layout.contains_refcounted(env.layout_interner) {
} else if field_layout.contains_refcounted(layout_interner) {
let field_ptr = env
.builder
.new_build_struct_gep(
@ -1723,11 +1847,11 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
.unwrap();
let field_value =
if field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
if field_layout.is_passed_by_reference(layout_interner, env.target_info) {
field_ptr.into()
} else {
env.builder.new_build_load(
basic_type_from_layout(env, field_layout),
basic_type_from_layout(env, layout_interner, field_layout),
field_ptr,
"field_value",
)
@ -1735,6 +1859,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
modify_refcount_layout_help(
env,
layout_interner,
layout_ids,
mode.to_call_mode(fn_val),
when_recursive,