Update llvm backend

This commit is contained in:
Ayaz Hafiz 2023-01-04 12:35:18 -06:00
parent 9d70c45781
commit 03ece6e274
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
10 changed files with 696 additions and 701 deletions

View file

@ -17,7 +17,9 @@ 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, STLayoutInterner};
use roc_mono::layout::{
Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner,
};
use super::build::{create_entry_block_alloca, BuilderExt};
use super::convert::zig_list_type;
@ -98,7 +100,7 @@ pub fn call_bitcode_fn_fixing_for_convention<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
bitcode_return_type: StructType<'ctx>,
args: &[BasicValueEnum<'ctx>],
return_layout: &Layout<'a>,
return_layout: InLayout<'a>,
fn_name: &str,
) -> BasicValueEnum<'ctx> {
// Calling zig bitcode, so we must follow C calling conventions.
@ -168,8 +170,8 @@ pub(crate) fn build_transform_caller<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>,
argument_layouts: &[Layout<'a>],
result_layout: Layout<'a>,
argument_layouts: &[InLayout<'a>],
result_layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
let fn_name: &str = &format!(
"{}_zig_function_caller",
@ -195,8 +197,8 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>,
argument_layouts: &[Layout<'a>],
result_layout: Layout<'a>,
argument_layouts: &[InLayout<'a>],
result_layout: InLayout<'a>,
fn_name: &str,
) -> FunctionValue<'ctx> {
debug_assert!(argument_layouts.len() <= 7);
@ -242,7 +244,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
for (argument_ptr, layout) in arguments.iter().zip(argument_layouts) {
let basic_type =
basic_type_from_layout(env, layout_interner, layout).ptr_type(AddressSpace::Generic);
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(),
@ -265,13 +267,13 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
closure_data_layout
.is_represented(layout_interner)
.is_some(),
closure_data_layout.runtime_representation(layout_interner),
closure_data_layout.runtime_representation(),
) {
(false, _) => {
// the function doesn't expect a closure argument, nothing to add
}
(true, layout) => {
let closure_type = basic_type_from_layout(env, layout_interner, &layout)
let closure_type = basic_type_from_layout(env, layout_interner, layout)
.ptr_type(AddressSpace::Generic);
let closure_cast =
@ -289,7 +291,7 @@ fn build_transform_caller_help<'a, 'ctx, 'env>(
env,
layout_interner,
roc_function,
&result_layout,
result_layout,
arguments_cast.as_slice(),
);
@ -325,7 +327,7 @@ 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>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::IncN)
}
@ -335,7 +337,7 @@ 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>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Inc)
}
@ -344,7 +346,7 @@ 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>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
build_rc_wrapper(env, layout_interner, layout_ids, layout, Mode::Dec)
}
@ -353,7 +355,7 @@ 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>,
layout: InLayout<'a>,
rc_operation: Mode,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
@ -361,7 +363,7 @@ fn build_rc_wrapper<'a, 'ctx, 'env>(
let symbol = Symbol::GENERIC_RC_REF;
let fn_name = layout_ids
.get(symbol, layout)
.get(symbol, &layout)
.to_symbol_string(symbol, &env.interns);
let fn_name = match rc_operation {
@ -417,7 +419,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(layout_interner, env.target_info) {
let value = if layout_interner.is_passed_by_reference(layout) {
value_ptr.into()
} else {
env.builder
@ -457,14 +459,14 @@ 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>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let symbol = Symbol::GENERIC_EQ_REF;
let fn_name = layout_ids
.get(symbol, layout)
.get(symbol, &layout)
.to_symbol_string(symbol, &env.interns);
let function_value = match env.module.get_function(fn_name.as_str()) {
@ -511,8 +513,8 @@ 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_interner, *layout, value_cast1, "load_opaque");
let value2 = load_roc_value(env, layout_interner, *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,
@ -542,7 +544,7 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
roc_function: FunctionValue<'ctx>,
closure_data_layout: LambdaSet<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
@ -609,15 +611,18 @@ pub fn build_compare_wrapper<'a, 'ctx, 'env>(
let default = [value1.into(), value2.into()];
let arguments_cast = match closure_data_layout.runtime_representation(layout_interner) {
let closure_data_repr = closure_data_layout.runtime_representation();
let arguments_cast = match layout_interner.get(closure_data_repr) {
Layout::Struct {
field_layouts: &[], ..
} => {
// nothing to add
&default
}
other => {
let closure_type = basic_type_from_layout(env, layout_interner, &other);
_ => {
let closure_type =
basic_type_from_layout(env, layout_interner, closure_data_repr);
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

View file

@ -11,7 +11,7 @@ use inkwell::{AddressSpace, IntPredicate};
use morphic_lib::UpdateMode;
use roc_builtins::bitcode;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner};
use roc_mono::layout::{Builtin, InLayout, LayoutIds, LayoutInterner, STLayoutInterner};
use super::bitcode::{call_list_bitcode_fn, BitcodeReturns};
use super::build::{
@ -63,9 +63,9 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
element: BasicValueEnum<'ctx>,
layout: Layout<'a>,
layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_type = basic_type_from_layout(env, layout_interner, &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");
@ -83,13 +83,10 @@ 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>,
layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
env.ptr_int()
.const_int(
layout.stack_size(layout_interner, env.target_info) as u64,
false,
)
.const_int(layout_interner.stack_size(layout) as u64, false)
.into()
}
@ -112,14 +109,13 @@ pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
capacity: IntValue<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn(
env,
&[],
&[
capacity.into(),
env.alignment_intvalue(layout_interner, &element_layout),
layout_width(env, layout_interner, &element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
],
BitcodeReturns::List,
bitcode::LIST_WITH_CAPACITY,
@ -136,8 +132,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
) -> BasicValueEnum<'ctx> {
let builder = env.builder;
let element_layout = layout_interner.get(element_layout);
let elem_type = basic_type_from_layout(env, layout_interner, &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);
@ -161,7 +156,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
"list_get_load_element",
);
increment_refcount_layout(env, layout_interner, layout_ids, 1, result, &element_layout);
increment_refcount_layout(env, layout_interner, layout_ids, 1, result, element_layout);
result
}
@ -175,14 +170,13 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
element_layout: InLayout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn_1(
env,
list.into_struct_value(),
&[
env.alignment_intvalue(layout_interner, &element_layout),
env.alignment_intvalue(layout_interner, element_layout),
spare,
layout_width(env, layout_interner, &element_layout),
layout_width(env, layout_interner, element_layout),
pass_update_mode(env, update_mode),
],
bitcode::LIST_RESERVE,
@ -195,13 +189,13 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
pass_element_as_opaque(env, layout_interner, element, *element_layout),
pass_element_as_opaque(env, layout_interner, element, element_layout),
layout_width(env, layout_interner, element_layout),
],
bitcode::LIST_APPEND_UNSAFE,
@ -214,14 +208,14 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
original_wrapper: StructValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
env.alignment_intvalue(layout_interner, element_layout),
pass_element_as_opaque(env, layout_interner, element, *element_layout),
pass_element_as_opaque(env, layout_interner, element, element_layout),
layout_width(env, layout_interner, element_layout),
],
bitcode::LIST_PREPEND,
@ -238,13 +232,12 @@ pub(crate) fn list_swap<'a, 'ctx, 'env>(
element_layout: InLayout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn_1(
env,
original_wrapper,
&[
env.alignment_intvalue(layout_interner, &element_layout),
layout_width(env, layout_interner, &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),
@ -263,14 +256,13 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>(
len: IntValue<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, &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(layout_interner, &element_layout),
layout_width(env, layout_interner, &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(),
@ -288,14 +280,13 @@ pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
count: IntValue<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = layout_interner.get(element_layout);
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, &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(layout_interner, &element_layout),
layout_width(env, layout_interner, &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(),
],
@ -311,7 +302,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
list: BasicValueEnum<'ctx>,
index: IntValue<'ctx>,
element: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
element_layout: InLayout<'a>,
update_mode: UpdateMode,
) -> BasicValueEnum<'ctx> {
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
@ -327,7 +318,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
list.into_struct_value(),
&[
index.into(),
pass_element_as_opaque(env, layout_interner, element, *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),
],
@ -339,7 +330,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
&[
env.alignment_intvalue(layout_interner, element_layout),
index.into(),
pass_element_as_opaque(env, layout_interner, element, *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),
],
@ -354,7 +345,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(layout_interner, env.target_info);
let element_align = layout_interner.alignment_bytes(element_layout);
let element_first = element_align > env.target_info.ptr_width() as u32;
let fields = if element_first {
@ -443,7 +434,7 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
roc_function_call: RocFunctionCall<'ctx>,
compare_wrapper: PointerValue<'ctx>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn_1(
env,
@ -466,8 +457,8 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
roc_function_call: RocFunctionCall<'ctx>,
list: BasicValueEnum<'ctx>,
element_layout: &Layout<'a>,
return_layout: &Layout<'a>,
element_layout: InLayout<'a>,
return_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
call_list_bitcode_fn_1(
env,
@ -492,9 +483,9 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
roc_function_call: RocFunctionCall<'ctx>,
list1: BasicValueEnum<'ctx>,
list2: BasicValueEnum<'ctx>,
element1_layout: &Layout<'a>,
element2_layout: &Layout<'a>,
return_layout: &Layout<'a>,
element1_layout: InLayout<'a>,
element2_layout: InLayout<'a>,
return_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
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);
@ -527,10 +518,10 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
list1: BasicValueEnum<'ctx>,
list2: BasicValueEnum<'ctx>,
list3: BasicValueEnum<'ctx>,
element1_layout: &Layout<'a>,
element2_layout: &Layout<'a>,
element3_layout: &Layout<'a>,
result_layout: &Layout<'a>,
element1_layout: InLayout<'a>,
element2_layout: InLayout<'a>,
element3_layout: InLayout<'a>,
result_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
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);
@ -571,11 +562,11 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
list2: BasicValueEnum<'ctx>,
list3: BasicValueEnum<'ctx>,
list4: BasicValueEnum<'ctx>,
element1_layout: &Layout<'a>,
element2_layout: &Layout<'a>,
element3_layout: &Layout<'a>,
element4_layout: &Layout<'a>,
result_layout: &Layout<'a>,
element1_layout: InLayout<'a>,
element2_layout: InLayout<'a>,
element3_layout: InLayout<'a>,
element4_layout: InLayout<'a>,
result_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
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);
@ -619,13 +610,12 @@ pub(crate) fn list_concat<'a, 'ctx, 'env>(
list2: BasicValueEnum<'ctx>,
element_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
let element_layout = layout_interner.get(element_layout);
call_list_bitcode_fn(
env,
&[list1.into_struct_value(), list2.into_struct_value()],
&[
env.alignment_intvalue(layout_interner, &element_layout),
layout_width(env, layout_interner, &element_layout),
env.alignment_intvalue(layout_interner, element_layout),
layout_width(env, layout_interner, element_layout),
],
BitcodeReturns::List,
bitcode::LIST_CONCAT,
@ -636,7 +626,7 @@ 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>,
element_layout: InLayout<'a>,
ptr: PointerValue<'ctx>,
len: IntValue<'ctx>,
index_name: &str,
@ -647,7 +637,7 @@ where
{
let builder = env.builder;
let element_type = basic_type_from_layout(env, layout_interner, &element_layout);
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
incrementing_index_loop(
env,
@ -770,19 +760,19 @@ 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>,
elem_layout: InLayout<'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(layout_interner, env.target_info) as u64;
let elem_bytes = layout_interner.stack_size(elem_layout) 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, layout_interner, elem_layout);
let alignment_bytes = elem_layout.alignment_bytes(layout_interner, env.target_info);
let alignment_bytes = layout_interner.alignment_bytes(elem_layout);
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
}

View file

@ -2,13 +2,13 @@ use crate::llvm::build::Env;
use inkwell::values::{BasicValueEnum, PointerValue, StructValue};
use inkwell::AddressSpace;
use roc_builtins::bitcode;
use roc_mono::layout::Layout;
use roc_mono::layout::{InLayout, Layout};
use roc_target::PtrWidth;
use super::bitcode::{call_str_bitcode_fn, BitcodeReturns};
use super::build::BuilderExt;
pub static CHAR_LAYOUT: Layout = Layout::u8();
pub static CHAR_LAYOUT: InLayout = Layout::U8;
pub(crate) fn decode_from_utf8_result<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,

View file

@ -27,8 +27,8 @@ pub fn generic_eq<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
lhs_layout: &Layout<'a>,
rhs_layout: &Layout<'a>,
lhs_layout: InLayout<'a>,
rhs_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
build_eq(
env,
@ -48,8 +48,8 @@ pub fn generic_neq<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
lhs_layout: &Layout<'a>,
rhs_layout: &Layout<'a>,
lhs_layout: InLayout<'a>,
rhs_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
build_neq(
env,
@ -129,16 +129,19 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
Builtin::Decimal => dec_binop_with_unchecked(env, bitcode::DEC_EQ, lhs_val, rhs_val),
Builtin::Str => str_equal(env, lhs_val, rhs_val),
Builtin::List(elem) => build_list_eq(
env,
layout_interner,
layout_ids,
&Layout::Builtin(*builtin),
*elem,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
when_recursive,
),
Builtin::List(elem) => {
let list_layout = layout_interner.insert(Layout::Builtin(*builtin));
build_list_eq(
env,
layout_interner,
layout_ids,
list_layout,
*elem,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
when_recursive,
)
}
}
}
@ -148,12 +151,11 @@ fn build_eq<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
lhs_layout: &Layout<'a>,
rhs_layout: &Layout<'a>,
lhs_layout: InLayout<'a>,
rhs_layout: InLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
let lhs_layout = &lhs_layout.runtime_representation(layout_interner);
let rhs_layout = &rhs_layout.runtime_representation(layout_interner);
let lhs_layout_raw = &layout_interner.runtime_representation(lhs_layout);
if lhs_layout != rhs_layout {
panic!(
"Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}",
@ -161,7 +163,7 @@ fn build_eq<'a, 'ctx, 'env>(
);
}
match lhs_layout {
match lhs_layout_raw {
Layout::Builtin(builtin) => build_eq_builtin(
env,
layout_interner,
@ -211,9 +213,9 @@ fn build_eq<'a, 'ctx, 'env>(
}
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
let bt = basic_type_from_layout(env, layout_interner, &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(
@ -314,11 +316,12 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
result.into()
}
Builtin::List(elem) => {
let builtin_layout = layout_interner.insert(Layout::Builtin(*builtin));
let is_equal = build_list_eq(
env,
layout_interner,
layout_ids,
&Layout::Builtin(*builtin),
builtin_layout,
*elem,
lhs_val.into_struct_value(),
rhs_val.into_struct_value(),
@ -339,8 +342,8 @@ fn build_neq<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
lhs_val: BasicValueEnum<'ctx>,
rhs_val: BasicValueEnum<'ctx>,
lhs_layout: &Layout<'a>,
rhs_layout: &Layout<'a>,
lhs_layout: InLayout<'a>,
rhs_layout: InLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> BasicValueEnum<'ctx> {
if lhs_layout != rhs_layout {
@ -350,14 +353,14 @@ fn build_neq<'a, 'ctx, 'env>(
);
}
match lhs_layout {
match layout_interner.get(lhs_layout) {
Layout::Builtin(builtin) => build_neq_builtin(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
builtin,
&builtin,
when_recursive,
),
@ -384,7 +387,7 @@ fn build_neq<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
when_recursive,
union_layout,
&union_layout,
lhs_val,
rhs_val,
)
@ -402,7 +405,7 @@ fn build_neq<'a, 'ctx, 'env>(
layout_ids,
when_recursive,
lhs_layout,
*inner_layout,
inner_layout,
lhs_val,
rhs_val,
)
@ -424,7 +427,7 @@ 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>,
list_layout: InLayout<'a>,
element_layout: InLayout<'a>,
list1: StructValue<'ctx>,
list2: StructValue<'ctx>,
@ -436,6 +439,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
let symbol = Symbol::LIST_EQ;
let element_layout = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
let element_layout = layout_interner.insert(element_layout);
let fn_name = layout_ids
.get(symbol, &element_layout)
.to_symbol_string(symbol, &env.interns);
@ -458,7 +462,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
layout_ids,
when_recursive,
function_value,
&element_layout,
element_layout,
);
function_value
@ -483,7 +487,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
parent: FunctionValue<'ctx>,
element_layout: &Layout<'a>,
element_layout: InLayout<'a>,
) {
let ctx = env.context;
let builder = env.builder;
@ -582,14 +586,14 @@ 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, layout_interner, *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, layout_interner, *element_layout, elem_ptr, "get_elem")
load_roc_value(env, layout_interner, element_layout, elem_ptr, "get_elem")
};
let are_equal = build_eq(
@ -641,7 +645,7 @@ 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>],
field_layouts: &'a [InLayout<'a>],
when_recursive: WhenRecursive<'a>,
struct1: StructValue<'ctx>,
struct2: StructValue<'ctx>,
@ -649,7 +653,7 @@ fn build_struct_eq<'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 struct_layout = Layout::struct_no_name_order(field_layouts);
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
let symbol = Symbol::GENERIC_EQ;
let fn_name = layout_ids
@ -659,7 +663,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, layout_interner, &struct_layout);
let arg_type = basic_type_from_layout(env, layout_interner, struct_layout);
let function_value = crate::llvm::refcounting::build_header_help(
env,
@ -699,7 +703,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
parent: FunctionValue<'ctx>,
when_recursive: WhenRecursive<'a>,
field_layouts: &[Layout<'a>],
field_layouts: &[InLayout<'a>],
) {
let ctx = env.context;
let builder = env.builder;
@ -756,15 +760,15 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
.build_extract_value(struct2, index as u32, "eq_field")
.unwrap();
let are_equal = if let Layout::RecursivePointer = field_layout {
let are_equal = if let Layout::RecursivePointer = layout_interner.get(*field_layout) {
match &when_recursive {
WhenRecursive::Unreachable => {
unreachable!("The current layout should not be recursive, but is")
}
WhenRecursive::Loop(union_layout) => {
let field_layout = Layout::Union(*union_layout);
let field_layout = layout_interner.insert(Layout::Union(*union_layout));
let bt = basic_type_from_layout(env, layout_interner, &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(
@ -785,8 +789,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
layout_ids,
field1_cast.into(),
field2_cast.into(),
&field_layout,
&field_layout,
field_layout,
field_layout,
WhenRecursive::Loop(*union_layout),
)
.into_int_value()
@ -801,8 +805,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
layout_ids,
lhs,
rhs,
field_layout,
field_layout,
*field_layout,
*field_layout,
when_recursive,
)
.into_int_value()
@ -842,7 +846,7 @@ fn build_tag_eq<'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 tag_layout = Layout::Union(*union_layout);
let tag_layout = layout_interner.insert(Layout::Union(*union_layout));
let symbol = Symbol::GENERIC_EQ;
let fn_name = layout_ids
.get(symbol, &tag_layout)
@ -1285,13 +1289,13 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
union_layout: &UnionLayout<'a>,
opt_when_recursive: Option<WhenRecursive<'a>>,
field_layouts: &'a [Layout<'a>],
field_layouts: &'a [InLayout<'a>],
tag1: PointerValue<'ctx>,
tag2: PointerValue<'ctx>,
) -> IntValue<'ctx> {
let struct_layout = Layout::struct_no_name_order(field_layouts);
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
let wrapper_type = basic_type_from_layout(env, layout_interner, &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
@ -1336,7 +1340,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
when_recursive: WhenRecursive<'a>,
box_layout: &Layout<'a>,
box_layout: InLayout<'a>,
inner_layout: InLayout<'a>,
tag1: BasicValueEnum<'ctx>,
tag2: BasicValueEnum<'ctx>,
@ -1346,7 +1350,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
let symbol = Symbol::GENERIC_EQ;
let fn_name = layout_ids
.get(symbol, box_layout)
.get(symbol, &box_layout)
.to_symbol_string(symbol, &env.interns);
let function = match env.module.get_function(fn_name.as_str()) {
@ -1456,8 +1460,6 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
let box1 = box1.into_pointer_value();
let box2 = box2.into_pointer_value();
let inner_layout = layout_interner.get(inner_layout);
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");
@ -1467,8 +1469,8 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
layout_ids,
value1,
value2,
&inner_layout,
&inner_layout,
inner_layout,
inner_layout,
when_recursive,
);

View file

@ -6,19 +6,19 @@ use inkwell::values::StructValue;
use inkwell::AddressSpace;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_mono::layout::{
round_up_to_alignment, Builtin, Layout, LayoutInterner, STLayoutInterner, UnionLayout,
round_up_to_alignment, Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout,
};
use roc_target::TargetInfo;
fn basic_type_from_record<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
fields: &[Layout<'_>],
fields: &[InLayout<'_>],
) -> 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, layout_interner, field_layout));
field_types.push(basic_type_from_layout(env, layout_interner, *field_layout));
}
env.context
@ -29,34 +29,31 @@ 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<'_>,
layout: InLayout<'_>,
) -> BasicTypeEnum<'ctx> {
use Layout::*;
match layout {
match layout_interner.get(layout) {
Struct {
field_layouts: sorted_fields,
..
} => 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),
),
LambdaSet(lambda_set) => {
basic_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
}
Boxed(inner_layout) => {
let inner_layout = layout_interner.get(*inner_layout);
let inner_type = basic_type_from_layout(env, layout_interner, &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, layout_interner, union_layout),
Union(union_layout) => basic_type_from_union_layout(env, layout_interner, &union_layout),
RecursivePointer => env
.context
.i64_type()
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
Builtin(builtin) => basic_type_from_builtin(env, builtin),
Builtin(builtin) => basic_type_from_builtin(env, &builtin),
}
}
@ -148,27 +145,25 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
pub fn argument_type_from_layout<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'_>,
layout: InLayout<'a>,
) -> BasicTypeEnum<'ctx> {
use Layout::*;
match 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),
match layout_interner.get(layout) {
LambdaSet(lambda_set) => {
argument_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
}
Union(union_layout) => argument_type_from_union_layout(env, layout_interner, &union_layout),
Builtin(_) => {
let base = basic_type_from_layout(env, layout_interner, layout);
if layout.is_passed_by_reference(layout_interner, env.target_info) {
if layout_interner.is_passed_by_reference(layout) {
base.ptr_type(AddressSpace::Generic).into()
} else {
base
}
}
other => basic_type_from_layout(env, layout_interner, other),
_ => basic_type_from_layout(env, layout_interner, layout),
}
}
@ -301,7 +296,7 @@ impl<'ctx> RocUnion<'ctx> {
pub fn tagged_from_slices(
interner: &STLayoutInterner,
context: &'ctx Context,
layouts: &[&[Layout<'_>]],
layouts: &[&[InLayout<'_>]],
target_info: TargetInfo,
) -> Self {
let tag_type = match layouts.len() {
@ -318,7 +313,7 @@ impl<'ctx> RocUnion<'ctx> {
pub fn untagged_from_slices(
interner: &STLayoutInterner,
context: &'ctx Context,
layouts: &[&[Layout<'_>]],
layouts: &[&[InLayout<'_>]],
target_info: TargetInfo,
) -> Self {
let (data_width, data_align) =

View file

@ -11,7 +11,9 @@ use inkwell::AddressSpace;
use roc_builtins::bitcode;
use roc_module::symbol::Symbol;
use roc_mono::ir::LookupType;
use roc_mono::layout::{Builtin, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
};
use roc_region::all::Region;
use super::build::BuilderExt;
@ -199,10 +201,9 @@ 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(layout_interner, env.target_info) as u64,
false,
);
let stack_size = env
.ptr_int()
.const_int(layout_interner.stack_size(layout) as u64, false);
let mut extra_offset = env.builder.build_int_add(offset, stack_size, "offset");
@ -218,7 +219,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
original_ptr,
cursors,
value,
*layout,
layout,
WhenRecursive::Unreachable,
);
@ -284,10 +285,10 @@ fn build_clone<'a, 'ctx, 'env>(
ptr: PointerValue<'ctx>,
cursors: Cursors<'ctx>,
value: BasicValueEnum<'ctx>,
layout: Layout<'a>,
layout: InLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
match layout {
match layout_interner.get(layout) {
Layout::Builtin(builtin) => build_clone_builtin(
env,
layout_interner,
@ -315,7 +316,7 @@ fn build_clone<'a, 'ctx, 'env>(
Layout::LambdaSet(_) => cursors.extra_offset,
Layout::Union(union_layout) => {
if layout.safe_to_memcpy(layout_interner) {
if layout_interner.safe_to_memcpy(layout) {
let ptr = unsafe {
env.builder.new_build_in_bounds_gep(
env.context.i8_type(),
@ -352,13 +353,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 = 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(layout_interner, env.target_info) as u64,
false,
);
let inner_width = env
.ptr_int()
.const_int(layout_interner.stack_size(inner_layout) as u64, false);
let new_extra = env
.builder
@ -387,9 +386,9 @@ fn build_clone<'a, 'ctx, 'env>(
}
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
let bt = basic_type_from_layout(env, layout_interner, &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(
@ -420,7 +419,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
ptr: PointerValue<'ctx>,
cursors: Cursors<'ctx>,
value: BasicValueEnum<'ctx>,
field_layouts: &[Layout<'a>],
field_layouts: &[InLayout<'a>],
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
let layout = Layout::struct_no_name_order(field_layouts);
@ -451,10 +450,9 @@ fn build_clone_struct<'a, 'ctx, 'env>(
when_recursive,
);
let field_width = env.ptr_int().const_int(
field_layout.stack_size(layout_interner, env.target_info) as u64,
false,
);
let field_width = env
.ptr_int()
.const_int(layout_interner.stack_size(*field_layout) as u64, false);
cursors.extra_offset = new_extra;
cursors.offset = env
@ -476,7 +474,7 @@ fn build_clone_tag<'a, 'ctx, 'env>(
union_layout: UnionLayout<'a>,
when_recursive: WhenRecursive<'a>,
) -> IntValue<'ctx> {
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
let layout_id = layout_ids.get(Symbol::CLONE, &layout);
let fn_name = layout_id.to_symbol_string(Symbol::CLONE, &env.interns);
@ -631,12 +629,12 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let block = env.context.append_basic_block(parent, "tag_id_modify");
env.builder.position_at_end(block);
let layout = Layout::struct_no_name_order(field_layouts);
let layout = Layout::struct_no_name_order(
let layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
let layout = layout_interner.insert(Layout::struct_no_name_order(
env.arena.alloc([layout, union_layout.tag_id_layout()]),
);
));
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let data = load_tag_data(
env,
layout_interner,
@ -690,16 +688,16 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
let layout = Layout::struct_no_name_order(field_layouts);
let layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) {
layout
} else {
Layout::struct_no_name_order(
layout_interner.insert(Layout::struct_no_name_order(
env.arena.alloc([layout, union_layout.tag_id_layout()]),
)
))
};
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
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, _) =
@ -748,8 +746,8 @@ 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_interner, &layout);
let layout = layout_interner.insert(Layout::struct_no_name_order(fields));
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
@ -814,8 +812,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
other_tags[i]
};
let layout = Layout::struct_no_name_order(fields);
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
let layout = layout_interner.insert(Layout::struct_no_name_order(fields));
let basic_type = basic_type_from_layout(env, layout_interner, layout);
let (width, _) =
union_layout.data_size_and_alignment(layout_interner, env.target_info);
@ -898,17 +896,15 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
// write the "pointer" af the current offset
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_interner, &layout);
let layout = layout_interner.insert(Layout::struct_no_name_order(other_fields));
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(layout_interner, env.target_info) as _,
false,
),
env.ptr_int()
.const_int(layout_interner.stack_size(layout) as _, false),
"new_offset",
),
};
@ -1041,14 +1037,12 @@ 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 = layout_interner.get(elem);
let (element_width, _element_align) =
elem.stack_size_and_alignment(layout_interner, env.target_info);
let (element_width, _element_align) = layout_interner.stack_size_and_alignment(elem);
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(layout_interner) {
if layout_interner.safe_to_memcpy(elem) {
// 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(
@ -1063,7 +1057,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, layout_interner, &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),
@ -1073,10 +1067,9 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
// if the element has any pointers, we clone them to this offset
let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset");
let element_stack_size = env.ptr_int().const_int(
elem.stack_size(layout_interner, env.target_info) as u64,
false,
);
let element_stack_size = env
.ptr_int()
.const_int(layout_interner.stack_size(elem) as u64, false);
let rest_start_offset = bd.build_int_add(
cursors.extra_offset,
bd.build_int_mul(len, element_stack_size, "elements_width"),

View file

@ -12,7 +12,7 @@ use roc_error_macros::internal_error;
use roc_module::{low_level::LowLevel, symbol::Symbol};
use roc_mono::{
ir::HigherOrderLowLevel,
layout::{Builtin, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner},
layout::{Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner},
};
use roc_target::PtrWidth;
@ -50,8 +50,8 @@ use super::{
};
macro_rules! list_element_layout {
($list_layout:expr) => {
match $list_layout {
($interner:expr, $list_layout:expr) => {
match $interner.get($list_layout) {
Layout::Builtin(Builtin::List(list_layout)) => list_layout,
_ => unreachable!("invalid list layout"),
}
@ -64,7 +64,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>,
parent: FunctionValue<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
op: LowLevel,
args: &[Symbol],
update_mode: UpdateMode,
@ -200,13 +200,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
// Str.toNum : Str -> Result (Num *) {}
arguments!(string);
let number_layout = match layout {
let number_layout = match layout_interner.get(layout) {
Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
_ => unreachable!(),
};
// match on the return layout to figure out which zig builtin we need
let intrinsic = match number_layout {
let intrinsic = match layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
Layout::Builtin(Builtin::Float(float_width)) => &bitcode::STR_TO_FLOAT[float_width],
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
@ -227,7 +227,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
intrinsic,
),
None => {
let return_type_name = match number_layout {
let return_type_name = match layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => int_width.type_name(),
Layout::Builtin(Builtin::Decimal) => {
// zig picks 128 for dec.RocDec
@ -267,7 +267,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
load_roc_value(
env,
layout_interner,
*layout,
layout,
roc_return_alloca,
"str_to_num_result",
)
@ -275,7 +275,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
}
}
PtrWidth::Bytes8 => {
let cc_return_by_pointer = match number_layout {
let cc_return_by_pointer = match layout_interner.get(number_layout) {
Layout::Builtin(Builtin::Int(int_width)) => {
(int_width.stack_size() as usize > env.target_info.ptr_size())
.then_some(int_width.type_name())
@ -321,8 +321,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let (int, int_layout) = load_symbol_and_layout(scope, &args[0]);
let int = int.into_int_value();
let int_width = match int_layout {
Layout::Builtin(Builtin::Int(int_width)) => *int_width,
let int_width = match layout_interner.get(int_layout) {
Layout::Builtin(Builtin::Int(int_width)) => int_width,
_ => unreachable!(),
};
@ -340,8 +340,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
let float_width = match float_layout {
Layout::Builtin(Builtin::Float(float_width)) => *float_width,
let float_width = match layout_interner.get(float_layout) {
Layout::Builtin(Builtin::Float(float_width)) => float_width,
_ => unreachable!(),
};
@ -649,12 +649,12 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
// List.withCapacity : Nat -> List a
arguments!(list_len);
let result_layout = *layout;
let result_layout = layout;
list_with_capacity(
env,
layout_interner,
list_len.into_int_value(),
list_element_layout!(result_layout),
list_element_layout!(layout_interner, result_layout),
)
}
ListConcat => {
@ -664,14 +664,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let second_list = load_symbol(scope, &args[1]);
let element_layout = list_element_layout!(list_layout);
let element_layout = list_element_layout!(layout_interner, list_layout);
list_concat(
env,
layout_interner,
first_list,
second_list,
*element_layout,
element_layout,
)
}
ListAppendUnsafe => {
@ -697,7 +697,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
debug_assert_eq!(args.len(), 2);
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
let element_layout = list_element_layout!(list_layout);
let element_layout = list_element_layout!(layout_interner, list_layout);
let spare = load_symbol(scope, &args[1]);
list_reserve(
@ -705,7 +705,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
layout_interner,
list,
spare,
*element_layout,
element_layout,
update_mode,
)
}
@ -719,14 +719,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let index_1 = load_symbol(scope, &args[1]);
let index_2 = load_symbol(scope, &args[2]);
let element_layout = list_element_layout!(list_layout);
let element_layout = list_element_layout!(layout_interner, list_layout);
list_swap(
env,
layout_interner,
original_wrapper,
index_1.into_int_value(),
index_2.into_int_value(),
*element_layout,
element_layout,
update_mode,
)
}
@ -739,7 +739,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let start = load_symbol(scope, &args[1]);
let len = load_symbol(scope, &args[2]);
let element_layout = list_element_layout!(list_layout);
let element_layout = list_element_layout!(layout_interner, list_layout);
list_sublist(
env,
layout_interner,
@ -747,7 +747,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
original_wrapper,
start.into_int_value(),
len.into_int_value(),
*element_layout,
element_layout,
)
}
ListDropAt => {
@ -759,14 +759,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
let count = load_symbol(scope, &args[1]);
let element_layout = list_element_layout!(list_layout);
let element_layout = list_element_layout!(layout_interner, list_layout);
list_drop_at(
env,
layout_interner,
layout_ids,
original_wrapper,
count.into_int_value(),
*element_layout,
element_layout,
)
}
StrGetUnsafe => {
@ -789,7 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
env,
layout_interner,
layout_ids,
*list_element_layout!(list_layout),
list_element_layout!(layout_interner, list_layout),
element_index.into_int_value(),
wrapper_struct.into_struct_value(),
)
@ -824,7 +824,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
// Num.toStr : Num a -> Str
arguments_with_layouts!((num, num_layout));
match num_layout {
match layout_interner.get(num_layout) {
Layout::Builtin(Builtin::Int(int_width)) => {
let int = num.into_int_value();
@ -833,14 +833,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
&[],
&[int.into()],
BitcodeReturns::Str,
&bitcode::STR_FROM_INT[*int_width],
&bitcode::STR_FROM_INT[int_width],
)
}
Layout::Builtin(Builtin::Float(_float_width)) => {
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
let float_width = match float_layout {
Layout::Builtin(Builtin::Float(float_width)) => *float_width,
let float_width = match layout_interner.get(float_layout) {
Layout::Builtin(Builtin::Float(float_width)) => float_width,
_ => unreachable!(),
};
@ -861,19 +861,19 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
| NumToIntChecked => {
arguments_with_layouts!((arg, arg_layout));
match arg_layout {
match layout_interner.get(arg_layout) {
Layout::Builtin(arg_builtin) => {
use roc_mono::layout::Builtin::*;
match arg_builtin {
Int(int_width) => {
let int_type = convert::int_type_from_int_width(env, *int_width);
let int_type = convert::int_type_from_int_width(env, int_width);
build_int_unary_op(
env,
layout_interner,
parent,
arg.into_int_value(),
*int_width,
int_width,
int_type,
op,
layout,
@ -881,10 +881,11 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
}
Float(float_width) => build_float_unary_op(
env,
layout_interner,
layout,
arg.into_float_value(),
op,
*float_width,
float_width,
),
_ => {
unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout);
@ -925,7 +926,10 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
use inkwell::FloatPredicate;
match (lhs_layout, rhs_layout) {
match (
layout_interner.get(lhs_layout),
layout_interner.get(rhs_layout),
) {
(Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin))
if lhs_builtin == rhs_builtin =>
{
@ -1011,13 +1015,22 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
| NumSubChecked | NumSubSaturated | NumMulWrap | NumMulSaturated | NumMulChecked => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
build_num_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op)
build_num_binop(
env,
layout_interner,
parent,
lhs_arg,
lhs_layout,
rhs_arg,
rhs_layout,
op,
)
}
NumBitwiseAnd | NumBitwiseOr | NumBitwiseXor => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
debug_assert_eq!(lhs_layout, rhs_layout);
let int_width = intwidth_from_layout(*lhs_layout);
let int_width = intwidth_from_layout(lhs_layout);
build_int_binop(
env,
@ -1031,9 +1044,9 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
NumShiftLeftBy | NumShiftRightBy | NumShiftRightZfBy => {
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
let int_width = intwidth_from_layout(*lhs_layout);
let int_width = intwidth_from_layout(lhs_layout);
debug_assert_eq!(rhs_layout, &Layout::Builtin(Builtin::Int(IntWidth::U8)));
debug_assert_eq!(rhs_layout, Layout::U8);
let rhs_arg = if rhs_layout != lhs_layout {
// LLVM shift intrinsics expect the left and right sides to have the same type, so
// here we cast up `rhs` to the lhs type. Since the rhs was checked to be a U8,
@ -1061,7 +1074,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
arguments!(arg);
let to = basic_type_from_layout(env, layout_interner, layout).into_int_type();
let to_signed = intwidth_from_layout(*layout).is_signed();
let to_signed = intwidth_from_layout(layout).is_signed();
env.builder
.build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast")
@ -1070,7 +1083,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
NumToFloatCast => {
arguments_with_layouts!((arg, arg_layout));
match arg_layout {
match layout_interner.get(arg_layout) {
Layout::Builtin(Builtin::Int(width)) => {
// Converting from int to float
let int_val = arg.into_int_value();
@ -1198,12 +1211,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
}
}
fn intwidth_from_layout(layout: Layout) -> IntWidth {
match layout {
Layout::Builtin(Builtin::Int(int_width)) => int_width,
_ => unreachable!(),
}
fn intwidth_from_layout(layout: InLayout) -> IntWidth {
layout.to_int_width()
}
fn build_int_binop<'a, 'ctx, 'env>(
@ -1429,14 +1438,18 @@ fn build_int_binop<'a, 'ctx, 'env>(
pub fn build_num_binop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &STLayoutInterner<'a>,
parent: FunctionValue<'ctx>,
lhs_arg: BasicValueEnum<'ctx>,
lhs_layout: &Layout<'a>,
lhs_layout: InLayout<'a>,
rhs_arg: BasicValueEnum<'ctx>,
rhs_layout: &Layout<'a>,
rhs_layout: InLayout<'a>,
op: LowLevel,
) -> BasicValueEnum<'ctx> {
match (lhs_layout, rhs_layout) {
match (
layout_interner.get(lhs_layout),
layout_interner.get(rhs_layout),
) {
(Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin))
if lhs_builtin == rhs_builtin =>
{
@ -1446,7 +1459,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
Int(int_width) => build_int_binop(
env,
parent,
*int_width,
int_width,
lhs_arg.into_int_value(),
rhs_arg.into_int_value(),
op,
@ -1454,7 +1467,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
Float(float_width) => build_float_binop(
env,
*float_width,
float_width,
lhs_arg.into_float_value(),
rhs_arg.into_float_value(),
op,
@ -1786,9 +1799,9 @@ fn build_dec_binop<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
parent: FunctionValue<'ctx>,
lhs: BasicValueEnum<'ctx>,
_lhs_layout: &Layout<'a>,
_lhs_layout: InLayout<'a>,
rhs: BasicValueEnum<'ctx>,
_rhs_layout: &Layout<'a>,
_rhs_layout: InLayout<'a>,
op: LowLevel,
) -> BasicValueEnum<'ctx> {
use roc_module::low_level::LowLevel::*;
@ -1868,7 +1881,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
arg_width: IntWidth,
arg_int_type: IntType<'ctx>,
op: LowLevel,
return_layout: &Layout<'a>,
return_layout: InLayout<'a>,
) -> BasicValueEnum<'ctx> {
use roc_module::low_level::LowLevel::*;
@ -1886,9 +1899,9 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
NumToFrac => {
// This is an Int, so we need to convert it.
let target_float_type = match return_layout {
let target_float_type = match layout_interner.get(return_layout) {
Layout::Builtin(Builtin::Float(float_width)) => {
convert::float_type_from_float_width(env, *float_width)
convert::float_type_from_float_width(env, float_width)
}
_ => internal_error!("There can only be floats here!"),
};
@ -1903,16 +1916,10 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
NumToIntChecked => {
// return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool }
let target_int_width = match return_layout {
let target_int_width = match layout_interner.get(return_layout) {
Layout::Struct { field_layouts, .. } if field_layouts.len() == 2 => {
debug_assert!(matches!(field_layouts[1], Layout::Builtin(Builtin::Bool)));
match field_layouts[0] {
Layout::Builtin(Builtin::Int(iw)) => iw,
layout => internal_error!(
"There can only be an int layout here, found {:?}!",
layout
),
}
debug_assert!(matches!(field_layouts[1], Layout::BOOL));
field_layouts[0].to_int_width()
}
layout => internal_error!(
"There can only be a result layout here, found {:?}!",
@ -2017,7 +2024,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
load_roc_value(
env,
layout_interner,
*return_layout,
return_layout,
roc_return_alloca,
"num_to_int",
)
@ -2159,7 +2166,8 @@ fn int_abs_with_overflow<'a, 'ctx, 'env>(
fn build_float_unary_op<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout: &Layout<'a>,
layout_interner: &STLayoutInterner<'a>,
layout: InLayout<'a>,
arg: FloatValue<'ctx>,
op: LowLevel,
float_width: FloatWidth, // arg width
@ -2175,8 +2183,8 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
NumSqrtUnchecked => env.call_intrinsic(&LLVM_SQRT[float_width], &[arg.into()]),
NumLogUnchecked => env.call_intrinsic(&LLVM_LOG[float_width], &[arg.into()]),
NumToFrac => {
let return_width = match layout {
Layout::Builtin(Builtin::Float(return_width)) => *return_width,
let return_width = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Float(return_width)) => return_width,
_ => internal_error!("Layout for returning is not Float : {:?}", layout),
};
match (float_width, return_width) {
@ -2197,10 +2205,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
}
}
NumCeiling => {
let (return_signed, return_type) = match layout {
let (return_signed, return_type) = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(int_width)) => (
int_width.is_signed(),
convert::int_type_from_int_width(env, *int_width),
convert::int_type_from_int_width(env, int_width),
),
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
};
@ -2217,10 +2225,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
)
}
NumFloor => {
let (return_signed, return_type) = match layout {
let (return_signed, return_type) = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(int_width)) => (
int_width.is_signed(),
convert::int_type_from_int_width(env, *int_width),
convert::int_type_from_int_width(env, int_width),
),
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
};
@ -2237,10 +2245,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
)
}
NumRound => {
let (return_signed, return_type) = match layout {
let (return_signed, return_type) = match layout_interner.get(layout) {
Layout::Builtin(Builtin::Int(int_width)) => (
int_width.is_signed(),
convert::int_type_from_int_width(env, *int_width),
convert::int_type_from_int_width(env, int_width),
),
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
};
@ -2277,7 +2285,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
scope: &Scope<'a, 'ctx>,
return_layout: &Layout<'a>,
return_layout: InLayout<'a>,
func_spec: FuncSpec,
higher_order: &HigherOrderLowLevel<'a>,
) -> BasicValueEnum<'ctx> {
@ -2312,7 +2320,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
);
let (closure, closure_layout) =
load_symbol_and_lambda_set(scope, &captured_environment);
load_symbol_and_lambda_set(layout_interner, scope, &captured_environment);
(function, closure, closure_layout)
}};
@ -2325,14 +2333,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let (function, closure, closure_layout) = function_details!();
match (list_layout, return_layout) {
match (
layout_interner.get(list_layout),
layout_interner.get(return_layout),
) {
(
Layout::Builtin(Builtin::List(element_layout)),
Layout::Builtin(Builtin::List(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(
@ -2352,8 +2360,8 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
layout_interner,
roc_function_call,
list,
&element_layout,
&result_layout,
element_layout,
result_layout,
)
}
_ => unreachable!("invalid list layout"),
@ -2365,16 +2373,16 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let (function, closure, closure_layout) = function_details!();
match (list1_layout, list2_layout, return_layout) {
match (
layout_interner.get(list1_layout),
layout_interner.get(list2_layout),
layout_interner.get(return_layout),
) {
(
Layout::Builtin(Builtin::List(element1_layout)),
Layout::Builtin(Builtin::List(element2_layout)),
Layout::Builtin(Builtin::List(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(
@ -2396,9 +2404,9 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
roc_function_call,
list1,
list2,
&element1_layout,
&element2_layout,
&result_layout,
element1_layout,
element2_layout,
result_layout,
)
}
_ => unreachable!("invalid list layout"),
@ -2411,18 +2419,18 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let (function, closure, closure_layout) = function_details!();
match (list1_layout, list2_layout, list3_layout, return_layout) {
match (
layout_interner.get(list1_layout),
layout_interner.get(list2_layout),
layout_interner.get(list3_layout),
layout_interner.get(return_layout),
) {
(
Layout::Builtin(Builtin::List(element1_layout)),
Layout::Builtin(Builtin::List(element2_layout)),
Layout::Builtin(Builtin::List(element3_layout)),
Layout::Builtin(Builtin::List(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(
@ -2445,10 +2453,10 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list1,
list2,
list3,
&element1_layout,
&element2_layout,
&element3_layout,
&result_layout,
element1_layout,
element2_layout,
element3_layout,
result_layout,
)
}
_ => unreachable!("invalid list layout"),
@ -2463,11 +2471,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let (function, closure, closure_layout) = function_details!();
match (
list1_layout,
list2_layout,
list3_layout,
list4_layout,
return_layout,
layout_interner.get(list1_layout),
layout_interner.get(list2_layout),
layout_interner.get(list3_layout),
layout_interner.get(list4_layout),
layout_interner.get(return_layout),
) {
(
Layout::Builtin(Builtin::List(element1_layout)),
@ -2476,12 +2484,6 @@ 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 = 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,
element2_layout,
@ -2510,11 +2512,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
list2,
list3,
list4,
&element1_layout,
&element2_layout,
&element3_layout,
&element4_layout,
&result_layout,
element1_layout,
element2_layout,
element3_layout,
element4_layout,
result_layout,
)
}
_ => unreachable!("invalid list layout"),
@ -2526,12 +2528,10 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
let (function, closure, closure_layout) = function_details!();
match list_layout {
match layout_interner.get(list_layout) {
Layout::Builtin(Builtin::List(element_layout)) => {
use crate::llvm::bitcode::build_compare_wrapper;
let element_layout = layout_interner.get(*element_layout);
let argument_layouts = &[element_layout, element_layout];
let compare_wrapper = build_compare_wrapper(
@ -2539,7 +2539,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
layout_interner,
function,
closure_layout,
&element_layout,
element_layout,
)
.as_global_value()
.as_pointer_value();
@ -2562,7 +2562,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
roc_function_call,
compare_wrapper,
list,
&element_layout,
element_layout,
)
}
_ => unreachable!("invalid list layout"),
@ -2572,11 +2572,12 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
}
fn load_symbol_and_lambda_set<'a, 'ctx, 'b>(
layout_interner: &STLayoutInterner<'a>,
scope: &'b Scope<'a, 'ctx>,
symbol: &Symbol,
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
match scope.get(symbol) {
Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, *lambda_set),
match scope.get(symbol).map(|(l, v)| (layout_interner.get(*l), v)) {
Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set),
Some((other, ptr)) => panic!("Not a lambda set: {:?}, {:?}", other, ptr),
None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope),
}

View file

@ -113,7 +113,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
fn modify<'a, 'env>(
&self,
mode: CallMode<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
) {
@ -131,10 +131,10 @@ impl<'ctx> PointerToRefcount<'ctx> {
&self,
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) {
let alignment = layout
.allocation_alignment_bytes(layout_interner, env.target_info)
let alignment = layout_interner
.allocation_alignment_bytes(layout)
.max(env.target_info.ptr_width() as u32);
let context = env.context;
@ -275,28 +275,28 @@ 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>],
layouts: &'a [InLayout<'a>],
mode: Mode,
when_recursive: &WhenRecursive<'a>,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
let layout = Layout::struct_no_name_order(layouts);
let layout = layout_interner.insert(Layout::struct_no_name_order(layouts));
let (_, fn_name) = function_name_from_mode(
layout_ids,
&env.interns,
"increment_struct",
"decrement_struct",
&layout,
layout,
mode,
);
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_interner, &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(
@ -327,7 +327,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layouts: &[Layout<'a>],
layouts: &[InLayout<'a>],
fn_val: FunctionValue<'ctx>,
) {
let builder = env.builder;
@ -349,7 +349,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(layout_interner) {
if layout_interner.contains_refcounted(*field_layout) {
let raw_value = env
.builder
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
@ -370,7 +370,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
mode.to_call_mode(fn_val),
when_recursive,
field_value,
field_layout,
*field_layout,
);
}
}
@ -384,7 +384,7 @@ pub fn increment_refcount_layout<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
inc_amount: u64,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) {
let amount = env.ptr_int().const_int(inc_amount, false);
increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout);
@ -396,7 +396,7 @@ pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
amount: IntValue<'ctx>,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) {
modify_refcount_layout(
env,
@ -413,7 +413,7 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) {
modify_refcount_layout(
env,
@ -431,7 +431,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
builtin: &Builtin<'a>,
) -> Option<FunctionValue<'ctx>> {
use Builtin::*;
@ -471,7 +471,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
call_mode: CallMode<'ctx>,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) {
modify_refcount_layout_help(
env,
@ -491,7 +491,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
call_mode: CallMode<'ctx>,
when_recursive: &WhenRecursive<'a>,
value: BasicValueEnum<'ctx>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) {
let mode = match call_mode {
CallMode::Inc(_) => Mode::Inc,
@ -510,15 +510,15 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
None => return,
};
match layout {
match layout_interner.get(layout) {
Layout::RecursivePointer => match when_recursive {
WhenRecursive::Unreachable => {
unreachable!("recursion pointers should never be hashed directly")
}
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(*union_layout);
let layout = layout_interner.insert(Layout::Union(*union_layout));
let bt = basic_type_from_layout(env, layout_interner, &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(
@ -569,11 +569,11 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
) -> Option<FunctionValue<'ctx>> {
use Layout::*;
match layout {
match layout_interner.get(layout) {
Builtin(builtin) => modify_refcount_builtin(
env,
layout_interner,
@ -581,11 +581,11 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
mode,
when_recursive,
layout,
builtin,
&builtin,
),
Boxed(inner) => {
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, *inner);
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, inner);
Some(function)
}
@ -618,8 +618,8 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
mode,
&WhenRecursive::Loop(*variant),
*variant,
&WhenRecursive::Loop(variant),
variant,
);
Some(function)
@ -645,7 +645,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
unreachable!("recursion pointers cannot be in/decremented directly")
}
WhenRecursive::Loop(union_layout) => {
let layout = Layout::Union(*union_layout);
let layout = layout_interner.insert(Layout::Union(*union_layout));
let function = modify_refcount_layout_build_function(
env,
@ -653,7 +653,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
when_recursive,
&layout,
layout,
)?;
Some(function)
@ -665,7 +665,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
when_recursive,
&lambda_set.runtime_representation(layout_interner),
lambda_set.runtime_representation(),
),
}
}
@ -684,7 +684,7 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
let element_layout = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
let element_layout = layout_interner.insert(element_layout);
let list_layout = &Layout::Builtin(Builtin::List(element_layout));
let list_layout = layout_interner.insert(Layout::Builtin(Builtin::List(element_layout)));
let (_, fn_name) = function_name_from_mode(
layout_ids,
&env.interns,
@ -735,7 +735,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
layout: &Layout<'a>,
layout: InLayout<'a>,
element_layout: InLayout<'a>,
fn_val: FunctionValue<'ctx>,
) {
@ -775,9 +775,8 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
builder.position_at_end(modification_block);
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)
if layout_interner.contains_refcounted(element_layout) {
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);
@ -790,7 +789,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
mode.to_call_mode(fn_val),
when_recursive,
element,
&element_layout,
element_layout,
);
};
@ -823,7 +822,7 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
layout_interner: &mut STLayoutInterner<'a>,
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
layout: &Layout<'a>,
layout: InLayout<'a>,
) -> FunctionValue<'ctx> {
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
@ -860,7 +859,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
env: &Env<'a, 'ctx, 'env>,
layout_interner: &mut STLayoutInterner<'a>,
mode: Mode,
layout: &Layout<'a>,
layout: InLayout<'a>,
fn_val: FunctionValue<'ctx>,
) {
let builder = env.builder;
@ -936,7 +935,7 @@ fn modify_refcount_boxed<'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 boxed_layout = env.arena.alloc(Layout::Boxed(inner_layout));
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
let (_, fn_name) = function_name_from_mode(
layout_ids,
@ -991,8 +990,8 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>(
let boxed = arg_val.into_pointer_value();
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, layout_interner);
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
// this function returns void
builder.build_return(None);
@ -1097,14 +1096,14 @@ fn build_rec_union<'a, 'ctx, 'env>(
when_recursive: &WhenRecursive<'a>,
union_layout: UnionLayout<'a>,
) -> FunctionValue<'ctx> {
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
let (_, fn_name) = function_name_from_mode(
layout_ids,
&env.interns,
"increment_rec_union",
"decrement_rec_union",
&layout,
layout,
mode,
);
@ -1114,7 +1113,7 @@ 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_interner, &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(
@ -1203,12 +1202,12 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
let call_mode = mode_to_call_mode(fn_val, mode);
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
match mode {
Mode::Inc => {
// inc is cheap; we never recurse
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
refcount_ptr.modify(call_mode, layout, env, layout_interner);
env.builder.build_return(None);
}
@ -1225,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, layout_interner);
refcount_ptr.modify(call_mode, layout, env, layout_interner);
env.builder.build_return(None);
}
@ -1257,10 +1256,11 @@ enum DecOrReuse {
Reuse,
}
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[Layout]) -> bool {
!field_layouts
.iter()
.any(|x| x.is_refcounted() || x.contains_refcounted(interner))
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLayout]) -> bool {
!field_layouts.iter().any(|x| {
let x = interner.get(*x);
x.is_refcounted() || x.contains_refcounted(interner)
})
}
#[allow(clippy::too_many_arguments)]
@ -1289,7 +1289,7 @@ 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, layout_interner, &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() {
let tag_id = match nullable_id {
@ -1310,11 +1310,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
env.builder.position_at_end(block);
let wrapper_type = basic_type_from_layout(
env,
layout_interner,
&Layout::struct_no_name_order(field_layouts),
);
let fields_struct = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct);
// cast the opaque pointer to a pointer of the correct shape
let struct_ptr = env.builder.build_pointer_cast(
@ -1329,7 +1326,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
let mut deferred_nonrec = Vec::new_in(env.arena);
for (i, field_layout) in field_layouts.iter().enumerate() {
if let Layout::RecursivePointer = field_layout {
if let Layout::RecursivePointer = layout_interner.get(*field_layout) {
// this field has type `*i64`, but is really a pointer to the data we want
let elem_pointer = env
.builder
@ -1350,12 +1347,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_interner, &Layout::Union(union_layout));
let union_layout = layout_interner.insert(Layout::Union(union_layout));
let union_type = basic_type_from_layout(env, layout_interner, 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(layout_interner) {
} else if layout_interner.contains_refcounted(*field_layout) {
let elem_pointer = env
.builder
.new_build_struct_gep(
@ -1388,12 +1385,8 @@ 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,
layout_interner,
);
let union_layout = layout_interner.insert(Layout::Union(union_layout));
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
}
}
@ -1405,7 +1398,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
mode.to_call_mode(decrement_fn),
when_recursive,
field,
field_layout,
*field_layout,
);
}
@ -1446,12 +1439,8 @@ 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,
layout_interner,
);
let union_layout = layout_interner.insert(Layout::Union(union_layout));
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
}
}
@ -1462,7 +1451,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
struct UnionLayoutTags<'a> {
nullable_id: Option<u16>,
tags: &'a [&'a [Layout<'a>]],
tags: &'a [&'a [InLayout<'a>]],
}
fn union_layout_tags<'a>(
@ -1509,7 +1498,8 @@ pub fn build_reset<'a, 'ctx, 'env>(
) -> FunctionValue<'ctx> {
let mode = Mode::Dec;
let layout_id = layout_ids.get(Symbol::DEC, &Layout::Union(union_layout));
let union_layout_in = layout_interner.insert(Layout::Union(union_layout));
let layout_id = layout_ids.get(Symbol::DEC, &union_layout_in);
let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns);
let fn_name = format!("{}_reset", fn_name);
@ -1529,8 +1519,7 @@ 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_interner, &Layout::Union(union_layout));
let basic_type = basic_type_from_layout(env, layout_interner, union_layout_in);
let function_value = build_header(env, basic_type, mode, &fn_name);
build_reuse_rec_union_help(
@ -1616,7 +1605,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
env.builder.position_at_end(should_recurse_block);
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
let do_recurse_block = env.context.append_basic_block(parent, "do_recurse");
let no_recurse_block = env.context.append_basic_block(parent, "no_recurse");
@ -1626,7 +1615,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, layout_interner);
refcount_ptr.modify(call_mode, layout, env, layout_interner);
env.builder.build_return(None);
}
@ -1656,7 +1645,7 @@ fn function_name_from_mode<'a>(
interns: &Interns,
if_inc: &'static str,
if_dec: &'static str,
layout: &Layout<'a>,
layout: InLayout<'a>,
mode: Mode,
) -> (&'static str, String) {
// NOTE this is not a typo, we always determine the layout ID
@ -1664,7 +1653,7 @@ fn function_name_from_mode<'a>(
// decremented, so `dec` is used on more layouts. That can cause the
// layout ids of the inc and dec versions to be different, which is
// rather confusing, so now `inc_x` always corresponds to `dec_x`
let layout_id = layout_ids.get(Symbol::DEC, layout);
let layout_id = layout_ids.get(Symbol::DEC, &layout);
match mode {
Mode::Inc => (if_inc, layout_id.to_symbol_string(Symbol::INC, interns)),
Mode::Dec => (if_dec, layout_id.to_symbol_string(Symbol::DEC, interns)),
@ -1677,10 +1666,10 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
fields: &'a [&'a [Layout<'a>]],
fields: &'a [&'a [InLayout<'a>]],
) -> FunctionValue<'ctx> {
let union_layout = UnionLayout::NonRecursive(fields);
let layout = Layout::Union(union_layout);
let layout = layout_interner.insert(Layout::Union(union_layout));
let block = env.builder.get_insert_block().expect("to be in a function");
let di_location = env.builder.get_current_debug_location().unwrap();
@ -1690,7 +1679,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
&env.interns,
"increment_union",
"decrement_union",
&layout,
layout,
mode,
);
@ -1727,7 +1716,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
layout_ids: &mut LayoutIds<'a>,
mode: Mode,
when_recursive: &WhenRecursive<'a>,
tags: &[&[Layout<'a>]],
tags: &'a [&'a [InLayout<'a>]],
fn_val: FunctionValue<'ctx>,
) {
debug_assert!(!tags.is_empty());
@ -1753,9 +1742,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
let before_block = env.builder.get_insert_block().expect("to be in a function");
let union_layout = UnionLayout::NonRecursive(tags);
let layout = Layout::Union(union_layout);
let union_struct_type =
basic_type_from_layout(env, layout_interner, &layout).into_struct_type();
let layout = layout_interner.insert(Layout::Union(union_layout));
let union_struct_type = basic_type_from_layout(env, layout_interner, layout).into_struct_type();
// read the tag_id
let tag_id_ptr = env
@ -1771,7 +1759,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
let tag_id = env
.builder
.new_build_load(
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()),
basic_type_from_layout(env, layout_interner, union_layout.tag_id_layout()),
tag_id_ptr,
"load_tag_id",
)
@ -1790,21 +1778,18 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
for (tag_id, field_layouts) in tags.iter().enumerate() {
// if none of the fields are or contain anything refcounted, just move on
if !field_layouts
.iter()
.any(|x| x.is_refcounted() || x.contains_refcounted(layout_interner))
{
if !field_layouts.iter().any(|x| {
let x = layout_interner.get(*x);
x.is_refcounted() || x.contains_refcounted(layout_interner)
}) {
continue;
}
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_interner,
&Layout::struct_no_name_order(field_layouts),
);
let fields_struct = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
let data_struct_type = basic_type_from_layout(env, layout_interner, fields_struct);
debug_assert!(data_struct_type.is_struct_type());
let data_struct_type = data_struct_type.into_struct_type();
@ -1825,7 +1810,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
);
for (i, field_layout) in field_layouts.iter().enumerate() {
if let Layout::RecursivePointer = field_layout {
if let Layout::RecursivePointer = layout_interner.get(*field_layout) {
let recursive_union_layout = match when_recursive {
WhenRecursive::Unreachable => {
panic!("non-recursive tag unions cannot contain naked recursion pointers!");
@ -1854,11 +1839,8 @@ 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_interner,
&Layout::Union(*recursive_union_layout),
);
let union_layout = layout_interner.insert(Layout::Union(*recursive_union_layout));
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
let recursive_ptr_field_value =
cast_basic_basic(env.builder, field_value, union_type);
@ -1869,9 +1851,9 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
mode.to_call_mode(fn_val),
when_recursive,
recursive_ptr_field_value,
&Layout::RecursivePointer,
Layout::RECURSIVE_PTR,
)
} else if field_layout.contains_refcounted(layout_interner) {
} else if layout_interner.contains_refcounted(*field_layout) {
let field_ptr = env
.builder
.new_build_struct_gep(
@ -1882,16 +1864,15 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
)
.unwrap();
let field_value =
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, layout_interner, field_layout),
field_ptr,
"field_value",
)
};
let field_value = if layout_interner.is_passed_by_reference(*field_layout) {
field_ptr.into()
} else {
env.builder.new_build_load(
basic_type_from_layout(env, layout_interner, *field_layout),
field_ptr,
"field_value",
)
};
modify_refcount_layout_help(
env,
@ -1900,7 +1881,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
mode.to_call_mode(fn_val),
when_recursive,
field_value,
field_layout,
*field_layout,
);
}
}