Merge remote-tracking branch 'origin/main' into glue-getters-rtfeldman

This commit is contained in:
Folkert 2023-01-18 20:06:26 +01:00
commit bb44063419
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
248 changed files with 10064 additions and 5244 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

@ -10,9 +10,8 @@ use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, Str
use inkwell::{AddressSpace, IntPredicate};
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, STLayoutInterner};
use roc_mono::layout::{Builtin, InLayout, LayoutIds, LayoutInterner, STLayoutInterner};
use super::bitcode::{call_list_bitcode_fn, BitcodeReturns};
use super::build::{
@ -64,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");
@ -84,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()
}
@ -113,7 +109,6 @@ 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,
&[],
@ -137,7 +132,6 @@ 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 ptr_type = elem_type.ptr_type(AddressSpace::Generic);
// Load the pointer to the array data
@ -157,7 +151,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
let result = load_roc_value(
env,
layout_interner,
*element_layout,
element_layout,
elem_ptr,
"list_get_load_element",
);
@ -176,7 +170,6 @@ 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(),
@ -196,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,
@ -215,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,
@ -239,7 +232,6 @@ 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,
@ -264,7 +256,6 @@ 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);
call_list_bitcode_fn_1(
env,
@ -289,7 +280,6 @@ 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);
call_list_bitcode_fn_1(
env,
@ -312,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);
@ -328,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),
],
@ -340,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),
],
@ -355,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 {
@ -444,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,
@ -467,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,
@ -493,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);
@ -528,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);
@ -572,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);
@ -620,7 +610,6 @@ 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()],
@ -637,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,
@ -648,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,
@ -771,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

@ -12,9 +12,10 @@ use inkwell::values::{
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
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, STLayoutInterner, UnionLayout};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
};
use super::build::{load_roc_value, use_roc_value, BuilderExt};
use super::convert::argument_type_from_union_layout;
@ -26,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,
@ -47,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,
@ -128,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,
)
}
}
}
@ -147,12 +151,12 @@ 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 = &layout_interner.runtime_representation_in(lhs_layout);
let rhs_layout = &layout_interner.runtime_representation_in(rhs_layout);
if lhs_layout != rhs_layout {
panic!(
"Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}",
@ -160,14 +164,14 @@ fn build_eq<'a, 'ctx, 'env>(
);
}
match lhs_layout {
match layout_interner.get(*lhs_layout) {
Layout::Builtin(builtin) => build_eq_builtin(
env,
layout_interner,
layout_ids,
lhs_val,
rhs_val,
builtin,
&builtin,
when_recursive,
),
@ -188,7 +192,7 @@ fn build_eq<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
when_recursive,
union_layout,
&union_layout,
lhs_val,
rhs_val,
),
@ -198,8 +202,8 @@ fn build_eq<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
when_recursive,
lhs_layout,
*inner_layout,
*lhs_layout,
inner_layout,
lhs_val,
rhs_val,
),
@ -210,9 +214,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(
@ -313,11 +317,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(),
@ -338,8 +343,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 {
@ -349,14 +354,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,
),
@ -383,7 +388,7 @@ fn build_neq<'a, 'ctx, 'env>(
layout_interner,
layout_ids,
when_recursive,
union_layout,
&union_layout,
lhs_val,
rhs_val,
)
@ -401,7 +406,7 @@ fn build_neq<'a, 'ctx, 'env>(
layout_ids,
when_recursive,
lhs_layout,
*inner_layout,
inner_layout,
lhs_val,
rhs_val,
)
@ -423,7 +428,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>,
@ -434,7 +439,8 @@ 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 = 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);
@ -457,7 +463,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
layout_ids,
when_recursive,
function_value,
&element_layout,
element_layout,
);
function_value
@ -482,7 +488,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;
@ -581,14 +587,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(
@ -640,7 +646,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>,
@ -648,7 +654,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
@ -658,7 +664,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,
@ -698,7 +704,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;
@ -755,15 +761,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(
@ -784,8 +790,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()
@ -800,8 +806,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()
@ -841,7 +847,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)
@ -1284,13 +1290,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
@ -1335,7 +1341,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>,
@ -1345,7 +1351,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()) {
@ -1455,10 +1461,8 @@ 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");
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,

View file

@ -5,19 +5,20 @@ use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
use inkwell::values::StructValue;
use inkwell::AddressSpace;
use roc_builtins::bitcode::{FloatWidth, IntWidth};
use roc_intern::Interner;
use roc_mono::layout::{round_up_to_alignment, Builtin, Layout, STLayoutInterner, UnionLayout};
use roc_mono::layout::{
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
@ -28,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);
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),
}
}
@ -147,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),
}
}
@ -300,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() {
@ -317,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

@ -9,10 +9,11 @@ use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
use inkwell::AddressSpace;
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, STLayoutInterner, UnionLayout};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
};
use roc_region::all::Region;
use super::build::BuilderExt;
@ -200,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");
@ -219,7 +219,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
original_ptr,
cursors,
value,
*layout,
layout,
WhenRecursive::Unreachable,
);
@ -285,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,
@ -316,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(),
@ -353,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 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
@ -377,7 +375,7 @@ fn build_clone<'a, 'ctx, 'env>(
ptr,
cursors,
value,
*inner_layout,
inner_layout,
when_recursive,
)
}
@ -388,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(
@ -421,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);
@ -452,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
@ -477,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);
@ -632,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,
@ -691,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, _) =
@ -749,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);
@ -815,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);
@ -899,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",
),
};
@ -1042,16 +1037,18 @@ 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) {
// We clone the elements into the extra_offset address.
let _ = offset;
let elements_start_offset = cursors.extra_offset;
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 dest = pointer_at_offset(bd, env.context.i8_type(), ptr, elements_start_offset);
let src = bd.build_pointer_cast(
elements,
env.context.i8_type().ptr_type(AddressSpace::Generic),
@ -1059,11 +1056,8 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
);
bd.build_memcpy(dest, 1, src, 1, elements_width).unwrap();
bd.build_int_add(offset, elements_width, "new_offset")
bd.build_int_add(elements_start_offset, elements_width, "new_offset")
} else {
// 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 elements = bd.build_pointer_cast(
elements,
@ -1074,10 +1068,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"),
@ -1108,7 +1101,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
ptr,
cursors,
element,
*elem,
elem,
when_recursive,
);
@ -1125,7 +1118,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
env,
layout_interner,
parent,
*elem,
elem,
elements,
len,
"index",

View file

@ -9,11 +9,10 @@ use inkwell::{
use morphic_lib::{FuncSpec, UpdateMode};
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
use roc_error_macros::internal_error;
use roc_intern::Interner;
use roc_module::{low_level::LowLevel, symbol::Symbol};
use roc_mono::{
ir::HigherOrderLowLevel,
layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner},
layout::{Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner},
};
use roc_target::PtrWidth;
@ -51,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"),
}
@ -65,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,
@ -201,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,
@ -228,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
@ -268,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",
)
@ -276,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())
@ -322,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!(),
};
@ -341,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!(),
};
@ -650,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 => {
@ -665,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 => {
@ -698,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(
@ -706,7 +705,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
layout_interner,
list,
spare,
*element_layout,
element_layout,
update_mode,
)
}
@ -720,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,
)
}
@ -740,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,
@ -748,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 => {
@ -760,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 => {
@ -790,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(),
)
@ -825,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();
@ -834,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!(),
};
@ -862,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,
@ -882,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);
@ -926,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 =>
{
@ -1012,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,
@ -1032,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,
@ -1062,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")
@ -1071,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();
@ -1199,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>(
@ -1430,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 =>
{
@ -1447,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,
@ -1455,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,
@ -1787,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::*;
@ -1869,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::*;
@ -1887,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!"),
};
@ -1904,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 {:?}!",
@ -2018,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",
)
@ -2160,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
@ -2176,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) {
@ -2198,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),
};
@ -2218,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),
};
@ -2238,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),
};
@ -2278,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> {
@ -2313,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)
}};
@ -2326,15 +2333,15 @@ 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 argument_layouts = &[element_layout];
let roc_function_call = roc_function_call(
env,
@ -2345,7 +2352,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_map(
@ -2366,17 +2373,17 @@ 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 argument_layouts = &[element1_layout, element2_layout];
let roc_function_call = roc_function_call(
env,
@ -2387,7 +2394,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_map2(
@ -2412,19 +2419,19 @@ 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 argument_layouts = &[element1_layout, element2_layout, element3_layout];
let roc_function_call = roc_function_call(
env,
@ -2435,7 +2442,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_map3(
@ -2464,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)),
@ -2477,17 +2484,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 = 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,
*element3_layout,
*element4_layout,
element1_layout,
element2_layout,
element3_layout,
element4_layout,
];
let roc_function_call = roc_function_call(
@ -2499,7 +2500,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
closure_layout,
function_owns_closure_data,
argument_layouts,
*result_layout,
result_layout,
);
list_map4(
@ -2527,13 +2528,11 @@ 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 argument_layouts = &[element_layout, element_layout];
let compare_wrapper = build_compare_wrapper(
env,
@ -2573,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

@ -5,7 +5,7 @@ use crate::llvm::build::{
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, use_roc_value, Env,
WhenRecursive, FAST_CALL_CONV,
};
use crate::llvm::build_list::{incrementing_elem_loop, list_len, load_list};
use crate::llvm::build_list::{incrementing_elem_loop, list_capacity, load_list};
use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion};
use bumpalo::collections::Vec;
use inkwell::basic_block::BasicBlock;
@ -15,10 +15,11 @@ use inkwell::values::{
BasicValue, BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue,
};
use inkwell::{AddressSpace, IntPredicate};
use roc_intern::Interner;
use roc_module::symbol::Interns;
use roc_module::symbol::Symbol;
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner, UnionLayout};
use roc_mono::layout::{
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
};
use super::build::{cast_if_necessary_for_opaque_recursive_pointers, load_roc_value, FunctionSpec};
use super::convert::{argument_type_from_layout, argument_type_from_union_layout};
@ -112,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>,
) {
@ -130,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;
@ -274,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(
@ -326,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;
@ -348,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")
@ -369,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,
);
}
}
@ -383,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);
@ -395,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,
@ -412,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,
@ -430,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::*;
@ -470,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,
@ -490,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,
@ -509,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(
@ -568,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,
@ -580,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)
}
@ -617,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)
@ -644,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,
@ -652,7 +653,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
layout_ids,
mode,
when_recursive,
&layout,
layout,
)?;
Some(function)
@ -664,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(),
),
}
}
@ -681,9 +682,9 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
let di_location = env.builder.get_current_debug_location().unwrap();
let element_layout = layout_interner.get(element_layout);
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
let element_layout = layout_interner.insert(env.arena.alloc(element_layout));
let list_layout = &Layout::Builtin(Builtin::List(element_layout));
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
let element_layout = layout_interner.insert(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,
@ -734,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>,
) {
@ -757,7 +758,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
let parent = fn_val;
let original_wrapper = arg_val.into_struct_value();
let len = list_len(builder, original_wrapper);
let len = list_capacity(builder, original_wrapper);
let is_non_empty = builder.build_int_compare(
IntPredicate::UGT,
@ -774,8 +775,7 @@ 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) {
if layout_interner.contains_refcounted(element_layout) {
let ptr_type = basic_type_from_layout(env, layout_interner, element_layout)
.ptr_type(AddressSpace::Generic);
@ -797,7 +797,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
env,
layout_interner,
parent,
*element_layout,
element_layout,
ptr,
len,
"modify_rc_index",
@ -822,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();
@ -859,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;
@ -935,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,
@ -990,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);
@ -1096,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,
);
@ -1113,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(
@ -1148,7 +1148,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
fn_val: FunctionValue<'ctx>,
) {
let tags = union_layout_tags(env.arena, &union_layout);
debug_assert!(!tags.is_empty());
debug_assert!(!tags.tags.is_empty());
let context = &env.context;
let builder = env.builder;
@ -1202,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);
}
@ -1224,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);
}
@ -1256,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)]
@ -1271,7 +1272,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
parent: FunctionValue<'ctx>,
decrement_fn: FunctionValue<'ctx>,
union_layout: UnionLayout<'a>,
tags: &[&[Layout<'a>]],
tags: UnionLayoutTags<'a>,
value_ptr: PointerValue<'ctx>,
current_tag_id: IntValue<'ctx>,
refcount_ptr: PointerToRefcount<'ctx>,
@ -1282,13 +1283,24 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
let call_mode = mode_to_call_mode(decrement_fn, mode);
let builder = env.builder;
let UnionLayoutTags { nullable_id, tags } = tags;
// next, make a jump table for all possible values of the tag_id
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 {
Some(null_id) if tag_id as u16 >= null_id => {
// This tag comes after the nullable tag, so its ID is one higher than the
// enumeration says.
tag_id + 1
}
_ => tag_id,
};
// if none of the fields are or contain anything refcounted, just move on
if fields_need_no_refcounting(layout_interner, field_layouts) {
continue;
@ -1298,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(
@ -1317,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
@ -1338,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(
@ -1376,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);
}
}
@ -1393,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,
);
}
@ -1434,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);
}
}
@ -1448,20 +1449,44 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
}
}
struct UnionLayoutTags<'a> {
nullable_id: Option<u16>,
tags: &'a [&'a [InLayout<'a>]],
}
fn union_layout_tags<'a>(
arena: &'a bumpalo::Bump,
union_layout: &UnionLayout<'a>,
) -> &'a [&'a [Layout<'a>]] {
) -> UnionLayoutTags<'a> {
use UnionLayout::*;
match union_layout {
NullableWrapped {
other_tags: tags, ..
} => tags,
NullableUnwrapped { other_fields, .. } => arena.alloc([*other_fields]),
NonNullableUnwrapped(fields) => arena.alloc([*fields]),
Recursive(tags) => tags,
NonRecursive(tags) => tags,
other_tags,
nullable_id,
} => UnionLayoutTags {
nullable_id: Some(*nullable_id),
tags: other_tags,
},
NullableUnwrapped {
other_fields,
nullable_id,
} => UnionLayoutTags {
nullable_id: Some(*nullable_id as u16),
tags: arena.alloc([*other_fields]),
},
NonNullableUnwrapped(fields) => UnionLayoutTags {
nullable_id: None,
tags: arena.alloc([*fields]),
},
Recursive(tags) => UnionLayoutTags {
nullable_id: None,
tags,
},
NonRecursive(tags) => UnionLayoutTags {
nullable_id: None,
tags,
},
}
}
@ -1473,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);
@ -1493,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(
@ -1530,7 +1555,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
) {
let tags = union_layout_tags(env.arena, &union_layout);
debug_assert!(!tags.is_empty());
debug_assert!(!tags.tags.is_empty());
let context = &env.context;
let builder = env.builder;
@ -1580,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");
@ -1590,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);
}
@ -1620,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
@ -1628,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)),
@ -1641,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();
@ -1654,7 +1679,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
&env.interns,
"increment_union",
"decrement_union",
&layout,
layout,
mode,
);
@ -1691,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());
@ -1717,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
@ -1735,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",
)
@ -1754,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();
@ -1789,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!");
@ -1818,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);
@ -1833,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(
@ -1846,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,
@ -1864,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,
);
}
}