mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Push mutable layout interner through llvm backend
This commit is contained in:
parent
e4b5252e51
commit
512a1721ae
8 changed files with 1289 additions and 555 deletions
|
@ -17,7 +17,7 @@ use inkwell::values::{
|
|||
use inkwell::AddressSpace;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds};
|
||||
use roc_mono::layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner};
|
||||
|
||||
use super::build::{create_entry_block_alloca, BuilderExt};
|
||||
use super::convert::zig_list_type;
|
||||
|
@ -95,13 +95,14 @@ fn call_bitcode_fn_help<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
bitcode_return_type: StructType<'ctx>,
|
||||
args: &[BasicValueEnum<'ctx>],
|
||||
return_layout: &Layout<'_>,
|
||||
return_layout: &Layout<'a>,
|
||||
fn_name: &str,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
// Calling zig bitcode, so we must follow C calling conventions.
|
||||
let cc_return = to_cc_return(env, return_layout);
|
||||
let cc_return = to_cc_return(env, layout_interner, return_layout);
|
||||
match cc_return {
|
||||
CCReturn::Return => {
|
||||
// We'll get a return value
|
||||
|
@ -109,7 +110,7 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
|
|||
}
|
||||
CCReturn::ByPointer => {
|
||||
// We need to pass the return value by pointer.
|
||||
let roc_return_type = basic_type_from_layout(env, return_layout);
|
||||
let roc_return_type = basic_type_from_layout(env, layout_interner, return_layout);
|
||||
|
||||
let cc_return_type: BasicTypeEnum<'ctx> = bitcode_return_type.into();
|
||||
|
||||
|
@ -164,6 +165,7 @@ const ARGUMENT_SYMBOLS: [Symbol; 8] = [
|
|||
|
||||
pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
function: FunctionValue<'ctx>,
|
||||
closure_data_layout: LambdaSet<'a>,
|
||||
argument_layouts: &[Layout<'a>],
|
||||
|
@ -178,6 +180,7 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
|
|||
Some(function_value) => function_value,
|
||||
None => build_transform_caller_help(
|
||||
env,
|
||||
layout_interner,
|
||||
function,
|
||||
closure_data_layout,
|
||||
argument_layouts,
|
||||
|
@ -189,6 +192,7 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_transform_caller_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
roc_function: FunctionValue<'ctx>,
|
||||
closure_data_layout: LambdaSet<'a>,
|
||||
argument_layouts: &[Layout<'a>],
|
||||
|
@ -237,7 +241,8 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
|
|||
bumpalo::collections::Vec::with_capacity_in(arguments.len(), env.arena);
|
||||
|
||||
for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) {
|
||||
let basic_type = basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
|
||||
let basic_type =
|
||||
basic_type_from_layout(env, layout_interner, layout).ptr_type(AddressSpace::Generic);
|
||||
|
||||
let cast_ptr = env.builder.build_pointer_cast(
|
||||
argument_ptr.into_pointer_value(),
|
||||
|
@ -245,28 +250,36 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
|
|||
"cast_ptr_to_tag_build_transform_caller_help",
|
||||
);
|
||||
|
||||
let argument = load_roc_value(env, *layout, cast_ptr, "zig_helper_load_opaque");
|
||||
let argument = load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*layout,
|
||||
cast_ptr,
|
||||
"zig_helper_load_opaque",
|
||||
);
|
||||
|
||||
arguments_cast.push(argument);
|
||||
}
|
||||
|
||||
match (
|
||||
closure_data_layout
|
||||
.is_represented(env.layout_interner)
|
||||
.is_represented(layout_interner)
|
||||
.is_some(),
|
||||
closure_data_layout.runtime_representation(env.layout_interner),
|
||||
closure_data_layout.runtime_representation(layout_interner),
|
||||
) {
|
||||
(false, _) => {
|
||||
// the function doesn't expect a closure argument, nothing to add
|
||||
}
|
||||
(true, layout) => {
|
||||
let closure_type = basic_type_from_layout(env, &layout).ptr_type(AddressSpace::Generic);
|
||||
let closure_type = basic_type_from_layout(env, layout_interner, &layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let closure_cast =
|
||||
env.builder
|
||||
.build_pointer_cast(closure_ptr, closure_type, "cast_opaque_closure");
|
||||
|
||||
let closure_data = load_roc_value(env, layout, closure_cast, "load_closure");
|
||||
let closure_data =
|
||||
load_roc_value(env, layout_interner, layout, closure_cast, "load_closure");
|
||||
|
||||
arguments_cast.push(closure_data);
|
||||
}
|
||||
|
@ -274,6 +287,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
|
|||
|
||||
let result = crate::llvm::build::call_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
&result_layout,
|
||||
arguments_cast.as_slice(),
|
||||
|
@ -284,7 +298,13 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
|
|||
.unwrap()
|
||||
.into_pointer_value();
|
||||
|
||||
crate::llvm::build::store_roc_value_opaque(env, result_layout, result_u8_ptr, result);
|
||||
crate::llvm::build::store_roc_value_opaque(
|
||||
env,
|
||||
layout_interner,
|
||||
result_layout,
|
||||
result_u8_ptr,
|
||||
result,
|
||||
);
|
||||
env.builder.build_return(None);
|
||||
|
||||
env.builder.position_at_end(block);
|
||||
|
@ -303,31 +323,35 @@ enum Mode {
|
|||
/// a function that accepts two arguments: the value to increment, and an amount to increment by
|
||||
pub fn build_inc_n_wrapper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layout: &Layout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
build_rc_wrapper(env, layout_ids, layout, Mode::IncN)
|
||||
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::IncN)
|
||||
}
|
||||
|
||||
/// a function that accepts two arguments: the value to increment; increments by 1
|
||||
pub fn build_inc_wrapper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layout: &Layout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
build_rc_wrapper(env, layout_ids, layout, Mode::Inc)
|
||||
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Inc)
|
||||
}
|
||||
|
||||
pub fn build_dec_wrapper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layout: &Layout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
build_rc_wrapper(env, layout_ids, layout, Mode::Dec)
|
||||
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Dec)
|
||||
}
|
||||
|
||||
fn build_rc_wrapper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layout: &Layout<'a>,
|
||||
rc_operation: Mode,
|
||||
|
@ -384,7 +408,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
|
|||
|
||||
generic_value_ptr.set_name(Symbol::ARG_1.as_str(&env.interns));
|
||||
|
||||
let value_type = basic_type_from_layout(env, layout);
|
||||
let value_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let value_ptr_type = value_type.ptr_type(AddressSpace::Generic);
|
||||
let value_ptr =
|
||||
env.builder
|
||||
|
@ -393,7 +417,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
|
|||
// even though this looks like a `load_roc_value`, that gives segfaults in practice.
|
||||
// I suspect it has something to do with the lifetime of the alloca that is created by
|
||||
// `load_roc_value`
|
||||
let value = if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
|
||||
let value = if layout.is_passed_by_reference(layout_interner, env.target_info) {
|
||||
value_ptr.into()
|
||||
} else {
|
||||
env.builder
|
||||
|
@ -403,16 +427,16 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
|
|||
match rc_operation {
|
||||
Mode::Inc => {
|
||||
let n = 1;
|
||||
increment_refcount_layout(env, layout_ids, n, value, layout);
|
||||
increment_refcount_layout(env, layout_interner, layout_ids, n, value, layout);
|
||||
}
|
||||
Mode::IncN => {
|
||||
let n = it.next().unwrap().into_int_value();
|
||||
n.set_name(Symbol::ARG_2.as_str(&env.interns));
|
||||
|
||||
increment_n_refcount_layout(env, layout_ids, n, value, layout);
|
||||
increment_n_refcount_layout(env, layout_interner, layout_ids, n, value, layout);
|
||||
}
|
||||
Mode::Dec => {
|
||||
decrement_refcount_layout(env, layout_ids, value, layout);
|
||||
decrement_refcount_layout(env, layout_interner, layout_ids, value, layout);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,6 +455,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn build_eq_wrapper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layout: &Layout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
|
@ -474,7 +499,8 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
|
|||
value_ptr1.set_name(Symbol::ARG_1.as_str(&env.interns));
|
||||
value_ptr2.set_name(Symbol::ARG_2.as_str(&env.interns));
|
||||
|
||||
let value_type = basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
|
||||
let value_type = basic_type_from_layout(env, layout_interner, layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let value_cast1 = env
|
||||
.builder
|
||||
|
@ -485,11 +511,18 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
|
|||
.build_pointer_cast(value_ptr2, value_type, "load_opaque");
|
||||
|
||||
// load_roc_value(env, *element_layout, elem_ptr, "get_elem")
|
||||
let value1 = load_roc_value(env, *layout, value_cast1, "load_opaque");
|
||||
let value2 = load_roc_value(env, *layout, value_cast2, "load_opaque");
|
||||
let value1 = load_roc_value(env, layout_interner, *layout, value_cast1, "load_opaque");
|
||||
let value2 = load_roc_value(env, layout_interner, *layout, value_cast2, "load_opaque");
|
||||
|
||||
let result =
|
||||
crate::llvm::compare::generic_eq(env, layout_ids, value1, value2, layout, layout);
|
||||
let result = crate::llvm::compare::generic_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
value1,
|
||||
value2,
|
||||
layout,
|
||||
layout,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&result));
|
||||
|
||||
|
@ -506,6 +539,7 @@ pub fn build_eq_wrapper<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn build_compare_wrapper<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
roc_function: FunctionValue<'ctx>,
|
||||
closure_data_layout: LambdaSet<'a>,
|
||||
layout: &Layout<'a>,
|
||||
|
@ -555,7 +589,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
|
|||
value_ptr1.set_name(Symbol::ARG_2.as_str(&env.interns));
|
||||
value_ptr2.set_name(Symbol::ARG_3.as_str(&env.interns));
|
||||
|
||||
let value_type = basic_type_from_layout(env, layout);
|
||||
let value_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let value_ptr_type = value_type.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let value_cast1 =
|
||||
|
@ -575,8 +609,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
|
|||
|
||||
let default = [value1.into(), value2.into()];
|
||||
|
||||
let arguments_cast =
|
||||
match closure_data_layout.runtime_representation(env.layout_interner) {
|
||||
let arguments_cast = match closure_data_layout.runtime_representation(layout_interner) {
|
||||
Layout::Struct {
|
||||
field_layouts: &[], ..
|
||||
} => {
|
||||
|
@ -584,7 +617,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
|
|||
&default
|
||||
}
|
||||
other => {
|
||||
let closure_type = basic_type_from_layout(env, &other);
|
||||
let closure_type = basic_type_from_layout(env, layout_interner, &other);
|
||||
let closure_ptr_type = closure_type.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let closure_cast = env.builder.build_pointer_cast(
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -13,7 +13,7 @@ use morphic_lib::UpdateMode;
|
|||
use roc_builtins::bitcode;
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds};
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner};
|
||||
|
||||
use super::bitcode::{call_list_bitcode_fn, BitcodeReturns};
|
||||
use super::build::{
|
||||
|
@ -63,14 +63,15 @@ pub(crate) fn pass_update_mode<'a, 'ctx, 'env>(
|
|||
|
||||
fn pass_element_as_opaque<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
layout: Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_type = basic_type_from_layout(env, &layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let element_ptr = env
|
||||
.builder
|
||||
.build_alloca(element_type, "element_to_pass_as_opaque");
|
||||
store_roc_value(env, layout, element_ptr, element);
|
||||
store_roc_value(env, layout_interner, layout, element_ptr, element);
|
||||
|
||||
env.builder
|
||||
.build_pointer_cast(
|
||||
|
@ -83,11 +84,12 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
|
|||
|
||||
pub(crate) fn layout_width<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
env.ptr_int()
|
||||
.const_int(
|
||||
layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
)
|
||||
.into()
|
||||
|
@ -108,17 +110,18 @@ pub(crate) fn pass_as_opaque<'a, 'ctx, 'env>(
|
|||
|
||||
pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
capacity: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
&[],
|
||||
&[
|
||||
capacity.into(),
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
BitcodeReturns::List,
|
||||
bitcode::LIST_WITH_CAPACITY,
|
||||
|
@ -127,6 +130,7 @@ pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
|
|||
|
||||
pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
elem_index: IntValue<'ctx>,
|
||||
|
@ -134,8 +138,8 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
|
|||
) -> BasicValueEnum<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let elem_type = basic_type_from_layout(env, element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let elem_type = basic_type_from_layout(env, layout_interner, element_layout);
|
||||
let ptr_type = elem_type.ptr_type(AddressSpace::Generic);
|
||||
// Load the pointer to the array data
|
||||
let array_data_ptr = load_list_ptr(builder, wrapper_struct, ptr_type);
|
||||
|
@ -151,9 +155,15 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
|
|||
)
|
||||
};
|
||||
|
||||
let result = load_roc_value(env, *element_layout, elem_ptr, "list_get_load_element");
|
||||
let result = load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*element_layout,
|
||||
elem_ptr,
|
||||
"list_get_load_element",
|
||||
);
|
||||
|
||||
increment_refcount_layout(env, layout_ids, 1, result, element_layout);
|
||||
increment_refcount_layout(env, layout_interner, layout_ids, 1, result, element_layout);
|
||||
|
||||
result
|
||||
}
|
||||
|
@ -161,19 +171,20 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
|
|||
/// List.reserve : List elem, Nat -> List elem
|
||||
pub(crate) fn list_reserve<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
spare: BasicValueEnum<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
list.into_struct_value(),
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
spare,
|
||||
layout_width(env, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
pass_update_mode(env, update_mode),
|
||||
],
|
||||
bitcode::LIST_RESERVE,
|
||||
|
@ -183,6 +194,7 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
|
|||
/// List.appendUnsafe : List elem, elem -> List elem
|
||||
pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
|
@ -191,8 +203,8 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
|
|||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
pass_element_as_opaque(env, element, *element_layout),
|
||||
layout_width(env, element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
bitcode::LIST_APPEND_UNSAFE,
|
||||
)
|
||||
|
@ -201,6 +213,7 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
|
|||
/// List.prepend : List elem, elem -> List elem
|
||||
pub(crate) fn list_prepend<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
|
@ -209,9 +222,9 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
|
|||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
pass_element_as_opaque(env, element, *element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
bitcode::LIST_PREPEND,
|
||||
)
|
||||
|
@ -220,19 +233,20 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
|
|||
/// List.swap : List elem, Nat, Nat -> List elem
|
||||
pub(crate) fn list_swap<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
index_1: IntValue<'ctx>,
|
||||
index_2: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
index_1.into(),
|
||||
index_2.into(),
|
||||
pass_update_mode(env, update_mode),
|
||||
|
@ -244,20 +258,21 @@ pub(crate) fn list_swap<'a, 'ctx, 'env>(
|
|||
/// List.sublist : List elem, { start : Nat, len : Nat } -> List elem
|
||||
pub(crate) fn list_sublist<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
start: IntValue<'ctx>,
|
||||
len: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
start.into(),
|
||||
len.into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
|
@ -269,19 +284,20 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>(
|
|||
/// List.dropAt : List elem, Nat -> List elem
|
||||
pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
count: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_ids, element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
count.into(),
|
||||
dec_element_fn.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
|
@ -292,6 +308,7 @@ pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
|
|||
/// List.replace_unsafe : List elem, Nat, elem -> { list: List elem, value: elem }
|
||||
pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
_layout_ids: &mut LayoutIds<'a>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
index: IntValue<'ctx>,
|
||||
|
@ -299,7 +316,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
element_layout: &Layout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_type = basic_type_from_layout(env, element_layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
|
||||
let element_ptr = env
|
||||
.builder
|
||||
.build_alloca(element_type, "output_element_as_opaque");
|
||||
|
@ -312,8 +329,8 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
list.into_struct_value(),
|
||||
&[
|
||||
index.into(),
|
||||
pass_element_as_opaque(env, element, *element_layout),
|
||||
layout_width(env, element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
pass_as_opaque(env, element_ptr),
|
||||
],
|
||||
bitcode::LIST_REPLACE_IN_PLACE,
|
||||
|
@ -322,10 +339,10 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
env,
|
||||
list.into_struct_value(),
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
index.into(),
|
||||
pass_element_as_opaque(env, element, *element_layout),
|
||||
layout_width(env, element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
pass_as_opaque(env, element_ptr),
|
||||
],
|
||||
bitcode::LIST_REPLACE,
|
||||
|
@ -339,7 +356,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
|
||||
// the list has the same alignment as a usize / ptr. The element comes first in the struct if
|
||||
// its alignment is bigger than that of a list.
|
||||
let element_align = element_layout.alignment_bytes(env.layout_interner, env.target_info);
|
||||
let element_align = element_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
let element_first = element_align > env.target_info.ptr_width() as u32;
|
||||
|
||||
let fields = if element_first {
|
||||
|
@ -424,6 +441,7 @@ pub(crate) fn destructure<'ctx>(
|
|||
/// List.sortWith : List a, (a, a -> Ordering) -> List a
|
||||
pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
compare_wrapper: PointerValue<'ctx>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
|
@ -437,8 +455,8 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
bitcode::LIST_SORT_WITH,
|
||||
)
|
||||
|
@ -447,6 +465,7 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
|
|||
/// List.map : List before, (before -> after) -> List after
|
||||
pub(crate) fn list_map<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
|
@ -460,9 +479,9 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(return_layout),
|
||||
layout_width(env, element_layout),
|
||||
layout_width(env, return_layout),
|
||||
env.alignment_intvalue(layout_interner, return_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, return_layout),
|
||||
],
|
||||
bitcode::LIST_MAP,
|
||||
)
|
||||
|
@ -470,6 +489,7 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
|
|||
|
||||
pub(crate) fn list_map2<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list1: BasicValueEnum<'ctx>,
|
||||
|
@ -478,8 +498,8 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
|
|||
element2_layout: &Layout<'a>,
|
||||
return_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout);
|
||||
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
|
||||
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
|
@ -489,10 +509,10 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(return_layout),
|
||||
layout_width(env, element1_layout),
|
||||
layout_width(env, element2_layout),
|
||||
layout_width(env, return_layout),
|
||||
env.alignment_intvalue(layout_interner, return_layout),
|
||||
layout_width(env, layout_interner, element1_layout),
|
||||
layout_width(env, layout_interner, element2_layout),
|
||||
layout_width(env, layout_interner, return_layout),
|
||||
dec_a.as_global_value().as_pointer_value().into(),
|
||||
dec_b.as_global_value().as_pointer_value().into(),
|
||||
],
|
||||
|
@ -503,6 +523,7 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
|
|||
|
||||
pub(crate) fn list_map3<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list1: BasicValueEnum<'ctx>,
|
||||
|
@ -513,9 +534,9 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
|
|||
element3_layout: &Layout<'a>,
|
||||
result_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout);
|
||||
let dec_c = build_dec_wrapper(env, layout_ids, element3_layout);
|
||||
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
|
||||
let dec_c = build_dec_wrapper(env, layout_interner, layout_ids, element3_layout);
|
||||
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
|
@ -529,11 +550,11 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(result_layout),
|
||||
layout_width(env, element1_layout),
|
||||
layout_width(env, element2_layout),
|
||||
layout_width(env, element3_layout),
|
||||
layout_width(env, result_layout),
|
||||
env.alignment_intvalue(layout_interner, result_layout),
|
||||
layout_width(env, layout_interner, element1_layout),
|
||||
layout_width(env, layout_interner, element2_layout),
|
||||
layout_width(env, layout_interner, element3_layout),
|
||||
layout_width(env, layout_interner, result_layout),
|
||||
dec_a.as_global_value().as_pointer_value().into(),
|
||||
dec_b.as_global_value().as_pointer_value().into(),
|
||||
dec_c.as_global_value().as_pointer_value().into(),
|
||||
|
@ -545,6 +566,7 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
|
|||
|
||||
pub(crate) fn list_map4<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list1: BasicValueEnum<'ctx>,
|
||||
|
@ -557,10 +579,10 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
|
|||
element4_layout: &Layout<'a>,
|
||||
result_layout: &Layout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_a = build_dec_wrapper(env, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_ids, element2_layout);
|
||||
let dec_c = build_dec_wrapper(env, layout_ids, element3_layout);
|
||||
let dec_d = build_dec_wrapper(env, layout_ids, element4_layout);
|
||||
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
|
||||
let dec_c = build_dec_wrapper(env, layout_interner, layout_ids, element3_layout);
|
||||
let dec_d = build_dec_wrapper(env, layout_interner, layout_ids, element4_layout);
|
||||
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
|
@ -575,12 +597,12 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
|
|||
pass_as_opaque(env, roc_function_call.data),
|
||||
roc_function_call.inc_n_data.into(),
|
||||
roc_function_call.data_is_owned.into(),
|
||||
env.alignment_intvalue(result_layout),
|
||||
layout_width(env, element1_layout),
|
||||
layout_width(env, element2_layout),
|
||||
layout_width(env, element3_layout),
|
||||
layout_width(env, element4_layout),
|
||||
layout_width(env, result_layout),
|
||||
env.alignment_intvalue(layout_interner, result_layout),
|
||||
layout_width(env, layout_interner, element1_layout),
|
||||
layout_width(env, layout_interner, element2_layout),
|
||||
layout_width(env, layout_interner, element3_layout),
|
||||
layout_width(env, layout_interner, element4_layout),
|
||||
layout_width(env, layout_interner, result_layout),
|
||||
dec_a.as_global_value().as_pointer_value().into(),
|
||||
dec_b.as_global_value().as_pointer_value().into(),
|
||||
dec_c.as_global_value().as_pointer_value().into(),
|
||||
|
@ -594,25 +616,27 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
|
|||
/// List.concat : List elem, List elem -> List elem
|
||||
pub(crate) fn list_concat<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
list1: BasicValueEnum<'ctx>,
|
||||
list2: BasicValueEnum<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
&[list1.into_struct_value(), list2.into_struct_value()],
|
||||
&[
|
||||
env.alignment_intvalue(element_layout),
|
||||
layout_width(env, element_layout),
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
BitcodeReturns::List,
|
||||
bitcode::LIST_CONCAT,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn incrementing_elem_loop<'a, 'ctx, 'env, LoopFn>(
|
||||
pub(crate) fn incrementing_elem_loop<'a, 'r, 'ctx, 'env, LoopFn>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &'r mut STLayoutInterner<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
element_layout: Layout<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
|
@ -621,39 +645,49 @@ pub(crate) fn incrementing_elem_loop<'a, 'ctx, 'env, LoopFn>(
|
|||
mut loop_fn: LoopFn,
|
||||
) -> PointerValue<'ctx>
|
||||
where
|
||||
LoopFn: FnMut(IntValue<'ctx>, BasicValueEnum<'ctx>),
|
||||
LoopFn: FnMut(&'r mut STLayoutInterner<'a>, IntValue<'ctx>, BasicValueEnum<'ctx>),
|
||||
{
|
||||
let builder = env.builder;
|
||||
|
||||
let element_type = basic_type_from_layout(env, &element_layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, &element_layout);
|
||||
|
||||
incrementing_index_loop(env, parent, len, index_name, |index| {
|
||||
incrementing_index_loop(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
len,
|
||||
index_name,
|
||||
|layout_interner, index| {
|
||||
// The pointer to the element in the list
|
||||
let element_ptr =
|
||||
unsafe { builder.new_build_in_bounds_gep(element_type, ptr, &[index], "load_index") };
|
||||
let element_ptr = unsafe {
|
||||
builder.new_build_in_bounds_gep(element_type, ptr, &[index], "load_index")
|
||||
};
|
||||
|
||||
let elem = load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
element_layout,
|
||||
element_ptr,
|
||||
"incrementing_element_loop_load",
|
||||
);
|
||||
|
||||
loop_fn(index, elem);
|
||||
})
|
||||
loop_fn(layout_interner, index, elem);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// This helper simulates a basic for loop, where
|
||||
// and index increments up from 0 to some end value
|
||||
pub(crate) fn incrementing_index_loop<'a, 'ctx, 'env, LoopFn>(
|
||||
pub(crate) fn incrementing_index_loop<'a, 'r, 'ctx, 'env, LoopFn>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &'r mut STLayoutInterner<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
end: IntValue<'ctx>,
|
||||
index_name: &str,
|
||||
mut loop_fn: LoopFn,
|
||||
) -> PointerValue<'ctx>
|
||||
where
|
||||
LoopFn: FnMut(IntValue<'ctx>),
|
||||
LoopFn: FnMut(&'r mut STLayoutInterner<'a>, IntValue<'ctx>),
|
||||
{
|
||||
let ctx = env.context;
|
||||
let builder = env.builder;
|
||||
|
@ -682,7 +716,7 @@ where
|
|||
builder.build_store(index_alloca, next_index);
|
||||
|
||||
// The body of the loop
|
||||
loop_fn(current_index);
|
||||
loop_fn(layout_interner, current_index);
|
||||
|
||||
// #index < end
|
||||
let loop_end_cond = bounds_check_comparison(builder, next_index, end);
|
||||
|
@ -737,19 +771,20 @@ pub(crate) fn load_list_ptr<'ctx>(
|
|||
|
||||
pub(crate) fn allocate_list<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
elem_layout: &Layout<'a>,
|
||||
number_of_elements: IntValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let len_type = env.ptr_int();
|
||||
let elem_bytes = elem_layout.stack_size(env.layout_interner, env.target_info) as u64;
|
||||
let elem_bytes = elem_layout.stack_size(layout_interner, env.target_info) as u64;
|
||||
let bytes_per_element = len_type.const_int(elem_bytes, false);
|
||||
let number_of_data_bytes =
|
||||
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
|
||||
|
||||
let basic_type = basic_type_from_layout(env, elem_layout);
|
||||
let alignment_bytes = elem_layout.alignment_bytes(env.layout_interner, env.target_info);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, elem_layout);
|
||||
let alignment_bytes = elem_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use roc_builtins::bitcode;
|
|||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, UnionLayout};
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner, UnionLayout};
|
||||
|
||||
use super::build::{load_roc_value, use_roc_value, BuilderExt};
|
||||
use super::convert::argument_type_from_union_layout;
|
||||
|
@ -22,6 +22,7 @@ use super::lowlevel::dec_binop_with_unchecked;
|
|||
|
||||
pub fn generic_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
|
@ -30,6 +31,7 @@ pub fn generic_eq<'a, 'ctx, 'env>(
|
|||
) -> BasicValueEnum<'ctx> {
|
||||
build_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
|
@ -41,6 +43,7 @@ pub fn generic_eq<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn generic_neq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
|
@ -49,6 +52,7 @@ pub fn generic_neq<'a, 'ctx, 'env>(
|
|||
) -> BasicValueEnum<'ctx> {
|
||||
build_neq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
|
@ -60,6 +64,7 @@ pub fn generic_neq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_eq_builtin<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
|
@ -125,6 +130,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
||||
Builtin::List(elem) => build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
&Layout::Builtin(*builtin),
|
||||
*elem,
|
||||
|
@ -137,6 +143,7 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
|
@ -144,8 +151,8 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
rhs_layout: &Layout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let lhs_layout = &lhs_layout.runtime_representation(env.layout_interner);
|
||||
let rhs_layout = &rhs_layout.runtime_representation(env.layout_interner);
|
||||
let lhs_layout = &lhs_layout.runtime_representation(layout_interner);
|
||||
let rhs_layout = &rhs_layout.runtime_representation(layout_interner);
|
||||
if lhs_layout != rhs_layout {
|
||||
panic!(
|
||||
"Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}",
|
||||
|
@ -154,12 +161,19 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
match lhs_layout {
|
||||
Layout::Builtin(builtin) => {
|
||||
build_eq_builtin(env, layout_ids, lhs_val, rhs_val, builtin, when_recursive)
|
||||
}
|
||||
Layout::Builtin(builtin) => build_eq_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
builtin,
|
||||
when_recursive,
|
||||
),
|
||||
|
||||
Layout::Struct { field_layouts, .. } => build_struct_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
field_layouts,
|
||||
when_recursive,
|
||||
|
@ -171,6 +185,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
|
||||
Layout::Union(union_layout) => build_tag_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
union_layout,
|
||||
|
@ -180,6 +195,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
|
||||
Layout::Boxed(inner_layout) => build_box_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
|
@ -196,7 +212,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(union_layout);
|
||||
|
||||
let bt = basic_type_from_layout(env, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -213,6 +229,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
|
||||
build_tag_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
WhenRecursive::Loop(union_layout),
|
||||
&union_layout,
|
||||
|
@ -226,6 +243,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_neq_builtin<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
|
@ -297,6 +315,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
Builtin::List(elem) => {
|
||||
let is_equal = build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
&Layout::Builtin(*builtin),
|
||||
*elem,
|
||||
|
@ -315,6 +334,7 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_neq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
|
@ -330,13 +350,20 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
match lhs_layout {
|
||||
Layout::Builtin(builtin) => {
|
||||
build_neq_builtin(env, layout_ids, lhs_val, rhs_val, builtin, when_recursive)
|
||||
}
|
||||
Layout::Builtin(builtin) => build_neq_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
builtin,
|
||||
when_recursive,
|
||||
),
|
||||
|
||||
Layout::Struct { field_layouts, .. } => {
|
||||
let is_equal = build_struct_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
field_layouts,
|
||||
when_recursive,
|
||||
|
@ -353,6 +380,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
Layout::Union(union_layout) => {
|
||||
let is_equal = build_tag_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
union_layout,
|
||||
|
@ -369,6 +397,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
Layout::Boxed(inner_layout) => {
|
||||
let is_equal = build_box_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
|
@ -392,6 +421,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_list_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
list_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
|
@ -403,7 +433,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let symbol = Symbol::LIST_EQ;
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, &element_layout)
|
||||
|
@ -412,7 +442,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let arg_type = basic_type_from_layout(env, list_layout);
|
||||
let arg_type = basic_type_from_layout(env, layout_interner, list_layout);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
|
@ -423,6 +453,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
|
||||
build_list_eq_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
|
@ -447,6 +478,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_list_eq_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -509,7 +541,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
env.builder.position_at_end(then_block);
|
||||
|
||||
let builder = env.builder;
|
||||
let element_type = basic_type_from_layout(env, element_layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
|
||||
let ptr_type = element_type.ptr_type(AddressSpace::Generic);
|
||||
let ptr1 = load_list_ptr(env.builder, list1, ptr_type);
|
||||
let ptr2 = load_list_ptr(env.builder, list2, ptr_type);
|
||||
|
@ -549,18 +581,19 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
let elem_ptr = unsafe {
|
||||
builder.new_build_in_bounds_gep(element_type, ptr1, &[curr_index], "load_index")
|
||||
};
|
||||
load_roc_value(env, *element_layout, elem_ptr, "get_elem")
|
||||
load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem")
|
||||
};
|
||||
|
||||
let elem2 = {
|
||||
let elem_ptr = unsafe {
|
||||
builder.new_build_in_bounds_gep(element_type, ptr2, &[curr_index], "load_index")
|
||||
};
|
||||
load_roc_value(env, *element_layout, elem_ptr, "get_elem")
|
||||
load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem")
|
||||
};
|
||||
|
||||
let are_equal = build_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
elem1,
|
||||
elem2,
|
||||
|
@ -605,6 +638,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_struct_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
field_layouts: &'a [Layout<'a>],
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
|
@ -624,7 +658,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let arg_type = basic_type_from_layout(env, &struct_layout);
|
||||
let arg_type = basic_type_from_layout(env, layout_interner, &struct_layout);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
|
@ -635,6 +669,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
|
||||
build_struct_eq_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function_value,
|
||||
when_recursive,
|
||||
|
@ -659,6 +694,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_struct_eq_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
|
@ -727,7 +763,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
WhenRecursive::Loop(union_layout) => {
|
||||
let field_layout = Layout::Union(*union_layout);
|
||||
|
||||
let bt = basic_type_from_layout(env, &field_layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, &field_layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -744,6 +780,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
build_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
field1_cast.into(),
|
||||
field2_cast.into(),
|
||||
|
@ -755,11 +792,14 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
let lhs = use_roc_value(env, layout_interner, *field_layout, field1, "field1");
|
||||
let rhs = use_roc_value(env, layout_interner, *field_layout, field2, "field2");
|
||||
build_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
use_roc_value(env, *field_layout, field1, "field1"),
|
||||
use_roc_value(env, *field_layout, field2, "field2"),
|
||||
lhs,
|
||||
rhs,
|
||||
field_layout,
|
||||
field_layout,
|
||||
when_recursive,
|
||||
|
@ -791,6 +831,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_tag_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
|
@ -809,7 +850,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let arg_type = argument_type_from_union_layout(env, union_layout);
|
||||
let arg_type = argument_type_from_union_layout(env, layout_interner, union_layout);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
|
@ -820,6 +861,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
|
|||
|
||||
build_tag_eq_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
|
@ -844,6 +886,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_tag_eq_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -924,8 +967,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(compare_tag_ids);
|
||||
|
||||
let id1 = get_tag_id(env, parent, union_layout, tag1);
|
||||
let id2 = get_tag_id(env, parent, union_layout, tag2);
|
||||
let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
|
||||
let id2 = get_tag_id(env, layout_interner, parent, union_layout, tag2);
|
||||
|
||||
// clear the tag_id so we get a pointer to the actual data
|
||||
let tag1 = tag1.into_pointer_value();
|
||||
|
@ -952,6 +995,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
Some(when_recursive),
|
||||
|
@ -994,8 +1038,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(compare_tag_ids);
|
||||
|
||||
let id1 = get_tag_id(env, parent, union_layout, tag1);
|
||||
let id2 = get_tag_id(env, parent, union_layout, tag2);
|
||||
let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
|
||||
let id2 = get_tag_id(env, layout_interner, parent, union_layout, tag2);
|
||||
|
||||
// clear the tag_id so we get a pointer to the actual data
|
||||
let tag1 = tag_pointer_clear_tag_id(env, tag1.into_pointer_value());
|
||||
|
@ -1022,6 +1066,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
|
@ -1082,6 +1127,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
|
@ -1150,8 +1196,8 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(compare_other);
|
||||
|
||||
let id1 = get_tag_id(env, parent, union_layout, tag1);
|
||||
let id2 = get_tag_id(env, parent, union_layout, tag2);
|
||||
let id1 = get_tag_id(env, layout_interner, parent, union_layout, tag1);
|
||||
let id2 = get_tag_id(env, layout_interner, parent, union_layout, tag2);
|
||||
|
||||
// clear the tag_id so we get a pointer to the actual data
|
||||
let tag1 = tag_pointer_clear_tag_id(env, tag1.into_pointer_value());
|
||||
|
@ -1179,6 +1225,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
|
@ -1217,6 +1264,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
let answer = eq_ptr_to_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
None,
|
||||
|
@ -1232,6 +1280,7 @@ fn build_tag_eq_help<'a, 'ctx, 'env>(
|
|||
|
||||
fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
opt_when_recursive: Option<WhenRecursive<'a>>,
|
||||
|
@ -1241,7 +1290,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
) -> IntValue<'ctx> {
|
||||
let struct_layout = Layout::struct_no_name_order(field_layouts);
|
||||
|
||||
let wrapper_type = basic_type_from_layout(env, &struct_layout);
|
||||
let wrapper_type = basic_type_from_layout(env, layout_interner, &struct_layout);
|
||||
debug_assert!(wrapper_type.is_struct_type());
|
||||
|
||||
// cast the opaque pointer to a pointer of the correct shape
|
||||
|
@ -1269,6 +1318,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
|
||||
build_struct_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
field_layouts,
|
||||
opt_when_recursive.unwrap_or(WhenRecursive::Loop(*union_layout)),
|
||||
|
@ -1282,6 +1332,7 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_box_eq<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
box_layout: &Layout<'a>,
|
||||
|
@ -1300,7 +1351,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let arg_type = basic_type_from_layout(env, box_layout);
|
||||
let arg_type = basic_type_from_layout(env, layout_interner, box_layout);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
|
@ -1311,6 +1362,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
|
|||
|
||||
build_box_eq_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
|
@ -1335,6 +1387,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_box_eq_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -1402,13 +1455,14 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
|
|||
let box1 = box1.into_pointer_value();
|
||||
let box2 = box2.into_pointer_value();
|
||||
|
||||
let inner_layout = env.layout_interner.get(inner_layout);
|
||||
let inner_layout = layout_interner.get(inner_layout);
|
||||
|
||||
let value1 = load_roc_value(env, *inner_layout, box1, "load_box1");
|
||||
let value2 = load_roc_value(env, *inner_layout, box2, "load_box2");
|
||||
let value1 = load_roc_value(env, layout_interner, *inner_layout, box1, "load_box1");
|
||||
let value2 = load_roc_value(env, layout_interner, *inner_layout, box2, "load_box2");
|
||||
|
||||
let is_equal = build_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
value1,
|
||||
value2,
|
||||
|
|
|
@ -11,12 +11,13 @@ use roc_target::TargetInfo;
|
|||
|
||||
fn basic_type_from_record<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
fields: &[Layout<'_>],
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
let mut field_types = Vec::with_capacity_in(fields.len(), env.arena);
|
||||
|
||||
for field_layout in fields.iter() {
|
||||
field_types.push(basic_type_from_layout(env, field_layout));
|
||||
field_types.push(basic_type_from_layout(env, layout_interner, field_layout));
|
||||
}
|
||||
|
||||
env.context
|
||||
|
@ -26,6 +27,7 @@ fn basic_type_from_record<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &'env mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'_>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
use Layout::*;
|
||||
|
@ -34,17 +36,19 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
Struct {
|
||||
field_layouts: sorted_fields,
|
||||
..
|
||||
} => basic_type_from_record(env, sorted_fields),
|
||||
LambdaSet(lambda_set) => {
|
||||
basic_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner))
|
||||
}
|
||||
} => basic_type_from_record(env, layout_interner, sorted_fields),
|
||||
LambdaSet(lambda_set) => basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&lambda_set.runtime_representation(layout_interner),
|
||||
),
|
||||
Boxed(inner_layout) => {
|
||||
let inner_layout = env.layout_interner.get(*inner_layout);
|
||||
let inner_type = basic_type_from_layout(env, inner_layout);
|
||||
let inner_layout = layout_interner.get(*inner_layout);
|
||||
let inner_type = basic_type_from_layout(env, layout_interner, inner_layout);
|
||||
|
||||
inner_type.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
Union(union_layout) => basic_type_from_union_layout(env, union_layout),
|
||||
Union(union_layout) => basic_type_from_union_layout(env, layout_interner, union_layout),
|
||||
RecursivePointer => env
|
||||
.context
|
||||
.i64_type()
|
||||
|
@ -57,13 +61,14 @@ pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn struct_type_from_union_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: &UnionLayout<'_>,
|
||||
) -> StructType<'ctx> {
|
||||
use UnionLayout::*;
|
||||
|
||||
match union_layout {
|
||||
NonRecursive(tags) => {
|
||||
RocUnion::tagged_from_slices(env.layout_interner, env.context, tags, env.target_info)
|
||||
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
|
||||
.struct_type()
|
||||
}
|
||||
Recursive(tags)
|
||||
|
@ -71,47 +76,35 @@ pub fn struct_type_from_union_layout<'a, 'ctx, 'env>(
|
|||
other_tags: tags, ..
|
||||
} => {
|
||||
if union_layout.stores_tag_id_as_data(env.target_info) {
|
||||
RocUnion::tagged_from_slices(
|
||||
env.layout_interner,
|
||||
env.context,
|
||||
tags,
|
||||
env.target_info,
|
||||
)
|
||||
RocUnion::tagged_from_slices(layout_interner, env.context, tags, env.target_info)
|
||||
.struct_type()
|
||||
} else {
|
||||
RocUnion::untagged_from_slices(
|
||||
env.layout_interner,
|
||||
env.context,
|
||||
tags,
|
||||
env.target_info,
|
||||
)
|
||||
RocUnion::untagged_from_slices(layout_interner, env.context, tags, env.target_info)
|
||||
.struct_type()
|
||||
}
|
||||
}
|
||||
NullableUnwrapped { other_fields, .. } => RocUnion::untagged_from_slices(
|
||||
env.layout_interner,
|
||||
layout_interner,
|
||||
env.context,
|
||||
&[other_fields],
|
||||
env.target_info,
|
||||
)
|
||||
.struct_type(),
|
||||
NonNullableUnwrapped(fields) => RocUnion::untagged_from_slices(
|
||||
env.layout_interner,
|
||||
env.context,
|
||||
&[fields],
|
||||
env.target_info,
|
||||
)
|
||||
.struct_type(),
|
||||
NonNullableUnwrapped(fields) => {
|
||||
RocUnion::untagged_from_slices(layout_interner, env.context, &[fields], env.target_info)
|
||||
.struct_type()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn basic_type_from_union_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: &UnionLayout<'_>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
use UnionLayout::*;
|
||||
|
||||
let struct_type = struct_type_from_union_layout(env, union_layout);
|
||||
let struct_type = struct_type_from_union_layout(env, layout_interner, union_layout);
|
||||
|
||||
match union_layout {
|
||||
NonRecursive(_) => struct_type.into(),
|
||||
|
@ -153,34 +146,38 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
|
|||
/// is not currently implemented
|
||||
pub fn argument_type_from_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'_>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
use Layout::*;
|
||||
|
||||
match layout {
|
||||
LambdaSet(lambda_set) => {
|
||||
argument_type_from_layout(env, &lambda_set.runtime_representation(env.layout_interner))
|
||||
}
|
||||
Union(union_layout) => argument_type_from_union_layout(env, union_layout),
|
||||
LambdaSet(lambda_set) => argument_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&lambda_set.runtime_representation(layout_interner),
|
||||
),
|
||||
Union(union_layout) => argument_type_from_union_layout(env, layout_interner, union_layout),
|
||||
Builtin(_) => {
|
||||
let base = basic_type_from_layout(env, layout);
|
||||
let base = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
if layout.is_passed_by_reference(env.layout_interner, env.target_info) {
|
||||
if layout.is_passed_by_reference(layout_interner, env.target_info) {
|
||||
base.ptr_type(AddressSpace::Generic).into()
|
||||
} else {
|
||||
base
|
||||
}
|
||||
}
|
||||
other => basic_type_from_layout(env, other),
|
||||
other => basic_type_from_layout(env, layout_interner, other),
|
||||
}
|
||||
}
|
||||
|
||||
/// Non-recursive tag unions are stored on the stack, but passed by-reference
|
||||
pub fn argument_type_from_union_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: &UnionLayout<'_>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
let heap_type = basic_type_from_union_layout(env, union_layout);
|
||||
let heap_type = basic_type_from_union_layout(env, layout_interner, union_layout);
|
||||
|
||||
if let UnionLayout::NonRecursive(_) = union_layout {
|
||||
heap_type.ptr_type(AddressSpace::Generic).into()
|
||||
|
|
|
@ -12,7 +12,7 @@ use roc_builtins::bitcode;
|
|||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::ir::LookupType;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, UnionLayout};
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, STLayoutInterner, UnionLayout};
|
||||
use roc_region::all::Region;
|
||||
|
||||
use super::build::BuilderExt;
|
||||
|
@ -167,6 +167,7 @@ pub(crate) fn notify_parent_dbg(env: &Env, shared_memory: &SharedMemoryPointer)
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
shared_memory: &SharedMemoryPointer<'ctx>,
|
||||
|
@ -201,7 +202,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
let (value, layout) = load_symbol_and_layout(scope, lookup);
|
||||
|
||||
let stack_size = env.ptr_int().const_int(
|
||||
layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
|
||||
|
@ -214,6 +215,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
|
||||
extra_offset = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_ptr,
|
||||
cursors,
|
||||
|
@ -280,6 +282,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -290,6 +293,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
match layout {
|
||||
Layout::Builtin(builtin) => build_clone_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -300,6 +304,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
|
||||
Layout::Struct { field_layouts, .. } => build_clone_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -313,7 +318,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
Layout::LambdaSet(_) => cursors.extra_offset,
|
||||
|
||||
Layout::Union(union_layout) => {
|
||||
if layout.safe_to_memcpy(env.layout_interner) {
|
||||
if layout.safe_to_memcpy(layout_interner) {
|
||||
let ptr = unsafe {
|
||||
env.builder.new_build_in_bounds_gep(
|
||||
env.context.i8_type(),
|
||||
|
@ -328,12 +333,13 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
.builder
|
||||
.build_pointer_cast(ptr, ptr_type, "cast_ptr_type");
|
||||
|
||||
store_roc_value(env, layout, ptr, value);
|
||||
store_roc_value(env, layout_interner, layout, ptr, value);
|
||||
|
||||
cursors.extra_offset
|
||||
} else {
|
||||
build_clone_tag(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -349,11 +355,11 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, cursors.offset, cursors.extra_offset.into());
|
||||
|
||||
let source = value.into_pointer_value();
|
||||
let inner_layout = env.layout_interner.get(inner_layout);
|
||||
let value = load_roc_value(env, *inner_layout, source, "inner");
|
||||
let inner_layout = layout_interner.get(inner_layout);
|
||||
let value = load_roc_value(env, layout_interner, *inner_layout, source, "inner");
|
||||
|
||||
let inner_width = env.ptr_int().const_int(
|
||||
inner_layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
inner_layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
|
||||
|
@ -368,6 +374,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
|
||||
build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -385,7 +392,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(union_layout);
|
||||
|
||||
let bt = basic_type_from_layout(env, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -396,6 +403,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
|
||||
build_clone_tag(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -411,6 +419,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_struct<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -420,7 +429,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
) -> IntValue<'ctx> {
|
||||
let layout = Layout::struct_no_name_order(field_layouts);
|
||||
|
||||
if layout.safe_to_memcpy(env.layout_interner) {
|
||||
if layout.safe_to_memcpy(layout_interner) {
|
||||
build_copy(env, ptr, cursors.offset, value)
|
||||
} else {
|
||||
let mut cursors = cursors;
|
||||
|
@ -433,10 +442,11 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
.build_extract_value(structure, i as _, "extract")
|
||||
.unwrap();
|
||||
|
||||
let field = use_roc_value(env, *field_layout, field, "field");
|
||||
let field = use_roc_value(env, layout_interner, *field_layout, field, "field");
|
||||
|
||||
let new_extra = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -446,7 +456,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
);
|
||||
|
||||
let field_width = env.ptr_int().const_int(
|
||||
field_layout.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
field_layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
|
||||
|
@ -463,6 +473,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_tag<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -505,6 +516,7 @@ fn build_clone_tag<'a, 'ctx, 'env>(
|
|||
|
||||
build_clone_tag_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
union_layout,
|
||||
when_recursive,
|
||||
|
@ -539,11 +551,12 @@ fn build_clone_tag<'a, 'ctx, 'env>(
|
|||
|
||||
fn load_tag_data<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
tag_value: PointerValue<'ctx>,
|
||||
tag_type: BasicTypeEnum<'ctx>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let union_struct_type = struct_type_from_union_layout(env, &union_layout);
|
||||
let union_struct_type = struct_type_from_union_layout(env, layout_interner, &union_layout);
|
||||
|
||||
let raw_data_ptr = env
|
||||
.builder
|
||||
|
@ -567,6 +580,7 @@ fn load_tag_data<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_tag_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
|
@ -612,7 +626,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
env.builder.build_unreachable();
|
||||
}
|
||||
NonRecursive(tags) => {
|
||||
let id = get_tag_id(env, parent, &union_layout, tag_value);
|
||||
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
|
||||
|
||||
let switch_block = env.context.append_basic_block(parent, "switch_block");
|
||||
env.builder.build_unconditional_branch(switch_block);
|
||||
|
@ -628,16 +642,25 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
env.arena.alloc([layout, union_layout.tag_id_layout()]),
|
||||
);
|
||||
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let data = load_tag_data(
|
||||
env,
|
||||
layout_interner,
|
||||
union_layout,
|
||||
tag_value.into_pointer_value(),
|
||||
basic_type,
|
||||
);
|
||||
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
|
@ -657,7 +680,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
Recursive(tags) => {
|
||||
let id = get_tag_id(env, parent, &union_layout, tag_value);
|
||||
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
|
||||
|
||||
let switch_block = env.context.append_basic_block(parent, "switch_block");
|
||||
env.builder.build_unconditional_branch(switch_block);
|
||||
|
@ -682,11 +705,11 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
)
|
||||
};
|
||||
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let data = load_tag_data(env, union_layout, tag_value, basic_type);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
|
||||
union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
|
@ -698,8 +721,16 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
|
@ -724,10 +755,9 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = Layout::struct_no_name_order(fields);
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
|
||||
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
|
@ -738,10 +768,19 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
),
|
||||
};
|
||||
|
||||
let data = load_tag_data(env, union_layout, tag_value, basic_type);
|
||||
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer = build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
}
|
||||
|
@ -752,7 +791,7 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
let switch_block = env.context.append_basic_block(parent, "switch_block");
|
||||
let null_block = env.context.append_basic_block(parent, "null_block");
|
||||
|
||||
let id = get_tag_id(env, parent, &union_layout, tag_value);
|
||||
let id = get_tag_id(env, layout_interner, parent, &union_layout, tag_value);
|
||||
|
||||
let comparison = env
|
||||
.builder
|
||||
|
@ -782,10 +821,10 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let layout = Layout::struct_no_name_order(fields);
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(env.layout_interner, env.target_info);
|
||||
union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
|
@ -797,11 +836,20 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
|
||||
let data = load_tag_data(env, union_layout, tag_value, basic_type);
|
||||
let data =
|
||||
load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
|
||||
|
@ -857,14 +905,14 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = Layout::struct_no_name_order(other_fields);
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
extra_offset: env.builder.build_int_add(
|
||||
extra_offset,
|
||||
env.ptr_int().const_int(
|
||||
layout.stack_size(env.layout_interner, env.target_info) as _,
|
||||
layout.stack_size(layout_interner, env.target_info) as _,
|
||||
false,
|
||||
),
|
||||
"new_offset",
|
||||
|
@ -873,14 +921,23 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
|
||||
let data = load_tag_data(
|
||||
env,
|
||||
layout_interner,
|
||||
union_layout,
|
||||
tag_value.into_pointer_value(),
|
||||
basic_type,
|
||||
);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let answer =
|
||||
build_clone(env, layout_ids, ptr, cursors, data, layout, when_recursive);
|
||||
let answer = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
data,
|
||||
layout,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
env.builder.build_return(Some(&answer));
|
||||
}
|
||||
|
@ -945,6 +1002,7 @@ fn build_copy<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_clone_builtin<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
|
@ -990,14 +1048,14 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
offset = build_copy(env, ptr, offset, len.into());
|
||||
offset = build_copy(env, ptr, offset, len.into());
|
||||
|
||||
let elem = env.layout_interner.get(elem);
|
||||
let elem = layout_interner.get(elem);
|
||||
let (element_width, _element_align) =
|
||||
elem.stack_size_and_alignment(env.layout_interner, env.target_info);
|
||||
elem.stack_size_and_alignment(layout_interner, env.target_info);
|
||||
let element_width = env.ptr_int().const_int(element_width as _, false);
|
||||
|
||||
let elements_width = bd.build_int_mul(element_width, len, "elements_width");
|
||||
|
||||
if elem.safe_to_memcpy(env.layout_interner) {
|
||||
if elem.safe_to_memcpy(layout_interner) {
|
||||
// NOTE we are not actually sure the dest is properly aligned
|
||||
let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, offset);
|
||||
let src = bd.build_pointer_cast(
|
||||
|
@ -1012,7 +1070,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
// We cloned the elements into the extra_offset address.
|
||||
let elements_start_offset = cursors.extra_offset;
|
||||
|
||||
let element_type = basic_type_from_layout(env, elem);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, elem);
|
||||
let elements = bd.build_pointer_cast(
|
||||
elements,
|
||||
element_type.ptr_type(AddressSpace::Generic),
|
||||
|
@ -1023,7 +1081,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset");
|
||||
|
||||
let element_stack_size = env.ptr_int().const_int(
|
||||
elem.stack_size(env.layout_interner, env.target_info) as u64,
|
||||
elem.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
let rest_start_offset = bd.build_int_add(
|
||||
|
@ -1033,7 +1091,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
);
|
||||
bd.build_store(rest_offset, rest_start_offset);
|
||||
|
||||
let body = |index, element| {
|
||||
let body = |layout_interner, index, element| {
|
||||
let current_offset =
|
||||
bd.build_int_mul(element_stack_size, index, "current_offset");
|
||||
let current_offset =
|
||||
|
@ -1051,6 +1109,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
let new_offset = build_clone(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
ptr,
|
||||
cursors,
|
||||
|
@ -1068,7 +1127,16 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
.and_then(|b| b.get_parent())
|
||||
.unwrap();
|
||||
|
||||
incrementing_elem_loop(env, parent, *elem, elements, len, "index", body);
|
||||
incrementing_elem_loop(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
*elem,
|
||||
elements,
|
||||
len,
|
||||
"index",
|
||||
body,
|
||||
);
|
||||
|
||||
bd.new_build_load(env.ptr_int(), rest_offset, "rest_start_offset")
|
||||
.into_int_value()
|
||||
|
|
|
@ -13,7 +13,7 @@ use roc_intern::Interner;
|
|||
use roc_module::{low_level::LowLevel, symbol::Symbol};
|
||||
use roc_mono::{
|
||||
ir::HigherOrderLowLevel,
|
||||
layout::{Builtin, LambdaSet, Layout, LayoutIds},
|
||||
layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner},
|
||||
};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
|
@ -62,6 +62,7 @@ macro_rules! list_element_layout {
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -256,7 +257,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
);
|
||||
|
||||
let roc_return_type =
|
||||
basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
|
||||
basic_type_from_layout(env, layout_interner, layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let roc_return_alloca = env.builder.build_pointer_cast(
|
||||
zig_return_alloca,
|
||||
|
@ -264,7 +266,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
"cast_to_roc",
|
||||
);
|
||||
|
||||
load_roc_value(env, *layout, roc_return_alloca, "str_to_num_result")
|
||||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*layout,
|
||||
roc_return_alloca,
|
||||
"str_to_num_result",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +294,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
call_bitcode_fn_fixing_for_convention(
|
||||
env,
|
||||
layout_interner,
|
||||
bitcode_return_type,
|
||||
&[string],
|
||||
layout,
|
||||
|
@ -298,7 +307,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
// zig passes the result as a packed integer sometimes, instead of a struct. So we cast
|
||||
let expected_type = basic_type_from_layout(env, layout);
|
||||
let expected_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let actual_type = result.get_type();
|
||||
|
||||
if expected_type != actual_type {
|
||||
|
@ -487,7 +496,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
bitcode::STR_GET_SCALAR_UNSAFE,
|
||||
);
|
||||
|
||||
let return_type = basic_type_from_layout(env, layout);
|
||||
let return_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let cast_result = env.builder.build_pointer_cast(
|
||||
result,
|
||||
return_type.ptr_type(AddressSpace::Generic),
|
||||
|
@ -510,7 +519,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => result,
|
||||
PtrWidth::Bytes4 => {
|
||||
let to = basic_type_from_layout(env, layout);
|
||||
let to = basic_type_from_layout(env, layout_interner, layout);
|
||||
complex_bitcast_check_size(env, result, to, "to_roc_record")
|
||||
}
|
||||
}
|
||||
|
@ -645,6 +654,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let result_layout = *layout;
|
||||
list_with_capacity(
|
||||
env,
|
||||
layout_interner,
|
||||
list_len.into_int_value(),
|
||||
list_element_layout!(result_layout),
|
||||
)
|
||||
|
@ -658,7 +668,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
|
||||
list_concat(env, first_list, second_list, *element_layout)
|
||||
list_concat(
|
||||
env,
|
||||
layout_interner,
|
||||
first_list,
|
||||
second_list,
|
||||
*element_layout,
|
||||
)
|
||||
}
|
||||
ListAppendUnsafe => {
|
||||
// List.appendUnsafe : List elem, elem -> List elem
|
||||
|
@ -667,7 +683,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
||||
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
list_append_unsafe(env, original_wrapper, elem, elem_layout)
|
||||
list_append_unsafe(env, layout_interner, original_wrapper, elem, elem_layout)
|
||||
}
|
||||
ListPrepend => {
|
||||
// List.prepend : List elem, elem -> List elem
|
||||
|
@ -676,7 +692,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
||||
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
list_prepend(env, original_wrapper, elem, elem_layout)
|
||||
list_prepend(env, layout_interner, original_wrapper, elem, elem_layout)
|
||||
}
|
||||
ListReserve => {
|
||||
// List.reserve : List elem, Nat -> List elem
|
||||
|
@ -686,7 +702,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
let spare = load_symbol(scope, &args[1]);
|
||||
|
||||
list_reserve(env, list, spare, *element_layout, update_mode)
|
||||
list_reserve(
|
||||
env,
|
||||
layout_interner,
|
||||
list,
|
||||
spare,
|
||||
*element_layout,
|
||||
update_mode,
|
||||
)
|
||||
}
|
||||
ListSwap => {
|
||||
// List.swap : List elem, Nat, Nat -> List elem
|
||||
|
@ -701,6 +724,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
list_swap(
|
||||
env,
|
||||
layout_interner,
|
||||
original_wrapper,
|
||||
index_1.into_int_value(),
|
||||
index_2.into_int_value(),
|
||||
|
@ -720,6 +744,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
list_sublist(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
start.into_int_value(),
|
||||
|
@ -739,6 +764,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
list_drop_at(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
count.into_int_value(),
|
||||
|
@ -763,6 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_get_unsafe(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
*list_element_layout!(list_layout),
|
||||
element_index.into_int_value(),
|
||||
|
@ -774,6 +801,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_replace_unsafe(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
list,
|
||||
index.into_int_value(),
|
||||
|
@ -844,6 +872,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let int_type = convert::int_type_from_int_width(env, *int_width);
|
||||
build_int_unary_op(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
arg.into_int_value(),
|
||||
*int_width,
|
||||
|
@ -1033,7 +1062,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
NumIntCast => {
|
||||
arguments!(arg);
|
||||
|
||||
let to = basic_type_from_layout(env, layout).into_int_type();
|
||||
let to = basic_type_from_layout(env, layout_interner, layout).into_int_type();
|
||||
let to_signed = intwidth_from_layout(*layout).is_signed();
|
||||
|
||||
env.builder
|
||||
|
@ -1047,7 +1076,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::Int(width)) => {
|
||||
// Converting from int to float
|
||||
let int_val = arg.into_int_value();
|
||||
let dest = basic_type_from_layout(env, layout).into_float_type();
|
||||
let dest =
|
||||
basic_type_from_layout(env, layout_interner, layout).into_float_type();
|
||||
|
||||
if width.is_signed() {
|
||||
env.builder
|
||||
|
@ -1061,7 +1091,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
Layout::Builtin(Builtin::Float(_)) => {
|
||||
// Converting from float to float - e.g. F64 to F32, or vice versa
|
||||
let dest = basic_type_from_layout(env, layout).into_float_type();
|
||||
let dest =
|
||||
basic_type_from_layout(env, layout_interner, layout).into_float_type();
|
||||
|
||||
env.builder
|
||||
.build_float_cast(arg.into_float_value(), dest, "cast_float_to_float")
|
||||
|
@ -1083,12 +1114,28 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
Eq => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
generic_eq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
generic_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_arg,
|
||||
rhs_arg,
|
||||
lhs_layout,
|
||||
rhs_layout,
|
||||
)
|
||||
}
|
||||
NotEq => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
generic_neq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
generic_neq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_arg,
|
||||
rhs_arg,
|
||||
lhs_layout,
|
||||
rhs_layout,
|
||||
)
|
||||
}
|
||||
And => {
|
||||
// The (&&) operator
|
||||
|
@ -1137,13 +1184,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||
}
|
||||
|
||||
Unreachable => match RocReturn::from_layout(env, layout) {
|
||||
Unreachable => match RocReturn::from_layout(env, layout_interner, layout) {
|
||||
RocReturn::Return => {
|
||||
let basic_type = basic_type_from_layout(env, layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
basic_type.const_zero()
|
||||
}
|
||||
RocReturn::ByPointer => {
|
||||
let basic_type = basic_type_from_layout(env, layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let ptr = env.builder.build_alloca(basic_type, "unreachable_alloca");
|
||||
env.builder.build_store(ptr, basic_type.const_zero());
|
||||
|
||||
|
@ -1817,6 +1864,7 @@ fn int_type_signed_min(int_type: IntType) -> IntValue {
|
|||
|
||||
fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
arg: IntValue<'ctx>,
|
||||
arg_width: IntWidth,
|
||||
|
@ -1887,8 +1935,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
|| // Or if the two types are the same, they trivially fit.
|
||||
arg_width == target_int_width;
|
||||
|
||||
let return_type =
|
||||
convert::basic_type_from_layout(env, return_layout).into_struct_type();
|
||||
let return_type = convert::basic_type_from_layout(env, layout_interner, return_layout)
|
||||
.into_struct_type();
|
||||
|
||||
if arg_always_fits_in_target {
|
||||
// This is guaranteed to succeed so we can just make it an int cast and let LLVM
|
||||
|
@ -1958,7 +2006,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
intrinsic,
|
||||
);
|
||||
|
||||
let roc_return_type = basic_type_from_layout(env, return_layout)
|
||||
let roc_return_type =
|
||||
basic_type_from_layout(env, layout_interner, return_layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let roc_return_alloca = env.builder.build_pointer_cast(
|
||||
|
@ -1967,7 +2016,13 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
"cast_to_roc",
|
||||
);
|
||||
|
||||
load_roc_value(env, *return_layout, roc_return_alloca, "num_to_int")
|
||||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*return_layout,
|
||||
roc_return_alloca,
|
||||
"num_to_int",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1978,6 +2033,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
|
||||
call_bitcode_fn_fixing_for_convention(
|
||||
env,
|
||||
layout_interner,
|
||||
bitcode_return_type,
|
||||
&[arg.into()],
|
||||
return_layout,
|
||||
|
@ -2221,6 +2277,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
return_layout: &Layout<'a>,
|
||||
|
@ -2276,13 +2333,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element_layout = env.layout_interner.get(*element_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element_layout = layout_interner.get(*element_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2292,7 +2350,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
*result_layout,
|
||||
);
|
||||
|
||||
list_map(env, roc_function_call, list, element_layout, result_layout)
|
||||
list_map(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function_call,
|
||||
list,
|
||||
element_layout,
|
||||
result_layout,
|
||||
)
|
||||
}
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
|
@ -2309,14 +2374,15 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element2_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = env.layout_interner.get(*element1_layout);
|
||||
let element2_layout = env.layout_interner.get(*element2_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element1_layout, *element2_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2328,6 +2394,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_map2(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
list1,
|
||||
|
@ -2354,15 +2421,16 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element3_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = env.layout_interner.get(*element1_layout);
|
||||
let element2_layout = env.layout_interner.get(*element2_layout);
|
||||
let element3_layout = env.layout_interner.get(*element3_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let element3_layout = layout_interner.get(*element3_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element1_layout, *element2_layout, *element3_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2374,6 +2442,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_map3(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
list1,
|
||||
|
@ -2410,11 +2479,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element4_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = env.layout_interner.get(*element1_layout);
|
||||
let element2_layout = env.layout_interner.get(*element2_layout);
|
||||
let element3_layout = env.layout_interner.get(*element3_layout);
|
||||
let element4_layout = env.layout_interner.get(*element4_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let element3_layout = layout_interner.get(*element3_layout);
|
||||
let element4_layout = layout_interner.get(*element4_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[
|
||||
*element1_layout,
|
||||
|
@ -2425,6 +2494,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2436,6 +2506,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_map4(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
list1,
|
||||
|
@ -2462,17 +2533,23 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
use crate::llvm::bitcode::build_compare_wrapper;
|
||||
|
||||
let element_layout = env.layout_interner.get(*element_layout);
|
||||
let element_layout = layout_interner.get(*element_layout);
|
||||
|
||||
let argument_layouts = &[*element_layout, *element_layout];
|
||||
|
||||
let compare_wrapper =
|
||||
build_compare_wrapper(env, function, closure_layout, element_layout)
|
||||
let compare_wrapper = build_compare_wrapper(
|
||||
env,
|
||||
layout_interner,
|
||||
function,
|
||||
closure_layout,
|
||||
element_layout,
|
||||
)
|
||||
.as_global_value()
|
||||
.as_pointer_value();
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2484,6 +2561,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_sort_with(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function_call,
|
||||
compare_wrapper,
|
||||
list,
|
||||
|
|
|
@ -114,10 +114,11 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
mode: CallMode<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
) {
|
||||
match mode {
|
||||
CallMode::Inc(inc_amount) => self.increment(inc_amount, env),
|
||||
CallMode::Dec => self.decrement(env, layout),
|
||||
CallMode::Dec => self.decrement(env, layout_interner, layout),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,9 +126,14 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
incref_pointer(env, self.value, amount);
|
||||
}
|
||||
|
||||
pub fn decrement<'a, 'env>(&self, env: &Env<'a, 'ctx, 'env>, layout: &Layout<'a>) {
|
||||
pub fn decrement<'a, 'env>(
|
||||
&self,
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'a>,
|
||||
) {
|
||||
let alignment = layout
|
||||
.allocation_alignment_bytes(env.layout_interner, env.target_info)
|
||||
.allocation_alignment_bytes(layout_interner, env.target_info)
|
||||
.max(env.target_info.ptr_width() as u32);
|
||||
|
||||
let context = env.context;
|
||||
|
@ -266,6 +272,7 @@ pub fn decref_pointer_check_null<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_struct<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layouts: &'a [Layout<'a>],
|
||||
mode: Mode,
|
||||
|
@ -288,11 +295,12 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_struct_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
|
@ -314,6 +322,7 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -339,7 +348,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
let wrapper_struct = arg_val.into_struct_value();
|
||||
|
||||
for (i, field_layout) in layouts.iter().enumerate() {
|
||||
if field_layout.contains_refcounted(env.layout_interner) {
|
||||
if field_layout.contains_refcounted(layout_interner) {
|
||||
let raw_value = env
|
||||
.builder
|
||||
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
|
||||
|
@ -347,6 +356,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
|
||||
let field_value = use_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*field_layout,
|
||||
raw_value,
|
||||
"load_struct_tag_field_for_decrement",
|
||||
|
@ -354,6 +364,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
|
@ -368,36 +379,54 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn increment_refcount_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
inc_amount: u64,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
) {
|
||||
let amount = env.ptr_int().const_int(inc_amount, false);
|
||||
increment_n_refcount_layout(env, layout_ids, amount, value, layout);
|
||||
increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout);
|
||||
}
|
||||
|
||||
pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
amount: IntValue<'ctx>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
) {
|
||||
modify_refcount_layout(env, layout_ids, CallMode::Inc(amount), value, layout);
|
||||
modify_refcount_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
CallMode::Inc(amount),
|
||||
value,
|
||||
layout,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
) {
|
||||
modify_refcount_layout(env, layout_ids, CallMode::Dec, value, layout);
|
||||
modify_refcount_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
CallMode::Dec,
|
||||
value,
|
||||
layout,
|
||||
);
|
||||
}
|
||||
|
||||
fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -408,13 +437,25 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
match builtin {
|
||||
List(element_layout) => {
|
||||
let function =
|
||||
modify_refcount_list(env, layout_ids, mode, when_recursive, *element_layout);
|
||||
let function = modify_refcount_list(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
*element_layout,
|
||||
);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
||||
Str => Some(modify_refcount_str(env, layout_ids, mode, layout)),
|
||||
Str => Some(modify_refcount_str(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
layout,
|
||||
)),
|
||||
|
||||
_ => {
|
||||
debug_assert!(!builtin.is_refcounted());
|
||||
|
@ -425,6 +466,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
call_mode: CallMode<'ctx>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
|
@ -432,6 +474,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
|||
) {
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
call_mode,
|
||||
&WhenRecursive::Unreachable,
|
||||
|
@ -442,6 +485,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
call_mode: CallMode<'ctx>,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -455,6 +499,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
|||
|
||||
let function = match modify_refcount_layout_build_function(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
|
@ -472,7 +517,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
|||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(*union_layout);
|
||||
|
||||
let bt = basic_type_from_layout(env, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field_cast = env.builder.build_pointer_cast(
|
||||
|
@ -519,6 +564,7 @@ fn call_help<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -527,12 +573,18 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
use Layout::*;
|
||||
|
||||
match layout {
|
||||
Builtin(builtin) => {
|
||||
modify_refcount_builtin(env, layout_ids, mode, when_recursive, layout, builtin)
|
||||
}
|
||||
Builtin(builtin) => modify_refcount_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
layout,
|
||||
builtin,
|
||||
),
|
||||
|
||||
Boxed(inner) => {
|
||||
let function = modify_refcount_boxed(env, layout_ids, mode, *inner);
|
||||
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, *inner);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
@ -547,8 +599,14 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
NonRecursive(tags) => {
|
||||
let function =
|
||||
modify_refcount_nonrecursive(env, layout_ids, mode, when_recursive, tags);
|
||||
let function = modify_refcount_nonrecursive(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
tags,
|
||||
);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
@ -556,6 +614,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
_ => {
|
||||
let function = build_rec_union(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
&WhenRecursive::Loop(*variant),
|
||||
|
@ -568,8 +627,14 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
Struct { field_layouts, .. } => {
|
||||
let function =
|
||||
modify_refcount_struct(env, layout_ids, field_layouts, mode, when_recursive);
|
||||
let function = modify_refcount_struct(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
field_layouts,
|
||||
mode,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
@ -583,6 +648,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
|
||||
let function = modify_refcount_layout_build_function(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
|
@ -594,16 +660,18 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
},
|
||||
LambdaSet(lambda_set) => modify_refcount_layout_build_function(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
&lambda_set.runtime_representation(env.layout_interner),
|
||||
&lambda_set.runtime_representation(layout_interner),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_refcount_list<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -612,9 +680,9 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
|
||||
let element_layout = env.layout_interner.insert(env.arena.alloc(element_layout));
|
||||
let element_layout = layout_interner.insert(env.arena.alloc(element_layout));
|
||||
let list_layout = &Layout::Builtin(Builtin::List(element_layout));
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
|
@ -628,11 +696,12 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = argument_type_from_layout(env, list_layout);
|
||||
let basic_type = argument_type_from_layout(env, layout_interner, list_layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_list_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
|
@ -661,6 +730,7 @@ fn mode_to_call_mode(function: FunctionValue<'_>, mode: Mode) -> CallMode<'_> {
|
|||
|
||||
fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -704,15 +774,17 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
|
||||
builder.position_at_end(modification_block);
|
||||
|
||||
let element_layout = env.layout_interner.get(element_layout);
|
||||
if element_layout.contains_refcounted(env.layout_interner) {
|
||||
let ptr_type = basic_type_from_layout(env, element_layout).ptr_type(AddressSpace::Generic);
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
if element_layout.contains_refcounted(layout_interner) {
|
||||
let ptr_type = basic_type_from_layout(env, layout_interner, element_layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let (len, ptr) = load_list(env.builder, original_wrapper, ptr_type);
|
||||
|
||||
let loop_fn = |_index, element| {
|
||||
let loop_fn = |layout_interner, _index, element| {
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
|
@ -723,6 +795,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
|
||||
incrementing_elem_loop(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
*element_layout,
|
||||
ptr,
|
||||
|
@ -734,7 +807,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
|
||||
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, original_wrapper);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
refcount_ptr.modify(call_mode, layout, env);
|
||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
||||
|
||||
builder.build_unconditional_branch(cont_block);
|
||||
|
||||
|
@ -746,6 +819,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_str<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
layout: &Layout<'a>,
|
||||
|
@ -765,10 +839,10 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = argument_type_from_layout(env, layout);
|
||||
let basic_type = argument_type_from_layout(env, layout_interner, layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_str_help(env, mode, layout, function_value);
|
||||
modify_refcount_str_help(env, layout_interner, mode, layout, function_value);
|
||||
|
||||
function_value
|
||||
}
|
||||
|
@ -783,6 +857,7 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_str_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
mode: Mode,
|
||||
layout: &Layout<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
|
@ -805,9 +880,8 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
|
|||
|
||||
let parent = fn_val;
|
||||
|
||||
let arg_val = if Layout::Builtin(Builtin::Str)
|
||||
.is_passed_by_reference(env.layout_interner, env.target_info)
|
||||
{
|
||||
let arg_val =
|
||||
if Layout::Builtin(Builtin::Str).is_passed_by_reference(layout_interner, env.target_info) {
|
||||
let str_type = zig_str_type(env);
|
||||
env.builder
|
||||
.new_build_load(str_type, arg_val.into_pointer_value(), "load_str_to_stack")
|
||||
|
@ -841,7 +915,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
|
|||
|
||||
let refcount_ptr = PointerToRefcount::from_list_wrapper(env, str_wrapper);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
refcount_ptr.modify(call_mode, layout, env);
|
||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
||||
|
||||
builder.build_unconditional_branch(cont_block);
|
||||
|
||||
|
@ -853,6 +927,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_boxed<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
inner_layout: InLayout<'a>,
|
||||
|
@ -874,10 +949,10 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = basic_type_from_layout(env, boxed_layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, boxed_layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_box_help(env, mode, inner_layout, function_value);
|
||||
modify_refcount_box_help(env, layout_interner, mode, inner_layout, function_value);
|
||||
|
||||
function_value
|
||||
}
|
||||
|
@ -892,6 +967,7 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_box_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
mode: Mode,
|
||||
inner_layout: InLayout<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
|
@ -915,7 +991,7 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>(
|
|||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
let boxed_layout = Layout::Boxed(inner_layout);
|
||||
refcount_ptr.modify(call_mode, &boxed_layout, env);
|
||||
refcount_ptr.modify(call_mode, &boxed_layout, env, layout_interner);
|
||||
|
||||
// this function returns void
|
||||
builder.build_return(None);
|
||||
|
@ -1014,6 +1090,7 @@ enum CallMode<'ctx> {
|
|||
|
||||
fn build_rec_union<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -1036,11 +1113,12 @@ fn build_rec_union<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let basic_type = basic_type_from_layout(env, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
build_rec_union_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
|
@ -1062,6 +1140,7 @@ fn build_rec_union<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_rec_union_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -1091,7 +1170,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
let parent = fn_val;
|
||||
|
||||
debug_assert!(arg_val.is_pointer_value());
|
||||
let current_tag_id = get_tag_id(env, fn_val, &union_layout, arg_val);
|
||||
let current_tag_id = get_tag_id(env, layout_interner, fn_val, &union_layout, arg_val);
|
||||
let value_ptr = if union_layout.stores_tag_id_in_pointer(env.target_info) {
|
||||
tag_pointer_clear_tag_id(env, arg_val.into_pointer_value())
|
||||
} else {
|
||||
|
@ -1128,7 +1207,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
match mode {
|
||||
Mode::Inc => {
|
||||
// inc is cheap; we never recurse
|
||||
refcount_ptr.modify(call_mode, &layout, env);
|
||||
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1224,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
{
|
||||
env.builder.position_at_end(no_recurse_block);
|
||||
|
||||
refcount_ptr.modify(call_mode, &layout, env);
|
||||
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
|
@ -1154,6 +1233,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
build_rec_union_recursive_decrement(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
parent,
|
||||
|
@ -1185,6 +1265,7 @@ fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[Layo
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -1205,11 +1286,11 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
let tag_id_int_type =
|
||||
basic_type_from_layout(env, &union_layout.tag_id_layout()).into_int_type();
|
||||
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()).into_int_type();
|
||||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if fields_need_no_refcounting(env.layout_interner, field_layouts) {
|
||||
if fields_need_no_refcounting(layout_interner, field_layouts) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1217,8 +1298,11 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let wrapper_type =
|
||||
basic_type_from_layout(env, &Layout::struct_no_name_order(field_layouts));
|
||||
let wrapper_type = basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&Layout::struct_no_name_order(field_layouts),
|
||||
);
|
||||
|
||||
// cast the opaque pointer to a pointer of the correct shape
|
||||
let struct_ptr = env.builder.build_pointer_cast(
|
||||
|
@ -1254,11 +1338,12 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
|
||||
|
||||
// therefore we must cast it to our desired type
|
||||
let union_type = basic_type_from_layout(env, &Layout::Union(union_layout));
|
||||
let union_type =
|
||||
basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout));
|
||||
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
|
||||
|
||||
deferred_rec.push(recursive_field_ptr);
|
||||
} else if field_layout.contains_refcounted(env.layout_interner) {
|
||||
} else if field_layout.contains_refcounted(layout_interner) {
|
||||
let elem_pointer = env
|
||||
.builder
|
||||
.new_build_struct_gep(
|
||||
|
@ -1269,8 +1354,13 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let field =
|
||||
load_roc_value(env, *field_layout, elem_pointer, "decrement_struct_field");
|
||||
let field = load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*field_layout,
|
||||
elem_pointer,
|
||||
"decrement_struct_field",
|
||||
);
|
||||
|
||||
deferred_nonrec.push((field, field_layout));
|
||||
}
|
||||
|
@ -1286,13 +1376,19 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
match decrement_or_reuse {
|
||||
DecOrReuse::Reuse => {}
|
||||
DecOrReuse::Dec => {
|
||||
refcount_ptr.modify(call_mode, &Layout::Union(union_layout), env);
|
||||
refcount_ptr.modify(
|
||||
call_mode,
|
||||
&Layout::Union(union_layout),
|
||||
env,
|
||||
layout_interner,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (field, field_layout) in deferred_nonrec {
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode.to_call_mode(decrement_fn),
|
||||
when_recursive,
|
||||
|
@ -1338,7 +1434,12 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
|
||||
// increment/decrement the cons-cell itself
|
||||
if let DecOrReuse::Dec = decrement_or_reuse {
|
||||
refcount_ptr.modify(call_mode, &Layout::Union(union_layout), env);
|
||||
refcount_ptr.modify(
|
||||
call_mode,
|
||||
&Layout::Union(union_layout),
|
||||
env,
|
||||
layout_interner,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1366,6 +1467,7 @@ fn union_layout_tags<'a>(
|
|||
|
||||
pub fn build_reset<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
|
@ -1376,7 +1478,14 @@ pub fn build_reset<'a, 'ctx, 'env>(
|
|||
let fn_name = format!("{}_reset", fn_name);
|
||||
|
||||
let when_recursive = WhenRecursive::Loop(union_layout);
|
||||
let dec_function = build_rec_union(env, layout_ids, Mode::Dec, &when_recursive, union_layout);
|
||||
let dec_function = build_rec_union(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
Mode::Dec,
|
||||
&when_recursive,
|
||||
union_layout,
|
||||
);
|
||||
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
|
@ -1384,11 +1493,13 @@ pub fn build_reset<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let basic_type = basic_type_from_layout(env, &Layout::Union(union_layout));
|
||||
let basic_type =
|
||||
basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout));
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
build_reuse_rec_union_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
&when_recursive,
|
||||
union_layout,
|
||||
|
@ -1410,6 +1521,7 @@ pub fn build_reset<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
|
@ -1440,7 +1552,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
|||
let parent = reset_function;
|
||||
|
||||
debug_assert!(arg_val.is_pointer_value());
|
||||
let current_tag_id = get_tag_id(env, reset_function, &union_layout, arg_val);
|
||||
let current_tag_id = get_tag_id(env, layout_interner, reset_function, &union_layout, arg_val);
|
||||
let value_ptr = tag_pointer_clear_tag_id(env, arg_val.into_pointer_value());
|
||||
|
||||
// to increment/decrement the cons-cell itself
|
||||
|
@ -1478,7 +1590,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
|||
{
|
||||
env.builder.position_at_end(no_recurse_block);
|
||||
|
||||
refcount_ptr.modify(call_mode, &layout, env);
|
||||
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
|
@ -1487,6 +1599,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
build_rec_union_recursive_decrement(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
parent,
|
||||
|
@ -1524,6 +1637,7 @@ fn function_name_from_mode<'a>(
|
|||
|
||||
fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -1547,11 +1661,12 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = argument_type_from_union_layout(env, &union_layout);
|
||||
let basic_type = argument_type_from_union_layout(env, layout_interner, &union_layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_nonrecursive_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
|
@ -1572,6 +1687,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
|
|||
|
||||
fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
|
@ -1602,7 +1718,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
|
||||
let union_layout = UnionLayout::NonRecursive(tags);
|
||||
let layout = Layout::Union(union_layout);
|
||||
let union_struct_type = basic_type_from_layout(env, &layout).into_struct_type();
|
||||
let union_struct_type =
|
||||
basic_type_from_layout(env, layout_interner, &layout).into_struct_type();
|
||||
|
||||
// read the tag_id
|
||||
let tag_id_ptr = env
|
||||
|
@ -1618,7 +1735,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
let tag_id = env
|
||||
.builder
|
||||
.new_build_load(
|
||||
basic_type_from_layout(env, &union_layout.tag_id_layout()),
|
||||
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()),
|
||||
tag_id_ptr,
|
||||
"load_tag_id",
|
||||
)
|
||||
|
@ -1639,7 +1756,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if !field_layouts
|
||||
.iter()
|
||||
.any(|x| x.is_refcounted() || x.contains_refcounted(env.layout_interner))
|
||||
.any(|x| x.is_refcounted() || x.contains_refcounted(layout_interner))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -1647,8 +1764,11 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let data_struct_type =
|
||||
basic_type_from_layout(env, &Layout::struct_no_name_order(field_layouts));
|
||||
let data_struct_type = basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&Layout::struct_no_name_order(field_layouts),
|
||||
);
|
||||
|
||||
debug_assert!(data_struct_type.is_struct_type());
|
||||
let data_struct_type = data_struct_type.into_struct_type();
|
||||
|
@ -1698,20 +1818,24 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
debug_assert!(field_value.is_pointer_value());
|
||||
|
||||
// therefore we must cast it to our desired type
|
||||
let union_type =
|
||||
basic_type_from_layout(env, &Layout::Union(*recursive_union_layout));
|
||||
let union_type = basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&Layout::Union(*recursive_union_layout),
|
||||
);
|
||||
let recursive_ptr_field_value =
|
||||
cast_basic_basic(env.builder, field_value, union_type);
|
||||
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
recursive_ptr_field_value,
|
||||
&Layout::RecursivePointer,
|
||||
)
|
||||
} else if field_layout.contains_refcounted(env.layout_interner) {
|
||||
} else if field_layout.contains_refcounted(layout_interner) {
|
||||
let field_ptr = env
|
||||
.builder
|
||||
.new_build_struct_gep(
|
||||
|
@ -1723,11 +1847,11 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
.unwrap();
|
||||
|
||||
let field_value =
|
||||
if field_layout.is_passed_by_reference(env.layout_interner, env.target_info) {
|
||||
if field_layout.is_passed_by_reference(layout_interner, env.target_info) {
|
||||
field_ptr.into()
|
||||
} else {
|
||||
env.builder.new_build_load(
|
||||
basic_type_from_layout(env, field_layout),
|
||||
basic_type_from_layout(env, layout_interner, field_layout),
|
||||
field_ptr,
|
||||
"field_value",
|
||||
)
|
||||
|
@ -1735,6 +1859,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue