mirror of
https://github.com/roc-lang/roc.git
synced 2025-07-24 06:55:15 +00:00
Update llvm backend
This commit is contained in:
parent
9d70c45781
commit
03ece6e274
10 changed files with 696 additions and 701 deletions
|
@ -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
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
||||
|
|
|
@ -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) =
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue