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 inkwell::AddressSpace;
use roc_error_macros::internal_error; use roc_error_macros::internal_error;
use roc_module::symbol::Symbol; 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::build::{create_entry_block_alloca, BuilderExt};
use super::convert::zig_list_type; 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>( pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
bitcode_return_type: StructType<'ctx>, bitcode_return_type: StructType<'ctx>,
args: &[BasicValueEnum<'ctx>], args: &[BasicValueEnum<'ctx>],
return_layout: &Layout<'_>, return_layout: &Layout<'a>,
fn_name: &str, fn_name: &str,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
// Calling zig bitcode, so we must follow C calling conventions. // 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 { match cc_return {
CCReturn::Return => { CCReturn::Return => {
// We'll get a return value // We'll get a return value
@ -109,7 +110,7 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
} }
CCReturn::ByPointer => { CCReturn::ByPointer => {
// We need to pass the return value by pointer. // 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(); 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>( pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
function: FunctionValue<'ctx>, function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>, closure_data_layout: LambdaSet<'a>,
argument_layouts: &[Layout<'a>], argument_layouts: &[Layout<'a>],
@ -178,6 +180,7 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
Some(function_value) => function_value, Some(function_value) => function_value,
None => build_transform_caller_help( None => build_transform_caller_help(
env, env,
layout_interner,
function, function,
closure_data_layout, closure_data_layout,
argument_layouts, argument_layouts,
@ -189,6 +192,7 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
fn build_transform_caller_help<'a, 'ctx, 'env>( fn build_transform_caller_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>, closure_data_layout: LambdaSet<'a>,
argument_layouts: &[Layout<'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); bumpalo::collections::Vec::with_capacity_in(arguments.len(), env.arena);
for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) { 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( let cast_ptr = env.builder.build_pointer_cast(
argument_ptr.into_pointer_value(), 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", "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); arguments_cast.push(argument);
} }
match ( match (
closure_data_layout closure_data_layout
.is_represented(env.layout_interner) .is_represented(layout_interner)
.is_some(), .is_some(),
closure_data_layout.runtime_representation(env.layout_interner), closure_data_layout.runtime_representation(layout_interner),
) { ) {
(false, _) => { (false, _) => {
// the function doesn't expect a closure argument, nothing to add // the function doesn't expect a closure argument, nothing to add
} }
(true, layout) => { (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 = let closure_cast =
env.builder env.builder
.build_pointer_cast(closure_ptr, closure_type, "cast_opaque_closure"); .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); 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( let result = crate::llvm::build::call_roc_function(
env, env,
layout_interner,
roc_function, roc_function,
&result_layout, &result_layout,
arguments_cast.as_slice(), arguments_cast.as_slice(),
@ -284,7 +298,13 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
.unwrap() .unwrap()
.into_pointer_value(); .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.build_return(None);
env.builder.position_at_end(block); 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 /// 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>( pub fn build_inc_n_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>, layout: &Layout<'a>,
) -> FunctionValue<'ctx> { ) -> 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 /// a function that accepts two arguments: the value to increment; increments by 1
pub fn build_inc_wrapper<'a, 'ctx, 'env>( pub fn build_inc_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>, layout: &Layout<'a>,
) -> FunctionValue<'ctx> { ) -> 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>( pub fn build_dec_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>, layout: &Layout<'a>,
) -> FunctionValue<'ctx> { ) -> 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>( fn build_rc_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>, layout: &Layout<'a>,
rc_operation: Mode, 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)); 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_type = value_type.ptr_type(AddressSpace::Generic);
let value_ptr = let value_ptr =
env.builder 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. // 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 // I suspect it has something to do with the lifetime of the alloca that is created by
// `load_roc_value` // `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() value_ptr.into()
} else { } else {
env.builder env.builder
@ -403,16 +427,16 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
match rc_operation { match rc_operation {
Mode::Inc => { Mode::Inc => {
let n = 1; 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 => { Mode::IncN => {
let n = it.next().unwrap().into_int_value(); let n = it.next().unwrap().into_int_value();
n.set_name(Symbol::ARG_2.as_str(&env.interns)); 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 => { 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>( pub fn build_eq_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
layout: &Layout<'a>, layout: &Layout<'a>,
) -> FunctionValue<'ctx> { ) -> 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_ptr1.set_name(Symbol::ARG_1.as_str(&env.interns));
value_ptr2.set_name(Symbol::ARG_2.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 let value_cast1 = env
.builder .builder
@ -485,11 +511,18 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
.build_pointer_cast(value_ptr2, value_type, "load_opaque"); .build_pointer_cast(value_ptr2, value_type, "load_opaque");
// load_roc_value(env, *element_layout, elem_ptr, "get_elem") // load_roc_value(env, *element_layout, elem_ptr, "get_elem")
let value1 = load_roc_value(env, *layout, value_cast1, "load_opaque"); let value1 = load_roc_value(env, layout_interner, *layout, value_cast1, "load_opaque");
let value2 = load_roc_value(env, *layout, value_cast2, "load_opaque"); let value2 = load_roc_value(env, layout_interner, *layout, value_cast2, "load_opaque");
let result = let result = crate::llvm::compare::generic_eq(
crate::llvm::compare::generic_eq(env, layout_ids, value1, value2, layout, layout); env,
layout_interner,
layout_ids,
value1,
value2,
layout,
layout,
);
env.builder.build_return(Some(&result)); 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>( pub fn build_compare_wrapper<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>, roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>, closure_data_layout: LambdaSet<'a>,
layout: &Layout<'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_ptr1.set_name(Symbol::ARG_2.as_str(&env.interns));
value_ptr2.set_name(Symbol::ARG_3.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_ptr_type = value_type.ptr_type(AddressSpace::Generic);
let value_cast1 = let value_cast1 =
@ -575,33 +609,32 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
let default = [value1.into(), value2.into()]; let default = [value1.into(), value2.into()];
let arguments_cast = let arguments_cast = match closure_data_layout.runtime_representation(layout_interner) {
match closure_data_layout.runtime_representation(env.layout_interner) { Layout::Struct {
Layout::Struct { field_layouts: &[], ..
field_layouts: &[], .. } => {
} => { // nothing to add
// nothing to add &default
&default }
} other => {
other => { let closure_type = basic_type_from_layout(env, layout_interner, &other);
let closure_type = basic_type_from_layout(env, &other); let closure_ptr_type = closure_type.ptr_type(AddressSpace::Generic);
let closure_ptr_type = closure_type.ptr_type(AddressSpace::Generic);
let closure_cast = env.builder.build_pointer_cast( let closure_cast = env.builder.build_pointer_cast(
closure_ptr, closure_ptr,
closure_ptr_type, closure_ptr_type,
"load_opaque", "load_opaque",
); );
let closure_data = let closure_data =
env.builder env.builder
.new_build_load(closure_type, closure_cast, "load_opaque"); .new_build_load(closure_type, closure_cast, "load_opaque");
env.arena env.arena
.alloc([value1.into(), value2.into(), closure_data.into()]) .alloc([value1.into(), value2.into(), closure_data.into()])
as &[_] as &[_]
} }
}; };
let call = env.builder.build_call( let call = env.builder.build_call(
roc_function, 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_builtins::bitcode;
use roc_intern::Interner; use roc_intern::Interner;
use roc_module::symbol::Symbol; 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::bitcode::{call_list_bitcode_fn, BitcodeReturns};
use super::build::{ use super::build::{
@ -63,14 +63,15 @@ pub(crate) fn pass_update_mode<'a, 'ctx, 'env>(
fn pass_element_as_opaque<'a, 'ctx, 'env>( fn pass_element_as_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
element: BasicValueEnum<'ctx>, element: BasicValueEnum<'ctx>,
layout: Layout<'a>, layout: Layout<'a>,
) -> BasicValueEnum<'ctx> { ) -> 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 let element_ptr = env
.builder .builder
.build_alloca(element_type, "element_to_pass_as_opaque"); .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 env.builder
.build_pointer_cast( .build_pointer_cast(
@ -83,11 +84,12 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
pub(crate) fn layout_width<'a, 'ctx, 'env>( pub(crate) fn layout_width<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'a>, layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
env.ptr_int() env.ptr_int()
.const_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, false,
) )
.into() .into()
@ -108,17 +110,18 @@ pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>(
pub(crate) fn list_with_capacity<'a, 'ctx, 'env>( pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
capacity: IntValue<'ctx>, capacity: IntValue<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn( call_list_bitcode_fn(
env, env,
&[], &[],
&[ &[
capacity.into(), capacity.into(),
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
], ],
BitcodeReturns::List, BitcodeReturns::List,
bitcode::LIST_WITH_CAPACITY, 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>( pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
elem_index: IntValue<'ctx>, elem_index: IntValue<'ctx>,
@ -134,8 +138,8 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let builder = env.builder; let builder = env.builder;
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
let elem_type = basic_type_from_layout(env, element_layout); let elem_type = basic_type_from_layout(env, layout_interner, element_layout);
let ptr_type = elem_type.ptr_type(AddressSpace::Generic); let ptr_type = elem_type.ptr_type(AddressSpace::Generic);
// Load the pointer to the array data // Load the pointer to the array data
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type); 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 result
} }
@ -161,19 +171,20 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
/// List.reserve : List elem, Nat -> List elem /// List.reserve : List elem, Nat -> List elem
pub(crate) fn list_reserve<'a, 'ctx, 'env>( pub(crate) fn list_reserve<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
spare: BasicValueEnum<'ctx>, spare: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
update_mode: UpdateMode, update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn_1( call_list_bitcode_fn_1(
env, env,
list.into_struct_value(), list.into_struct_value(),
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
spare, spare,
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
pass_update_mode(env, update_mode), pass_update_mode(env, update_mode),
], ],
bitcode::LIST_RESERVE, bitcode::LIST_RESERVE,
@ -183,6 +194,7 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
/// List.appendUnsafe : List elem, elem -> List elem /// List.appendUnsafe : List elem, elem -> List elem
pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>( pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>, element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>, element_layout: &Layout<'a>,
@ -191,8 +203,8 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
env, env,
original_wrapper, original_wrapper,
&[ &[
pass_element_as_opaque(env, element, *element_layout), pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
], ],
bitcode::LIST_APPEND_UNSAFE, bitcode::LIST_APPEND_UNSAFE,
) )
@ -201,6 +213,7 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
/// List.prepend : List elem, elem -> List elem /// List.prepend : List elem, elem -> List elem
pub(crate) fn list_prepend<'a, 'ctx, 'env>( pub(crate) fn list_prepend<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>, element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>, element_layout: &Layout<'a>,
@ -209,9 +222,9 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
env, env,
original_wrapper, original_wrapper,
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
pass_element_as_opaque(env, element, *element_layout), pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
], ],
bitcode::LIST_PREPEND, bitcode::LIST_PREPEND,
) )
@ -220,19 +233,20 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
/// List.swap : List elem, Nat, Nat -> List elem /// List.swap : List elem, Nat, Nat -> List elem
pub(crate) fn list_swap<'a, 'ctx, 'env>( pub(crate) fn list_swap<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
index_1: IntValue<'ctx>, index_1: IntValue<'ctx>,
index_2: IntValue<'ctx>, index_2: IntValue<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
update_mode: UpdateMode, update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn_1( call_list_bitcode_fn_1(
env, env,
original_wrapper, original_wrapper,
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
index_1.into(), index_1.into(),
index_2.into(), index_2.into(),
pass_update_mode(env, update_mode), 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 /// List.sublist : List elem, { start : Nat, len : Nat } -> List elem
pub(crate) fn list_sublist<'a, 'ctx, 'env>( pub(crate) fn list_sublist<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
start: IntValue<'ctx>, start: IntValue<'ctx>,
len: IntValue<'ctx>, len: IntValue<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout); let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1( call_list_bitcode_fn_1(
env, env,
original_wrapper, original_wrapper,
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
start.into(), start.into(),
len.into(), len.into(),
dec_element_fn.as_global_value().as_pointer_value().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 /// List.dropAt : List elem, Nat -> List elem
pub(crate) fn list_drop_at<'a, 'ctx, 'env>( pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
original_wrapper: StructValue<'ctx>, original_wrapper: StructValue<'ctx>,
count: IntValue<'ctx>, count: IntValue<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout); let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
call_list_bitcode_fn_1( call_list_bitcode_fn_1(
env, env,
original_wrapper, original_wrapper,
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
count.into(), count.into(),
dec_element_fn.as_global_value().as_pointer_value().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 } /// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem }
pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>( pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
_layout_ids: &mut LayoutIds<'a>, _layout_ids: &mut LayoutIds<'a>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
index: IntValue<'ctx>, index: IntValue<'ctx>,
@ -299,7 +316,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
element_layout: &Layout<'a>, element_layout: &Layout<'a>,
update_mode: UpdateMode, update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> { ) -> 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 let element_ptr = env
.builder .builder
.build_alloca(element_type, "output_element_as_opaque"); .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(), list.into_struct_value(),
&[ &[
index.into(), index.into(),
pass_element_as_opaque(env, element, *element_layout), pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
pass_as_opaque(env, element_ptr), pass_as_opaque(env, element_ptr),
], ],
bitcode::LIST_REPLACE_IN_PLACE, bitcode::LIST_REPLACE_IN_PLACE,
@ -322,10 +339,10 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
env, env,
list.into_struct_value(), list.into_struct_value(),
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
index.into(), index.into(),
pass_element_as_opaque(env, element, *element_layout), pass_element_as_opaque(env, layout_interner, element, *element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
pass_as_opaque(env, element_ptr), pass_as_opaque(env, element_ptr),
], ],
bitcode::LIST_REPLACE, 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 // 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. // 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 element_first = element_align > env.target_info.ptr_width() as u32;
let fields = if element_first { let fields = if element_first {
@ -424,6 +441,7 @@ pub(crate) fn destructure<'ctx>(
/// List.sortWith : List a, (a, a -> Ordering) -> List a /// List.sortWith : List a, (a, a -> Ordering) -> List a
pub(crate) fn list_sort_with<'a, 'ctx, 'env>( pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
compare_wrapper: PointerValue<'ctx>, compare_wrapper: PointerValue<'ctx>,
list: BasicValueEnum<'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), pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(), roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(), roc_function_call.data_is_owned.into(),
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
], ],
bitcode::LIST_SORT_WITH, 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 /// List.map : List before, (before -> after) -> List after
pub(crate) fn list_map<'a, 'ctx, 'env>( pub(crate) fn list_map<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>, list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>, element_layout: &Layout<'a>,
@ -460,9 +479,9 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data), pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(), roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(), roc_function_call.data_is_owned.into(),
env.alignment_intvalue(return_layout), env.alignment_intvalue(layout_interner, return_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
layout_width(env, return_layout), layout_width(env, layout_interner, return_layout),
], ],
bitcode::LIST_MAP, bitcode::LIST_MAP,
) )
@ -470,6 +489,7 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
pub(crate) fn list_map2<'a, 'ctx, 'env>( pub(crate) fn list_map2<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>, list1: BasicValueEnum<'ctx>,
@ -478,8 +498,8 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
element2_layout: &Layout<'a>, element2_layout: &Layout<'a>,
return_layout: &Layout<'a>, return_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout); let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout); let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
call_list_bitcode_fn( call_list_bitcode_fn(
env, env,
@ -489,10 +509,10 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data), pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(), roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(), roc_function_call.data_is_owned.into(),
env.alignment_intvalue(return_layout), env.alignment_intvalue(layout_interner, return_layout),
layout_width(env, element1_layout), layout_width(env, layout_interner, element1_layout),
layout_width(env, element2_layout), layout_width(env, layout_interner, element2_layout),
layout_width(env, return_layout), layout_width(env, layout_interner, return_layout),
dec_a.as_global_value().as_pointer_value().into(), dec_a.as_global_value().as_pointer_value().into(),
dec_b.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>( pub(crate) fn list_map3<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>, list1: BasicValueEnum<'ctx>,
@ -513,9 +534,9 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
element3_layout: &Layout<'a>, element3_layout: &Layout<'a>,
result_layout: &Layout<'a>, result_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout); let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout); let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
let dec_c = build_dec_wrapper(env, layout_ids, element3_layout); let dec_c = build_dec_wrapper(env, layout_interner, layout_ids, element3_layout);
call_list_bitcode_fn( call_list_bitcode_fn(
env, env,
@ -529,11 +550,11 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data), pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(), roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(), roc_function_call.data_is_owned.into(),
env.alignment_intvalue(result_layout), env.alignment_intvalue(layout_interner, result_layout),
layout_width(env, element1_layout), layout_width(env, layout_interner, element1_layout),
layout_width(env, element2_layout), layout_width(env, layout_interner, element2_layout),
layout_width(env, element3_layout), layout_width(env, layout_interner, element3_layout),
layout_width(env, result_layout), layout_width(env, layout_interner, result_layout),
dec_a.as_global_value().as_pointer_value().into(), dec_a.as_global_value().as_pointer_value().into(),
dec_b.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(), 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>( pub(crate) fn list_map4<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
roc_function_call: RocFunctionCall<'ctx>, roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>, list1: BasicValueEnum<'ctx>,
@ -557,10 +579,10 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
element4_layout: &Layout<'a>, element4_layout: &Layout<'a>,
result_layout: &Layout<'a>, result_layout: &Layout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout); let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout); let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
let dec_c = build_dec_wrapper(env, layout_ids, element3_layout); let dec_c = build_dec_wrapper(env, layout_interner, layout_ids, element3_layout);
let dec_d = build_dec_wrapper(env, layout_ids, element4_layout); let dec_d = build_dec_wrapper(env, layout_interner, layout_ids, element4_layout);
call_list_bitcode_fn( call_list_bitcode_fn(
env, env,
@ -575,12 +597,12 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
pass_as_opaque(env, roc_function_call.data), pass_as_opaque(env, roc_function_call.data),
roc_function_call.inc_n_data.into(), roc_function_call.inc_n_data.into(),
roc_function_call.data_is_owned.into(), roc_function_call.data_is_owned.into(),
env.alignment_intvalue(result_layout), env.alignment_intvalue(layout_interner, result_layout),
layout_width(env, element1_layout), layout_width(env, layout_interner, element1_layout),
layout_width(env, element2_layout), layout_width(env, layout_interner, element2_layout),
layout_width(env, element3_layout), layout_width(env, layout_interner, element3_layout),
layout_width(env, element4_layout), layout_width(env, layout_interner, element4_layout),
layout_width(env, result_layout), layout_width(env, layout_interner, result_layout),
dec_a.as_global_value().as_pointer_value().into(), dec_a.as_global_value().as_pointer_value().into(),
dec_b.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(), 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 /// List.concat : List elem, List elem -> List elem
pub(crate) fn list_concat<'a, 'ctx, 'env>( pub(crate) fn list_concat<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
list1: BasicValueEnum<'ctx>, list1: BasicValueEnum<'ctx>,
list2: BasicValueEnum<'ctx>, list2: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>, element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let element_layout = env.layout_interner.get(element_layout); let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn( call_list_bitcode_fn(
env, env,
&[list1.into_struct_value(), list2.into_struct_value()], &[list1.into_struct_value(), list2.into_struct_value()],
&[ &[
env.alignment_intvalue(element_layout), env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, element_layout), layout_width(env, layout_interner, element_layout),
], ],
BitcodeReturns::List, BitcodeReturns::List,
bitcode::LIST_CONCAT, 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>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &'r mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
element_layout: Layout<'a>, element_layout: Layout<'a>,
ptr: PointerValue<'ctx>, ptr: PointerValue<'ctx>,
@ -621,39 +645,49 @@ pub(crate) fn incrementing_elem_loop<'a, 'ctx, 'env, LoopFn>(
mut loop_fn: LoopFn, mut loop_fn: LoopFn,
) -> PointerValue<'ctx> ) -> PointerValue<'ctx>
where where
LoopFn: FnMut(IntValue<'ctx>, BasicValueEnum<'ctx>), LoopFn: FnMut(&'r mut STLayoutInterner<'a>, IntValue<'ctx>, BasicValueEnum<'ctx>),
{ {
let builder = env.builder; 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| { incrementing_index_loop(
// The pointer to the element in the list env,
let element_ptr = layout_interner,
unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index], "load_index") }; 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( let elem = load_roc_value(
env, env,
element_layout, layout_interner,
element_ptr, element_layout,
"incrementing_element_loop_load", element_ptr,
); "incrementing_element_loop_load",
);
loop_fn(index, elem); loop_fn(layout_interner, index, elem);
}) },
)
} }
// This helper simulates a basic for loop, where // This helper simulates a basic for loop, where
// and index increments up from 0 to some end value // 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>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &'r mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
end: IntValue<'ctx>, end: IntValue<'ctx>,
index_name: &str, index_name: &str,
mut loop_fn: LoopFn, mut loop_fn: LoopFn,
) -> PointerValue<'ctx> ) -> PointerValue<'ctx>
where where
LoopFn: FnMut(IntValue<'ctx>), LoopFn: FnMut(&'r mut STLayoutInterner<'a>, IntValue<'ctx>),
{ {
let ctx = env.context; let ctx = env.context;
let builder = env.builder; let builder = env.builder;
@ -682,7 +716,7 @@ where
builder.build_store(index_alloca, next_index); builder.build_store(index_alloca, next_index);
// The body of the loop // The body of the loop
loop_fn(current_index); loop_fn(layout_interner, current_index);
// #index < end // #index < end
let loop_end_cond = bounds_check_comparison(builder, next_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>( pub(crate) fn allocate_list<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
elem_layout: &Layout<'a>, elem_layout: &Layout<'a>,
number_of_elements: IntValue<'ctx>, number_of_elements: IntValue<'ctx>,
) -> PointerValue<'ctx> { ) -> PointerValue<'ctx> {
let builder = env.builder; let builder = env.builder;
let len_type = env.ptr_int(); 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 bytes_per_element = len_type.const_int(elem_bytes, false);
let number_of_data_bytes = let number_of_data_bytes =
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length"); builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
let basic_type = basic_type_from_layout(env, elem_layout); let basic_type = basic_type_from_layout(env, layout_interner, elem_layout);
let alignment_bytes = elem_layout.alignment_bytes(env.layout_interner, env.target_info); 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) 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_builtins::bitcode::{FloatWidth, IntWidth};
use roc_intern::Interner; use roc_intern::Interner;
use roc_module::symbol::Symbol; 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::build::{load_roc_value, use_roc_value, BuilderExt};
use super::convert::argument_type_from_union_layout; 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>( pub fn generic_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>,
@ -30,6 +31,7 @@ pub fn generic_eq<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
build_eq( build_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
lhs_val, lhs_val,
rhs_val, rhs_val,
@ -41,6 +43,7 @@ pub fn generic_eq<'a, 'ctx, 'env>(
pub fn generic_neq<'a, 'ctx, 'env>( pub fn generic_neq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>,
@ -49,6 +52,7 @@ pub fn generic_neq<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
build_neq( build_neq(
env, env,
layout_interner,
layout_ids, layout_ids,
lhs_val, lhs_val,
rhs_val, rhs_val,
@ -60,6 +64,7 @@ pub fn generic_neq<'a, 'ctx, 'env>(
fn build_eq_builtin<'a, 'ctx, 'env>( fn build_eq_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
rhs_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::Str => str_equal(env, lhs_val, rhs_val),
Builtin::List(elem) => build_list_eq( Builtin::List(elem) => build_list_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
&Layout::Builtin(*builtin), &Layout::Builtin(*builtin),
*elem, *elem,
@ -137,6 +143,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
fn build_eq<'a, 'ctx, 'env>( fn build_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>,
@ -144,8 +151,8 @@ fn build_eq<'a, 'ctx, 'env>(
rhs_layout: &Layout<'a>, rhs_layout: &Layout<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let lhs_layout = &lhs_layout.runtime_representation(env.layout_interner); let lhs_layout = &lhs_layout.runtime_representation(layout_interner);
let rhs_layout = &rhs_layout.runtime_representation(env.layout_interner); let rhs_layout = &rhs_layout.runtime_representation(layout_interner);
if lhs_layout != rhs_layout { if lhs_layout != rhs_layout {
panic!( panic!(
"Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}", "Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}",
@ -154,12 +161,19 @@ fn build_eq<'a, 'ctx, 'env>(
} }
match lhs_layout { match lhs_layout {
Layout::Builtin(builtin) => { Layout::Builtin(builtin) => build_eq_builtin(
build_eq_builtin(env, layout_ids, lhs_val, rhs_val, builtin, when_recursive) env,
} layout_interner,
layout_ids,
lhs_val,
rhs_val,
builtin,
when_recursive,
),
Layout::Struct { field_layouts, .. } => build_struct_eq( Layout::Struct { field_layouts, .. } => build_struct_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
field_layouts, field_layouts,
when_recursive, when_recursive,
@ -171,6 +185,7 @@ fn build_eq<'a, 'ctx, 'env>(
Layout::Union(union_layout) => build_tag_eq( Layout::Union(union_layout) => build_tag_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
union_layout, union_layout,
@ -180,6 +195,7 @@ fn build_eq<'a, 'ctx, 'env>(
Layout::Boxed(inner_layout) => build_box_eq( Layout::Boxed(inner_layout) => build_box_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
lhs_layout, lhs_layout,
@ -196,7 +212,7 @@ fn build_eq<'a, 'ctx, 'env>(
WhenRecursive::Loop(union_layout) => { WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(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 // cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast( let field1_cast = env.builder.build_pointer_cast(
@ -213,6 +229,7 @@ fn build_eq<'a, 'ctx, 'env>(
build_tag_eq( build_tag_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
WhenRecursive::Loop(union_layout), WhenRecursive::Loop(union_layout),
&union_layout, &union_layout,
@ -226,6 +243,7 @@ fn build_eq<'a, 'ctx, 'env>(
fn build_neq_builtin<'a, 'ctx, 'env>( fn build_neq_builtin<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>,
@ -297,6 +315,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
Builtin::List(elem) => { Builtin::List(elem) => {
let is_equal = build_list_eq( let is_equal = build_list_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
&Layout::Builtin(*builtin), &Layout::Builtin(*builtin),
*elem, *elem,
@ -315,6 +334,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
fn build_neq<'a, 'ctx, 'env>( fn build_neq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>, lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>, rhs_val: BasicValueEnum<'ctx>,
@ -330,13 +350,20 @@ fn build_neq<'a, 'ctx, 'env>(
} }
match lhs_layout { match lhs_layout {
Layout::Builtin(builtin) => { Layout::Builtin(builtin) => build_neq_builtin(
build_neq_builtin(env, layout_ids, lhs_val, rhs_val, builtin, when_recursive) env,
} layout_interner,
layout_ids,
lhs_val,
rhs_val,
builtin,
when_recursive,
),
Layout::Struct { field_layouts, .. } => { Layout::Struct { field_layouts, .. } => {
let is_equal = build_struct_eq( let is_equal = build_struct_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
field_layouts, field_layouts,
when_recursive, when_recursive,
@ -353,6 +380,7 @@ fn build_neq<'a, 'ctx, 'env>(
Layout::Union(union_layout) => { Layout::Union(union_layout) => {
let is_equal = build_tag_eq( let is_equal = build_tag_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
union_layout, union_layout,
@ -369,6 +397,7 @@ fn build_neq<'a, 'ctx, 'env>(
Layout::Boxed(inner_layout) => { Layout::Boxed(inner_layout) => {
let is_equal = build_box_eq( let is_equal = build_box_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
lhs_layout, lhs_layout,
@ -392,6 +421,7 @@ fn build_neq<'a, 'ctx, 'env>(
fn build_list_eq<'a, 'ctx, 'env>( fn build_list_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
list_layout: &Layout<'a>, list_layout: &Layout<'a>,
element_layout: InLayout<'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 di_location = env.builder.get_current_debug_location().unwrap();
let symbol = Symbol::LIST_EQ; 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 element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
let fn_name = layout_ids let fn_name = layout_ids
.get(symbol, &element_layout) .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()) { let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value, Some(function_value) => function_value,
None => { 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( let function_value = crate::llvm::refcounting::build_header_help(
env, env,
@ -423,6 +453,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
build_list_eq_help( build_list_eq_help(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
function_value, function_value,
@ -447,6 +478,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
fn build_list_eq_help<'a, 'ctx, 'env>( fn build_list_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -509,7 +541,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(then_block); env.builder.position_at_end(then_block);
let builder = env.builder; 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 ptr_type = element_type.ptr_type(AddressSpace::Generic);
let ptr1 = load_list_ptr(env.builder, list1, ptr_type); let ptr1 = load_list_ptr(env.builder, list1, ptr_type);
let ptr2 = load_list_ptr(env.builder, list2, 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 { let elem_ptr = unsafe {
builder.new_build_in_bounds_gep(element_type, ptr1, &[curr_index], "load_index") 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 elem2 = {
let elem_ptr = unsafe { let elem_ptr = unsafe {
builder.new_build_in_bounds_gep(element_type, ptr2, &[curr_index], "load_index") 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( let are_equal = build_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
elem1, elem1,
elem2, elem2,
@ -605,6 +638,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
fn build_struct_eq<'a, 'ctx, 'env>( fn build_struct_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
field_layouts: &'a [Layout<'a>], field_layouts: &'a [Layout<'a>],
when_recursive: WhenRecursive<'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()) { let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value, Some(function_value) => function_value,
None => { 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( let function_value = crate::llvm::refcounting::build_header_help(
env, env,
@ -635,6 +669,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
build_struct_eq_help( build_struct_eq_help(
env, env,
layout_interner,
layout_ids, layout_ids,
function_value, function_value,
when_recursive, when_recursive,
@ -659,6 +694,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
fn build_struct_eq_help<'a, 'ctx, 'env>( fn build_struct_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
@ -727,7 +763,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
WhenRecursive::Loop(union_layout) => { WhenRecursive::Loop(union_layout) => {
let field_layout = Layout::Union(*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 // cast the i64 pointer to a pointer to block of memory
let field1_cast = env.builder.build_pointer_cast( let field1_cast = env.builder.build_pointer_cast(
@ -744,6 +780,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
build_eq( build_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
field1_cast.into(), field1_cast.into(),
field2_cast.into(), field2_cast.into(),
@ -755,11 +792,14 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
} }
} }
} else { } 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( build_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
use_roc_value(env, *field_layout, field1, "field1"), lhs,
use_roc_value(env, *field_layout, field2, "field2"), rhs,
field_layout, field_layout,
field_layout, field_layout,
when_recursive, when_recursive,
@ -791,6 +831,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
fn build_tag_eq<'a, 'ctx, 'env>( fn build_tag_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
union_layout: &UnionLayout<'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()) { let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value, Some(function_value) => function_value,
None => { 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( let function_value = crate::llvm::refcounting::build_header_help(
env, env,
@ -820,6 +861,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
build_tag_eq_help( build_tag_eq_help(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
function_value, function_value,
@ -844,6 +886,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
fn build_tag_eq_help<'a, 'ctx, 'env>( fn build_tag_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -924,8 +967,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(compare_tag_ids); env.builder.position_at_end(compare_tag_ids);
let id1 = get_tag_id(env, parent, union_layout, tag1); let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
let id2 = get_tag_id(env, parent, union_layout, tag2); 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 // clear the tag_id so we get a pointer to the actual data
let tag1 = tag1.into_pointer_value(); let tag1 = tag1.into_pointer_value();
@ -952,6 +995,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct( let answer = eq_ptr_to_struct(
env, env,
layout_interner,
layout_ids, layout_ids,
union_layout, union_layout,
Some(when_recursive), Some(when_recursive),
@ -994,8 +1038,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(compare_tag_ids); env.builder.position_at_end(compare_tag_ids);
let id1 = get_tag_id(env, parent, union_layout, tag1); let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
let id2 = get_tag_id(env, parent, union_layout, tag2); 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 // 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()); 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( let answer = eq_ptr_to_struct(
env, env,
layout_interner,
layout_ids, layout_ids,
union_layout, union_layout,
None, None,
@ -1082,6 +1127,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct( let answer = eq_ptr_to_struct(
env, env,
layout_interner,
layout_ids, layout_ids,
union_layout, union_layout,
None, None,
@ -1150,8 +1196,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
env.builder.position_at_end(compare_other); env.builder.position_at_end(compare_other);
let id1 = get_tag_id(env, parent, union_layout, tag1); let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
let id2 = get_tag_id(env, parent, union_layout, tag2); 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 // 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()); 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( let answer = eq_ptr_to_struct(
env, env,
layout_interner,
layout_ids, layout_ids,
union_layout, union_layout,
None, None,
@ -1217,6 +1264,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
let answer = eq_ptr_to_struct( let answer = eq_ptr_to_struct(
env, env,
layout_interner,
layout_ids, layout_ids,
union_layout, union_layout,
None, None,
@ -1232,6 +1280,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
fn eq_ptr_to_struct<'a, 'ctx, 'env>( fn eq_ptr_to_struct<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
union_layout: &UnionLayout<'a>, union_layout: &UnionLayout<'a>,
opt_when_recursive: Option<WhenRecursive<'a>>, opt_when_recursive: Option<WhenRecursive<'a>>,
@ -1241,7 +1290,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let struct_layout = Layout::struct_no_name_order(field_layouts); 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()); debug_assert!(wrapper_type.is_struct_type());
// cast the opaque pointer to a pointer of the correct shape // 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( build_struct_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
field_layouts, field_layouts,
opt_when_recursive.unwrap_or(WhenRecursive::Loop(*union_layout)), 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>( fn build_box_eq<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
box_layout: &Layout<'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()) { let function = match env.module.get_function(fn_name.as_str()) {
Some(function_value) => function_value, Some(function_value) => function_value,
None => { 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( let function_value = crate::llvm::refcounting::build_header_help(
env, env,
@ -1311,6 +1362,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
build_box_eq_help( build_box_eq_help(
env, env,
layout_interner,
layout_ids, layout_ids,
when_recursive, when_recursive,
function_value, function_value,
@ -1335,6 +1387,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
fn build_box_eq_help<'a, 'ctx, 'env>( fn build_box_eq_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>, when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -1402,13 +1455,14 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
let box1 = box1.into_pointer_value(); let box1 = box1.into_pointer_value();
let box2 = box2.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 value1 = load_roc_value(env, layout_interner, *inner_layout, box1, "load_box1");
let value2 = load_roc_value(env, *inner_layout, box2, "load_box2"); let value2 = load_roc_value(env, layout_interner, *inner_layout, box2, "load_box2");
let is_equal = build_eq( let is_equal = build_eq(
env, env,
layout_interner,
layout_ids, layout_ids,
value1, value1,
value2, value2,

View file

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

View file

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

View file

@ -13,7 +13,7 @@ use roc_intern::Interner;
use roc_module::{low_level::LowLevel, symbol::Symbol}; use roc_module::{low_level::LowLevel, symbol::Symbol};
use roc_mono::{ use roc_mono::{
ir::HigherOrderLowLevel, ir::HigherOrderLowLevel,
layout::{Builtin, LambdaSet, Layout, LayoutIds}, layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner},
}; };
use roc_target::PtrWidth; use roc_target::PtrWidth;
@ -62,6 +62,7 @@ macro_rules! list_element_layout {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(crate) fn run_low_level<'a, 'ctx, 'env>( pub(crate) fn run_low_level<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
@ -256,7 +257,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
); );
let roc_return_type = 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( let roc_return_alloca = env.builder.build_pointer_cast(
zig_return_alloca, zig_return_alloca,
@ -264,7 +266,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
"cast_to_roc", "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( call_bitcode_fn_fixing_for_convention(
env, env,
layout_interner,
bitcode_return_type, bitcode_return_type,
&[string], &[string],
layout, 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 // 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(); let actual_type = result.get_type();
if expected_type != actual_type { if expected_type != actual_type {
@ -487,7 +496,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
bitcode::STR_GET_SCALAR_UNSAFE, 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( let cast_result = env.builder.build_pointer_cast(
result, result,
return_type.ptr_type(AddressSpace::Generic), 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() { match env.target_info.ptr_width() {
PtrWidth::Bytes8 => result, PtrWidth::Bytes8 => result,
PtrWidth::Bytes4 => { 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") 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; let result_layout = *layout;
list_with_capacity( list_with_capacity(
env, env,
layout_interner,
list_len.into_int_value(), list_len.into_int_value(),
list_element_layout!(result_layout), 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); 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 => { ListAppendUnsafe => {
// List.appendUnsafe : List elem, elem -> List elem // 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 original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]); 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 => { ListPrepend => {
// List.prepend : List elem, elem -> List elem // 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 original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]); 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 => { ListReserve => {
// List.reserve : List elem, Nat -> List elem // 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 element_layout = list_element_layout!(list_layout);
let spare = load_symbol(scope, &args[1]); 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 => { ListSwap => {
// List.swap : List elem, Nat, Nat -> List elem // 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); let element_layout = list_element_layout!(list_layout);
list_swap( list_swap(
env, env,
layout_interner,
original_wrapper, original_wrapper,
index_1.into_int_value(), index_1.into_int_value(),
index_2.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); let element_layout = list_element_layout!(list_layout);
list_sublist( list_sublist(
env, env,
layout_interner,
layout_ids, layout_ids,
original_wrapper, original_wrapper,
start.into_int_value(), 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); let element_layout = list_element_layout!(list_layout);
list_drop_at( list_drop_at(
env, env,
layout_interner,
layout_ids, layout_ids,
original_wrapper, original_wrapper,
count.into_int_value(), count.into_int_value(),
@ -763,6 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
list_get_unsafe( list_get_unsafe(
env, env,
layout_interner,
layout_ids, layout_ids,
*list_element_layout!(list_layout), *list_element_layout!(list_layout),
element_index.into_int_value(), element_index.into_int_value(),
@ -774,6 +801,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
list_replace_unsafe( list_replace_unsafe(
env, env,
layout_interner,
layout_ids, layout_ids,
list, list,
index.into_int_value(), 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); let int_type = convert::int_type_from_int_width(env, *int_width);
build_int_unary_op( build_int_unary_op(
env, env,
layout_interner,
parent, parent,
arg.into_int_value(), arg.into_int_value(),
*int_width, *int_width,
@ -1033,7 +1062,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
NumIntCast => { NumIntCast => {
arguments!(arg); 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(); let to_signed = intwidth_from_layout(*layout).is_signed();
env.builder env.builder
@ -1047,7 +1076,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::Int(width)) => { Layout::Builtin(Builtin::Int(width)) => {
// Converting from int to float // Converting from int to float
let int_val = arg.into_int_value(); 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() { if width.is_signed() {
env.builder env.builder
@ -1061,7 +1091,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
} }
Layout::Builtin(Builtin::Float(_)) => { Layout::Builtin(Builtin::Float(_)) => {
// Converting from float to float - e.g. F64 to F32, or vice versa // 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 env.builder
.build_float_cast(arg.into_float_value(), dest, "cast_float_to_float") .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 => { Eq => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); 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 => { NotEq => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout)); 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 => { And => {
// The (&&) operator // The (&&) operator
@ -1137,13 +1184,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
unreachable!("Not used in LLVM backend: {:?}", op); 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 => { 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() basic_type.const_zero()
} }
RocReturn::ByPointer => { 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"); let ptr = env.builder.build_alloca(basic_type, "unreachable_alloca");
env.builder.build_store(ptr, basic_type.const_zero()); 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>( fn build_int_unary_op<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
parent: FunctionValue<'ctx>, parent: FunctionValue<'ctx>,
arg: IntValue<'ctx>, arg: IntValue<'ctx>,
arg_width: IntWidth, 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. || // Or if the two types are the same, they trivially fit.
arg_width == target_int_width; arg_width == target_int_width;
let return_type = let return_type = convert::basic_type_from_layout(env, layout_interner, return_layout)
convert::basic_type_from_layout(env, return_layout).into_struct_type(); .into_struct_type();
if arg_always_fits_in_target { if arg_always_fits_in_target {
// This is guaranteed to succeed so we can just make it an int cast and let LLVM // 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, intrinsic,
); );
let roc_return_type = basic_type_from_layout(env, return_layout) let roc_return_type =
.ptr_type(AddressSpace::Generic); basic_type_from_layout(env, layout_interner, return_layout)
.ptr_type(AddressSpace::Generic);
let roc_return_alloca = env.builder.build_pointer_cast( let roc_return_alloca = env.builder.build_pointer_cast(
zig_return_alloca, zig_return_alloca,
@ -1967,7 +2016,13 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
"cast_to_roc", "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( call_bitcode_fn_fixing_for_convention(
env, env,
layout_interner,
bitcode_return_type, bitcode_return_type,
&[arg.into()], &[arg.into()],
return_layout, return_layout,
@ -2221,6 +2277,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>( pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>, env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>, layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>, scope: &Scope<'a, 'ctx>,
return_layout: &Layout<'a>, 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(element_layout)),
Layout::Builtin(Builtin::List(result_layout)), Layout::Builtin(Builtin::List(result_layout)),
) => { ) => {
let element_layout = env.layout_interner.get(*element_layout); let element_layout = layout_interner.get(*element_layout);
let result_layout = env.layout_interner.get(*result_layout); let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[*element_layout]; let argument_layouts = &[*element_layout];
let roc_function_call = roc_function_call( let roc_function_call = roc_function_call(
env, env,
layout_interner,
layout_ids, layout_ids,
function, function,
closure, closure,
@ -2292,7 +2350,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
*result_layout, *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"), _ => 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(element2_layout)),
Layout::Builtin(Builtin::List(result_layout)), Layout::Builtin(Builtin::List(result_layout)),
) => { ) => {
let element1_layout = env.layout_interner.get(*element1_layout); let element1_layout = layout_interner.get(*element1_layout);
let element2_layout = env.layout_interner.get(*element2_layout); let element2_layout = layout_interner.get(*element2_layout);
let result_layout = env.layout_interner.get(*result_layout); let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[*element1_layout, *element2_layout]; let argument_layouts = &[*element1_layout, *element2_layout];
let roc_function_call = roc_function_call( let roc_function_call = roc_function_call(
env, env,
layout_interner,
layout_ids, layout_ids,
function, function,
closure, closure,
@ -2328,6 +2394,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_map2( list_map2(
env, env,
layout_interner,
layout_ids, layout_ids,
roc_function_call, roc_function_call,
list1, 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(element3_layout)),
Layout::Builtin(Builtin::List(result_layout)), Layout::Builtin(Builtin::List(result_layout)),
) => { ) => {
let element1_layout = env.layout_interner.get(*element1_layout); let element1_layout = layout_interner.get(*element1_layout);
let element2_layout = env.layout_interner.get(*element2_layout); let element2_layout = layout_interner.get(*element2_layout);
let element3_layout = env.layout_interner.get(*element3_layout); let element3_layout = layout_interner.get(*element3_layout);
let result_layout = env.layout_interner.get(*result_layout); let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[*element1_layout, *element2_layout, *element3_layout]; let argument_layouts = &[*element1_layout, *element2_layout, *element3_layout];
let roc_function_call = roc_function_call( let roc_function_call = roc_function_call(
env, env,
layout_interner,
layout_ids, layout_ids,
function, function,
closure, closure,
@ -2374,6 +2442,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_map3( list_map3(
env, env,
layout_interner,
layout_ids, layout_ids,
roc_function_call, roc_function_call,
list1, 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(element4_layout)),
Layout::Builtin(Builtin::List(result_layout)), Layout::Builtin(Builtin::List(result_layout)),
) => { ) => {
let element1_layout = env.layout_interner.get(*element1_layout); let element1_layout = layout_interner.get(*element1_layout);
let element2_layout = env.layout_interner.get(*element2_layout); let element2_layout = layout_interner.get(*element2_layout);
let element3_layout = env.layout_interner.get(*element3_layout); let element3_layout = layout_interner.get(*element3_layout);
let element4_layout = env.layout_interner.get(*element4_layout); let element4_layout = layout_interner.get(*element4_layout);
let result_layout = env.layout_interner.get(*result_layout); let result_layout = layout_interner.get(*result_layout);
let argument_layouts = &[ let argument_layouts = &[
*element1_layout, *element1_layout,
@ -2425,6 +2494,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let roc_function_call = roc_function_call( let roc_function_call = roc_function_call(
env, env,
layout_interner,
layout_ids, layout_ids,
function, function,
closure, closure,
@ -2436,6 +2506,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_map4( list_map4(
env, env,
layout_interner,
layout_ids, layout_ids,
roc_function_call, roc_function_call,
list1, list1,
@ -2462,17 +2533,23 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
Layout::Builtin(Builtin::List(element_layout)) => { Layout::Builtin(Builtin::List(element_layout)) => {
use crate::llvm::bitcode::build_compare_wrapper; 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 argument_layouts = &[*element_layout, *element_layout];
let compare_wrapper = let compare_wrapper = build_compare_wrapper(
build_compare_wrapper(env, function, closure_layout, element_layout) env,
.as_global_value() layout_interner,
.as_pointer_value(); function,
closure_layout,
element_layout,
)
.as_global_value()
.as_pointer_value();
let roc_function_call = roc_function_call( let roc_function_call = roc_function_call(
env, env,
layout_interner,
layout_ids, layout_ids,
function, function,
closure, closure,
@ -2484,6 +2561,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list_sort_with( list_sort_with(
env, env,
layout_interner,
roc_function_call, roc_function_call,
compare_wrapper, compare_wrapper,
list, list,

View file

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