mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 04:08:19 +00:00
Merge remote-tracking branch 'origin/main' into glue-getters-rtfeldman
This commit is contained in:
commit
bb44063419
248 changed files with 10064 additions and 5244 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
|
@ -10,9 +10,8 @@ use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue, Str
|
|||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use morphic_lib::UpdateMode;
|
||||
use roc_builtins::bitcode;
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner};
|
||||
use roc_mono::layout::{Builtin, InLayout, LayoutIds, LayoutInterner, STLayoutInterner};
|
||||
|
||||
use super::bitcode::{call_list_bitcode_fn, BitcodeReturns};
|
||||
use super::build::{
|
||||
|
@ -64,9 +63,9 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
layout: Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let element_ptr = env
|
||||
.builder
|
||||
.build_alloca(element_type, "element_to_pass_as_opaque");
|
||||
|
@ -84,13 +83,10 @@ fn pass_element_as_opaque<'a, 'ctx, 'env>(
|
|||
pub(crate) fn layout_width<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
env.ptr_int()
|
||||
.const_int(
|
||||
layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
)
|
||||
.const_int(layout_interner.stack_size(layout) as u64, false)
|
||||
.into()
|
||||
}
|
||||
|
||||
|
@ -113,7 +109,6 @@ pub(crate) fn list_with_capacity<'a, 'ctx, 'env>(
|
|||
capacity: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
&[],
|
||||
|
@ -137,7 +132,6 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
|
|||
) -> BasicValueEnum<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let elem_type = basic_type_from_layout(env, layout_interner, element_layout);
|
||||
let ptr_type = elem_type.ptr_type(AddressSpace::Generic);
|
||||
// Load the pointer to the array data
|
||||
|
@ -157,7 +151,7 @@ pub(crate) fn list_get_unsafe<'a, 'ctx, 'env>(
|
|||
let result = load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*element_layout,
|
||||
element_layout,
|
||||
elem_ptr,
|
||||
"list_get_load_element",
|
||||
);
|
||||
|
@ -176,7 +170,6 @@ pub(crate) fn list_reserve<'a, 'ctx, 'env>(
|
|||
element_layout: InLayout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
list.into_struct_value(),
|
||||
|
@ -196,13 +189,13 @@ pub(crate) fn list_append_unsafe<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
bitcode::LIST_APPEND_UNSAFE,
|
||||
|
@ -215,14 +208,14 @@ pub(crate) fn list_prepend<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
original_wrapper: StructValue<'ctx>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
original_wrapper,
|
||||
&[
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
],
|
||||
bitcode::LIST_PREPEND,
|
||||
|
@ -239,7 +232,6 @@ pub(crate) fn list_swap<'a, 'ctx, 'env>(
|
|||
element_layout: InLayout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
original_wrapper,
|
||||
|
@ -264,7 +256,6 @@ pub(crate) fn list_sublist<'a, 'ctx, 'env>(
|
|||
len: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
|
@ -289,7 +280,6 @@ pub(crate) fn list_drop_at<'a, 'ctx, 'env>(
|
|||
count: IntValue<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let dec_element_fn = build_dec_wrapper(env, layout_interner, layout_ids, element_layout);
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
|
@ -312,7 +302,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
list: BasicValueEnum<'ctx>,
|
||||
index: IntValue<'ctx>,
|
||||
element: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
update_mode: UpdateMode,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
|
||||
|
@ -328,7 +318,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
list.into_struct_value(),
|
||||
&[
|
||||
index.into(),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
pass_as_opaque(env, element_ptr),
|
||||
],
|
||||
|
@ -340,7 +330,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
&[
|
||||
env.alignment_intvalue(layout_interner, element_layout),
|
||||
index.into(),
|
||||
pass_element_as_opaque(env, layout_interner, element, *element_layout),
|
||||
pass_element_as_opaque(env, layout_interner, element, element_layout),
|
||||
layout_width(env, layout_interner, element_layout),
|
||||
pass_as_opaque(env, element_ptr),
|
||||
],
|
||||
|
@ -355,7 +345,7 @@ pub(crate) fn list_replace_unsafe<'a, 'ctx, 'env>(
|
|||
|
||||
// the list has the same alignment as a usize / ptr. The element comes first in the struct if
|
||||
// its alignment is bigger than that of a list.
|
||||
let element_align = element_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
let element_align = layout_interner.alignment_bytes(element_layout);
|
||||
let element_first = element_align > env.target_info.ptr_width() as u32;
|
||||
|
||||
let fields = if element_first {
|
||||
|
@ -444,7 +434,7 @@ pub(crate) fn list_sort_with<'a, 'ctx, 'env>(
|
|||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
compare_wrapper: PointerValue<'ctx>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
|
@ -467,8 +457,8 @@ pub(crate) fn list_map<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list: BasicValueEnum<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
return_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
return_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
call_list_bitcode_fn_1(
|
||||
env,
|
||||
|
@ -493,9 +483,9 @@ pub(crate) fn list_map2<'a, 'ctx, 'env>(
|
|||
roc_function_call: RocFunctionCall<'ctx>,
|
||||
list1: BasicValueEnum<'ctx>,
|
||||
list2: BasicValueEnum<'ctx>,
|
||||
element1_layout: &Layout<'a>,
|
||||
element2_layout: &Layout<'a>,
|
||||
return_layout: &Layout<'a>,
|
||||
element1_layout: InLayout<'a>,
|
||||
element2_layout: InLayout<'a>,
|
||||
return_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
|
||||
|
@ -528,10 +518,10 @@ pub(crate) fn list_map3<'a, 'ctx, 'env>(
|
|||
list1: BasicValueEnum<'ctx>,
|
||||
list2: BasicValueEnum<'ctx>,
|
||||
list3: BasicValueEnum<'ctx>,
|
||||
element1_layout: &Layout<'a>,
|
||||
element2_layout: &Layout<'a>,
|
||||
element3_layout: &Layout<'a>,
|
||||
result_layout: &Layout<'a>,
|
||||
element1_layout: InLayout<'a>,
|
||||
element2_layout: InLayout<'a>,
|
||||
element3_layout: InLayout<'a>,
|
||||
result_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
|
||||
|
@ -572,11 +562,11 @@ pub(crate) fn list_map4<'a, 'ctx, 'env>(
|
|||
list2: BasicValueEnum<'ctx>,
|
||||
list3: BasicValueEnum<'ctx>,
|
||||
list4: BasicValueEnum<'ctx>,
|
||||
element1_layout: &Layout<'a>,
|
||||
element2_layout: &Layout<'a>,
|
||||
element3_layout: &Layout<'a>,
|
||||
element4_layout: &Layout<'a>,
|
||||
result_layout: &Layout<'a>,
|
||||
element1_layout: InLayout<'a>,
|
||||
element2_layout: InLayout<'a>,
|
||||
element3_layout: InLayout<'a>,
|
||||
element4_layout: InLayout<'a>,
|
||||
result_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let dec_a = build_dec_wrapper(env, layout_interner, layout_ids, element1_layout);
|
||||
let dec_b = build_dec_wrapper(env, layout_interner, layout_ids, element2_layout);
|
||||
|
@ -620,7 +610,6 @@ pub(crate) fn list_concat<'a, 'ctx, 'env>(
|
|||
list2: BasicValueEnum<'ctx>,
|
||||
element_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
call_list_bitcode_fn(
|
||||
env,
|
||||
&[list1.into_struct_value(), list2.into_struct_value()],
|
||||
|
@ -637,7 +626,7 @@ pub(crate) fn incrementing_elem_loop<'a, 'r, 'ctx, 'env, LoopFn>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &'r mut STLayoutInterner<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
element_layout: Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
ptr: PointerValue<'ctx>,
|
||||
len: IntValue<'ctx>,
|
||||
index_name: &str,
|
||||
|
@ -648,7 +637,7 @@ where
|
|||
{
|
||||
let builder = env.builder;
|
||||
|
||||
let element_type = basic_type_from_layout(env, layout_interner, &element_layout);
|
||||
let element_type = basic_type_from_layout(env, layout_interner, element_layout);
|
||||
|
||||
incrementing_index_loop(
|
||||
env,
|
||||
|
@ -771,19 +760,19 @@ pub(crate) fn load_list_ptr<'ctx>(
|
|||
pub(crate) fn allocate_list<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
elem_layout: &Layout<'a>,
|
||||
elem_layout: InLayout<'a>,
|
||||
number_of_elements: IntValue<'ctx>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let builder = env.builder;
|
||||
|
||||
let len_type = env.ptr_int();
|
||||
let elem_bytes = elem_layout.stack_size(layout_interner, env.target_info) as u64;
|
||||
let elem_bytes = layout_interner.stack_size(elem_layout) as u64;
|
||||
let bytes_per_element = len_type.const_int(elem_bytes, false);
|
||||
let number_of_data_bytes =
|
||||
builder.build_int_mul(bytes_per_element, number_of_elements, "data_length");
|
||||
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, elem_layout);
|
||||
let alignment_bytes = elem_layout.alignment_bytes(layout_interner, env.target_info);
|
||||
let alignment_bytes = layout_interner.alignment_bytes(elem_layout);
|
||||
allocate_with_refcount_help(env, basic_type, alignment_bytes, number_of_data_bytes)
|
||||
}
|
||||
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -12,9 +12,10 @@ use inkwell::values::{
|
|||
use inkwell::{AddressSpace, FloatPredicate, IntPredicate};
|
||||
use roc_builtins::bitcode;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner, UnionLayout};
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
|
||||
};
|
||||
|
||||
use super::build::{load_roc_value, use_roc_value, BuilderExt};
|
||||
use super::convert::argument_type_from_union_layout;
|
||||
|
@ -26,8 +27,8 @@ pub fn generic_eq<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
lhs_layout: &Layout<'a>,
|
||||
rhs_layout: &Layout<'a>,
|
||||
lhs_layout: InLayout<'a>,
|
||||
rhs_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
build_eq(
|
||||
env,
|
||||
|
@ -47,8 +48,8 @@ pub fn generic_neq<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
lhs_layout: &Layout<'a>,
|
||||
rhs_layout: &Layout<'a>,
|
||||
lhs_layout: InLayout<'a>,
|
||||
rhs_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
build_neq(
|
||||
env,
|
||||
|
@ -128,16 +129,19 @@ fn build_eq_builtin<'a, 'ctx, 'env>(
|
|||
Builtin::Decimal => dec_binop_with_unchecked(env, bitcode::DEC_EQ, lhs_val, rhs_val),
|
||||
|
||||
Builtin::Str => str_equal(env, lhs_val, rhs_val),
|
||||
Builtin::List(elem) => build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
&Layout::Builtin(*builtin),
|
||||
*elem,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
when_recursive,
|
||||
),
|
||||
Builtin::List(elem) => {
|
||||
let list_layout = layout_interner.insert(Layout::Builtin(*builtin));
|
||||
build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
list_layout,
|
||||
*elem,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
when_recursive,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,12 +151,12 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
lhs_layout: &Layout<'a>,
|
||||
rhs_layout: &Layout<'a>,
|
||||
lhs_layout: InLayout<'a>,
|
||||
rhs_layout: InLayout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
let lhs_layout = &lhs_layout.runtime_representation(layout_interner);
|
||||
let rhs_layout = &rhs_layout.runtime_representation(layout_interner);
|
||||
let lhs_layout = &layout_interner.runtime_representation_in(lhs_layout);
|
||||
let rhs_layout = &layout_interner.runtime_representation_in(rhs_layout);
|
||||
if lhs_layout != rhs_layout {
|
||||
panic!(
|
||||
"Equality of different layouts; did you have a type mismatch?\n{:?} == {:?}",
|
||||
|
@ -160,14 +164,14 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
);
|
||||
}
|
||||
|
||||
match lhs_layout {
|
||||
match layout_interner.get(*lhs_layout) {
|
||||
Layout::Builtin(builtin) => build_eq_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
builtin,
|
||||
&builtin,
|
||||
when_recursive,
|
||||
),
|
||||
|
||||
|
@ -188,7 +192,7 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
union_layout,
|
||||
&union_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
),
|
||||
|
@ -198,8 +202,8 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
*inner_layout,
|
||||
*lhs_layout,
|
||||
inner_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
),
|
||||
|
@ -210,9 +214,9 @@ fn build_eq<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -313,11 +317,12 @@ fn build_neq_builtin<'a, 'ctx, 'env>(
|
|||
result.into()
|
||||
}
|
||||
Builtin::List(elem) => {
|
||||
let builtin_layout = layout_interner.insert(Layout::Builtin(*builtin));
|
||||
let is_equal = build_list_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
&Layout::Builtin(*builtin),
|
||||
builtin_layout,
|
||||
*elem,
|
||||
lhs_val.into_struct_value(),
|
||||
rhs_val.into_struct_value(),
|
||||
|
@ -338,8 +343,8 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
lhs_val: BasicValueEnum<'ctx>,
|
||||
rhs_val: BasicValueEnum<'ctx>,
|
||||
lhs_layout: &Layout<'a>,
|
||||
rhs_layout: &Layout<'a>,
|
||||
lhs_layout: InLayout<'a>,
|
||||
rhs_layout: InLayout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
if lhs_layout != rhs_layout {
|
||||
|
@ -349,14 +354,14 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
);
|
||||
}
|
||||
|
||||
match lhs_layout {
|
||||
match layout_interner.get(lhs_layout) {
|
||||
Layout::Builtin(builtin) => build_neq_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
builtin,
|
||||
&builtin,
|
||||
when_recursive,
|
||||
),
|
||||
|
||||
|
@ -383,7 +388,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
layout_interner,
|
||||
layout_ids,
|
||||
when_recursive,
|
||||
union_layout,
|
||||
&union_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
)
|
||||
|
@ -401,7 +406,7 @@ fn build_neq<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
when_recursive,
|
||||
lhs_layout,
|
||||
*inner_layout,
|
||||
inner_layout,
|
||||
lhs_val,
|
||||
rhs_val,
|
||||
)
|
||||
|
@ -423,7 +428,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
list_layout: &Layout<'a>,
|
||||
list_layout: InLayout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
list1: StructValue<'ctx>,
|
||||
list2: StructValue<'ctx>,
|
||||
|
@ -434,7 +439,8 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
|
||||
let symbol = Symbol::LIST_EQ;
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
|
||||
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
|
||||
let element_layout = layout_interner.insert(element_layout);
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, &element_layout)
|
||||
.to_symbol_string(symbol, &env.interns);
|
||||
|
@ -457,7 +463,7 @@ fn build_list_eq<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
when_recursive,
|
||||
function_value,
|
||||
&element_layout,
|
||||
element_layout,
|
||||
);
|
||||
|
||||
function_value
|
||||
|
@ -482,7 +488,7 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
element_layout: &Layout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
) {
|
||||
let ctx = env.context;
|
||||
let builder = env.builder;
|
||||
|
@ -581,14 +587,14 @@ fn build_list_eq_help<'a, 'ctx, 'env>(
|
|||
let elem_ptr = unsafe {
|
||||
builder.new_build_in_bounds_gep(element_type, ptr1, &[curr_index], "load_index")
|
||||
};
|
||||
load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem")
|
||||
load_roc_value(env, layout_interner, element_layout, elem_ptr, "get_elem")
|
||||
};
|
||||
|
||||
let elem2 = {
|
||||
let elem_ptr = unsafe {
|
||||
builder.new_build_in_bounds_gep(element_type, ptr2, &[curr_index], "load_index")
|
||||
};
|
||||
load_roc_value(env, layout_interner, *element_layout, elem_ptr, "get_elem")
|
||||
load_roc_value(env, layout_interner, element_layout, elem_ptr, "get_elem")
|
||||
};
|
||||
|
||||
let are_equal = build_eq(
|
||||
|
@ -640,7 +646,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
field_layouts: &'a [Layout<'a>],
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
struct1: StructValue<'ctx>,
|
||||
struct2: StructValue<'ctx>,
|
||||
|
@ -648,7 +654,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let struct_layout = Layout::struct_no_name_order(field_layouts);
|
||||
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let symbol = Symbol::GENERIC_EQ;
|
||||
let fn_name = layout_ids
|
||||
|
@ -658,7 +664,7 @@ fn build_struct_eq<'a, 'ctx, 'env>(
|
|||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let arg_type = basic_type_from_layout(env, layout_interner, &struct_layout);
|
||||
let arg_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
|
||||
let function_value = crate::llvm::refcounting::build_header_help(
|
||||
env,
|
||||
|
@ -698,7 +704,7 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
field_layouts: &[Layout<'a>],
|
||||
field_layouts: &[InLayout<'a>],
|
||||
) {
|
||||
let ctx = env.context;
|
||||
let builder = env.builder;
|
||||
|
@ -755,15 +761,15 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
.build_extract_value(struct2, index as u32, "eq_field")
|
||||
.unwrap();
|
||||
|
||||
let are_equal = if let Layout::RecursivePointer = field_layout {
|
||||
let are_equal = if let Layout::RecursivePointer = layout_interner.get(*field_layout) {
|
||||
match &when_recursive {
|
||||
WhenRecursive::Unreachable => {
|
||||
unreachable!("The current layout should not be recursive, but is")
|
||||
}
|
||||
WhenRecursive::Loop(union_layout) => {
|
||||
let field_layout = Layout::Union(*union_layout);
|
||||
let field_layout = layout_interner.insert(Layout::Union(*union_layout));
|
||||
|
||||
let bt = basic_type_from_layout(env, layout_interner, &field_layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, field_layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -784,8 +790,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
field1_cast.into(),
|
||||
field2_cast.into(),
|
||||
&field_layout,
|
||||
&field_layout,
|
||||
field_layout,
|
||||
field_layout,
|
||||
WhenRecursive::Loop(*union_layout),
|
||||
)
|
||||
.into_int_value()
|
||||
|
@ -800,8 +806,8 @@ fn build_struct_eq_help<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
lhs,
|
||||
rhs,
|
||||
field_layout,
|
||||
field_layout,
|
||||
*field_layout,
|
||||
*field_layout,
|
||||
when_recursive,
|
||||
)
|
||||
.into_int_value()
|
||||
|
@ -841,7 +847,7 @@ fn build_tag_eq<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let tag_layout = Layout::Union(*union_layout);
|
||||
let tag_layout = layout_interner.insert(Layout::Union(*union_layout));
|
||||
let symbol = Symbol::GENERIC_EQ;
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, &tag_layout)
|
||||
|
@ -1284,13 +1290,13 @@ fn eq_ptr_to_struct<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
opt_when_recursive: Option<WhenRecursive<'a>>,
|
||||
field_layouts: &'a [Layout<'a>],
|
||||
field_layouts: &'a [InLayout<'a>],
|
||||
tag1: PointerValue<'ctx>,
|
||||
tag2: PointerValue<'ctx>,
|
||||
) -> IntValue<'ctx> {
|
||||
let struct_layout = Layout::struct_no_name_order(field_layouts);
|
||||
let struct_layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
|
||||
let wrapper_type = basic_type_from_layout(env, layout_interner, &struct_layout);
|
||||
let wrapper_type = basic_type_from_layout(env, layout_interner, struct_layout);
|
||||
debug_assert!(wrapper_type.is_struct_type());
|
||||
|
||||
// cast the opaque pointer to a pointer of the correct shape
|
||||
|
@ -1335,7 +1341,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
box_layout: &Layout<'a>,
|
||||
box_layout: InLayout<'a>,
|
||||
inner_layout: InLayout<'a>,
|
||||
tag1: BasicValueEnum<'ctx>,
|
||||
tag2: BasicValueEnum<'ctx>,
|
||||
|
@ -1345,7 +1351,7 @@ fn build_box_eq<'a, 'ctx, 'env>(
|
|||
|
||||
let symbol = Symbol::GENERIC_EQ;
|
||||
let fn_name = layout_ids
|
||||
.get(symbol, box_layout)
|
||||
.get(symbol, &box_layout)
|
||||
.to_symbol_string(symbol, &env.interns);
|
||||
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
|
@ -1455,10 +1461,8 @@ fn build_box_eq_help<'a, 'ctx, 'env>(
|
|||
let box1 = box1.into_pointer_value();
|
||||
let box2 = box2.into_pointer_value();
|
||||
|
||||
let inner_layout = layout_interner.get(inner_layout);
|
||||
|
||||
let value1 = load_roc_value(env, layout_interner, *inner_layout, box1, "load_box1");
|
||||
let value2 = load_roc_value(env, layout_interner, *inner_layout, box2, "load_box2");
|
||||
let value1 = load_roc_value(env, layout_interner, inner_layout, box1, "load_box1");
|
||||
let value2 = load_roc_value(env, layout_interner, inner_layout, box2, "load_box2");
|
||||
|
||||
let is_equal = build_eq(
|
||||
env,
|
||||
|
|
|
@ -5,19 +5,20 @@ use inkwell::types::{BasicType, BasicTypeEnum, FloatType, IntType, StructType};
|
|||
use inkwell::values::StructValue;
|
||||
use inkwell::AddressSpace;
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_intern::Interner;
|
||||
use roc_mono::layout::{round_up_to_alignment, Builtin, Layout, STLayoutInterner, UnionLayout};
|
||||
use roc_mono::layout::{
|
||||
round_up_to_alignment, Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, UnionLayout,
|
||||
};
|
||||
use roc_target::TargetInfo;
|
||||
|
||||
fn basic_type_from_record<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
fields: &[Layout<'_>],
|
||||
fields: &[InLayout<'_>],
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
let mut field_types = Vec::with_capacity_in(fields.len(), env.arena);
|
||||
|
||||
for field_layout in fields.iter() {
|
||||
field_types.push(basic_type_from_layout(env, layout_interner, field_layout));
|
||||
field_types.push(basic_type_from_layout(env, layout_interner, *field_layout));
|
||||
}
|
||||
|
||||
env.context
|
||||
|
@ -28,34 +29,31 @@ fn basic_type_from_record<'a, 'ctx, 'env>(
|
|||
pub fn basic_type_from_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &'env mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'_>,
|
||||
layout: InLayout<'_>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
use Layout::*;
|
||||
|
||||
match layout {
|
||||
match layout_interner.get(layout) {
|
||||
Struct {
|
||||
field_layouts: sorted_fields,
|
||||
..
|
||||
} => basic_type_from_record(env, layout_interner, sorted_fields),
|
||||
LambdaSet(lambda_set) => basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&lambda_set.runtime_representation(layout_interner),
|
||||
),
|
||||
LambdaSet(lambda_set) => {
|
||||
basic_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
|
||||
}
|
||||
Boxed(inner_layout) => {
|
||||
let inner_layout = layout_interner.get(*inner_layout);
|
||||
let inner_type = basic_type_from_layout(env, layout_interner, inner_layout);
|
||||
|
||||
inner_type.ptr_type(AddressSpace::Generic).into()
|
||||
}
|
||||
Union(union_layout) => basic_type_from_union_layout(env, layout_interner, union_layout),
|
||||
Union(union_layout) => basic_type_from_union_layout(env, layout_interner, &union_layout),
|
||||
RecursivePointer => env
|
||||
.context
|
||||
.i64_type()
|
||||
.ptr_type(AddressSpace::Generic)
|
||||
.as_basic_type_enum(),
|
||||
|
||||
Builtin(builtin) => basic_type_from_builtin(env, builtin),
|
||||
Builtin(builtin) => basic_type_from_builtin(env, &builtin),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,27 +145,25 @@ pub fn basic_type_from_builtin<'a, 'ctx, 'env>(
|
|||
pub fn argument_type_from_layout<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'_>,
|
||||
layout: InLayout<'a>,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
use Layout::*;
|
||||
|
||||
match layout {
|
||||
LambdaSet(lambda_set) => argument_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&lambda_set.runtime_representation(layout_interner),
|
||||
),
|
||||
Union(union_layout) => argument_type_from_union_layout(env, layout_interner, union_layout),
|
||||
match layout_interner.get(layout) {
|
||||
LambdaSet(lambda_set) => {
|
||||
argument_type_from_layout(env, layout_interner, lambda_set.runtime_representation())
|
||||
}
|
||||
Union(union_layout) => argument_type_from_union_layout(env, layout_interner, &union_layout),
|
||||
Builtin(_) => {
|
||||
let base = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
if layout.is_passed_by_reference(layout_interner, env.target_info) {
|
||||
if layout_interner.is_passed_by_reference(layout) {
|
||||
base.ptr_type(AddressSpace::Generic).into()
|
||||
} else {
|
||||
base
|
||||
}
|
||||
}
|
||||
other => basic_type_from_layout(env, layout_interner, other),
|
||||
_ => basic_type_from_layout(env, layout_interner, layout),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +296,7 @@ impl<'ctx> RocUnion<'ctx> {
|
|||
pub fn tagged_from_slices(
|
||||
interner: &STLayoutInterner,
|
||||
context: &'ctx Context,
|
||||
layouts: &[&[Layout<'_>]],
|
||||
layouts: &[&[InLayout<'_>]],
|
||||
target_info: TargetInfo,
|
||||
) -> Self {
|
||||
let tag_type = match layouts.len() {
|
||||
|
@ -317,7 +313,7 @@ impl<'ctx> RocUnion<'ctx> {
|
|||
pub fn untagged_from_slices(
|
||||
interner: &STLayoutInterner,
|
||||
context: &'ctx Context,
|
||||
layouts: &[&[Layout<'_>]],
|
||||
layouts: &[&[InLayout<'_>]],
|
||||
target_info: TargetInfo,
|
||||
) -> Self {
|
||||
let (data_width, data_align) =
|
||||
|
|
|
@ -9,10 +9,11 @@ use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum};
|
|||
use inkwell::values::{BasicValueEnum, FunctionValue, IntValue, PointerValue};
|
||||
use inkwell::AddressSpace;
|
||||
use roc_builtins::bitcode;
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::ir::LookupType;
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, STLayoutInterner, UnionLayout};
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
|
||||
};
|
||||
use roc_region::all::Region;
|
||||
|
||||
use super::build::BuilderExt;
|
||||
|
@ -200,10 +201,9 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
|
||||
let (value, layout) = load_symbol_and_layout(scope, lookup);
|
||||
|
||||
let stack_size = env.ptr_int().const_int(
|
||||
layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
let stack_size = env
|
||||
.ptr_int()
|
||||
.const_int(layout_interner.stack_size(layout) as u64, false);
|
||||
|
||||
let mut extra_offset = env.builder.build_int_add(offset, stack_size, "offset");
|
||||
|
||||
|
@ -219,7 +219,7 @@ pub(crate) fn clone_to_shared_memory<'a, 'ctx, 'env>(
|
|||
original_ptr,
|
||||
cursors,
|
||||
value,
|
||||
*layout,
|
||||
layout,
|
||||
WhenRecursive::Unreachable,
|
||||
);
|
||||
|
||||
|
@ -285,10 +285,10 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> IntValue<'ctx> {
|
||||
match layout {
|
||||
match layout_interner.get(layout) {
|
||||
Layout::Builtin(builtin) => build_clone_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -316,7 +316,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
Layout::LambdaSet(_) => cursors.extra_offset,
|
||||
|
||||
Layout::Union(union_layout) => {
|
||||
if layout.safe_to_memcpy(layout_interner) {
|
||||
if layout_interner.safe_to_memcpy(layout) {
|
||||
let ptr = unsafe {
|
||||
env.builder.new_build_in_bounds_gep(
|
||||
env.context.i8_type(),
|
||||
|
@ -353,13 +353,11 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
build_copy(env, ptr, cursors.offset, cursors.extra_offset.into());
|
||||
|
||||
let source = value.into_pointer_value();
|
||||
let inner_layout = layout_interner.get(inner_layout);
|
||||
let value = load_roc_value(env, layout_interner, *inner_layout, source, "inner");
|
||||
let value = load_roc_value(env, layout_interner, inner_layout, source, "inner");
|
||||
|
||||
let inner_width = env.ptr_int().const_int(
|
||||
inner_layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
let inner_width = env
|
||||
.ptr_int()
|
||||
.const_int(layout_interner.stack_size(inner_layout) as u64, false);
|
||||
|
||||
let new_extra = env
|
||||
.builder
|
||||
|
@ -377,7 +375,7 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
ptr,
|
||||
cursors,
|
||||
value,
|
||||
*inner_layout,
|
||||
inner_layout,
|
||||
when_recursive,
|
||||
)
|
||||
}
|
||||
|
@ -388,9 +386,9 @@ fn build_clone<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field1_cast = env.builder.build_pointer_cast(
|
||||
|
@ -421,7 +419,7 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
ptr: PointerValue<'ctx>,
|
||||
cursors: Cursors<'ctx>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
field_layouts: &[Layout<'a>],
|
||||
field_layouts: &[InLayout<'a>],
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> IntValue<'ctx> {
|
||||
let layout = Layout::struct_no_name_order(field_layouts);
|
||||
|
@ -452,10 +450,9 @@ fn build_clone_struct<'a, 'ctx, 'env>(
|
|||
when_recursive,
|
||||
);
|
||||
|
||||
let field_width = env.ptr_int().const_int(
|
||||
field_layout.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
let field_width = env
|
||||
.ptr_int()
|
||||
.const_int(layout_interner.stack_size(*field_layout) as u64, false);
|
||||
|
||||
cursors.extra_offset = new_extra;
|
||||
cursors.offset = env
|
||||
|
@ -477,7 +474,7 @@ fn build_clone_tag<'a, 'ctx, 'env>(
|
|||
union_layout: UnionLayout<'a>,
|
||||
when_recursive: WhenRecursive<'a>,
|
||||
) -> IntValue<'ctx> {
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let layout_id = layout_ids.get(Symbol::CLONE, &layout);
|
||||
let fn_name = layout_id.to_symbol_string(Symbol::CLONE, &env.interns);
|
||||
|
||||
|
@ -632,12 +629,12 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let layout = Layout::struct_no_name_order(field_layouts);
|
||||
let layout = Layout::struct_no_name_order(
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(
|
||||
env.arena.alloc([layout, union_layout.tag_id_layout()]),
|
||||
);
|
||||
));
|
||||
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let data = load_tag_data(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -691,16 +688,16 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
|
||||
let tag_value = tag_pointer_clear_tag_id(env, tag_value.into_pointer_value());
|
||||
|
||||
let layout = Layout::struct_no_name_order(field_layouts);
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
let layout = if union_layout.stores_tag_id_in_pointer(env.target_info) {
|
||||
layout
|
||||
} else {
|
||||
Layout::struct_no_name_order(
|
||||
layout_interner.insert(Layout::struct_no_name_order(
|
||||
env.arena.alloc([layout, union_layout.tag_id_layout()]),
|
||||
)
|
||||
))
|
||||
};
|
||||
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let data = load_tag_data(env, layout_interner, union_layout, tag_value, basic_type);
|
||||
|
||||
let (width, _) =
|
||||
|
@ -749,8 +746,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
|
||||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = Layout::struct_no_name_order(fields);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(fields));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
let (width, _) = union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
||||
|
@ -815,8 +812,8 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
other_tags[i]
|
||||
};
|
||||
|
||||
let layout = Layout::struct_no_name_order(fields);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(fields));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
let (width, _) =
|
||||
union_layout.data_size_and_alignment(layout_interner, env.target_info);
|
||||
|
@ -899,17 +896,15 @@ fn build_clone_tag_help<'a, 'ctx, 'env>(
|
|||
// write the "pointer" af the current offset
|
||||
build_copy(env, ptr, offset, extra_offset.into());
|
||||
|
||||
let layout = Layout::struct_no_name_order(other_fields);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(other_fields));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
let cursors = Cursors {
|
||||
offset: extra_offset,
|
||||
extra_offset: env.builder.build_int_add(
|
||||
extra_offset,
|
||||
env.ptr_int().const_int(
|
||||
layout.stack_size(layout_interner, env.target_info) as _,
|
||||
false,
|
||||
),
|
||||
env.ptr_int()
|
||||
.const_int(layout_interner.stack_size(layout) as _, false),
|
||||
"new_offset",
|
||||
),
|
||||
};
|
||||
|
@ -1042,16 +1037,18 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
offset = build_copy(env, ptr, offset, len.into());
|
||||
offset = build_copy(env, ptr, offset, len.into());
|
||||
|
||||
let elem = layout_interner.get(elem);
|
||||
let (element_width, _element_align) =
|
||||
elem.stack_size_and_alignment(layout_interner, env.target_info);
|
||||
let (element_width, _element_align) = layout_interner.stack_size_and_alignment(elem);
|
||||
let element_width = env.ptr_int().const_int(element_width as _, false);
|
||||
|
||||
let elements_width = bd.build_int_mul(element_width, len, "elements_width");
|
||||
|
||||
if elem.safe_to_memcpy(layout_interner) {
|
||||
// We clone the elements into the extra_offset address.
|
||||
let _ = offset;
|
||||
let elements_start_offset = cursors.extra_offset;
|
||||
|
||||
if layout_interner.safe_to_memcpy(elem) {
|
||||
// NOTE we are not actually sure the dest is properly aligned
|
||||
let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, offset);
|
||||
let dest = pointer_at_offset(bd, env.context.i8_type(), ptr, elements_start_offset);
|
||||
let src = bd.build_pointer_cast(
|
||||
elements,
|
||||
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
||||
|
@ -1059,11 +1056,8 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
);
|
||||
bd.build_memcpy(dest, 1, src, 1, elements_width).unwrap();
|
||||
|
||||
bd.build_int_add(offset, elements_width, "new_offset")
|
||||
bd.build_int_add(elements_start_offset, elements_width, "new_offset")
|
||||
} else {
|
||||
// We cloned the elements into the extra_offset address.
|
||||
let elements_start_offset = cursors.extra_offset;
|
||||
|
||||
let element_type = basic_type_from_layout(env, layout_interner, elem);
|
||||
let elements = bd.build_pointer_cast(
|
||||
elements,
|
||||
|
@ -1074,10 +1068,9 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
// if the element has any pointers, we clone them to this offset
|
||||
let rest_offset = bd.build_alloca(env.ptr_int(), "rest_offset");
|
||||
|
||||
let element_stack_size = env.ptr_int().const_int(
|
||||
elem.stack_size(layout_interner, env.target_info) as u64,
|
||||
false,
|
||||
);
|
||||
let element_stack_size = env
|
||||
.ptr_int()
|
||||
.const_int(layout_interner.stack_size(elem) as u64, false);
|
||||
let rest_start_offset = bd.build_int_add(
|
||||
cursors.extra_offset,
|
||||
bd.build_int_mul(len, element_stack_size, "elements_width"),
|
||||
|
@ -1108,7 +1101,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
ptr,
|
||||
cursors,
|
||||
element,
|
||||
*elem,
|
||||
elem,
|
||||
when_recursive,
|
||||
);
|
||||
|
||||
|
@ -1125,7 +1118,7 @@ fn build_clone_builtin<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
*elem,
|
||||
elem,
|
||||
elements,
|
||||
len,
|
||||
"index",
|
||||
|
|
|
@ -9,11 +9,10 @@ use inkwell::{
|
|||
use morphic_lib::{FuncSpec, UpdateMode};
|
||||
use roc_builtins::bitcode::{self, FloatWidth, IntWidth};
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_intern::Interner;
|
||||
use roc_module::{low_level::LowLevel, symbol::Symbol};
|
||||
use roc_mono::{
|
||||
ir::HigherOrderLowLevel,
|
||||
layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner},
|
||||
layout::{Builtin, InLayout, LambdaSet, Layout, LayoutIds, LayoutInterner, STLayoutInterner},
|
||||
};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
|
@ -51,8 +50,8 @@ use super::{
|
|||
};
|
||||
|
||||
macro_rules! list_element_layout {
|
||||
($list_layout:expr) => {
|
||||
match $list_layout {
|
||||
($interner:expr, $list_layout:expr) => {
|
||||
match $interner.get($list_layout) {
|
||||
Layout::Builtin(Builtin::List(list_layout)) => list_layout,
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
|
@ -65,7 +64,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
op: LowLevel,
|
||||
args: &[Symbol],
|
||||
update_mode: UpdateMode,
|
||||
|
@ -201,13 +200,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
// Str.toNum : Str -> Result (Num *) {}
|
||||
arguments!(string);
|
||||
|
||||
let number_layout = match layout {
|
||||
let number_layout = match layout_interner.get(layout) {
|
||||
Layout::Struct { field_layouts, .. } => field_layouts[0], // TODO: why is it sometimes a struct?
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
// match on the return layout to figure out which zig builtin we need
|
||||
let intrinsic = match number_layout {
|
||||
let intrinsic = match layout_interner.get(number_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => &bitcode::STR_TO_INT[int_width],
|
||||
Layout::Builtin(Builtin::Float(float_width)) => &bitcode::STR_TO_FLOAT[float_width],
|
||||
Layout::Builtin(Builtin::Decimal) => bitcode::DEC_FROM_STR,
|
||||
|
@ -228,7 +227,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
intrinsic,
|
||||
),
|
||||
None => {
|
||||
let return_type_name = match number_layout {
|
||||
let return_type_name = match layout_interner.get(number_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => int_width.type_name(),
|
||||
Layout::Builtin(Builtin::Decimal) => {
|
||||
// zig picks 128 for dec.RocDec
|
||||
|
@ -268,7 +267,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*layout,
|
||||
layout,
|
||||
roc_return_alloca,
|
||||
"str_to_num_result",
|
||||
)
|
||||
|
@ -276,7 +275,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
PtrWidth::Bytes8 => {
|
||||
let cc_return_by_pointer = match number_layout {
|
||||
let cc_return_by_pointer = match layout_interner.get(number_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => {
|
||||
(int_width.stack_size() as usize > env.target_info.ptr_size())
|
||||
.then_some(int_width.type_name())
|
||||
|
@ -322,8 +321,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let (int, int_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let int = int.into_int_value();
|
||||
|
||||
let int_width = match int_layout {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => *int_width,
|
||||
let int_width = match layout_interner.get(int_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -341,8 +340,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
let float_width = match float_layout {
|
||||
Layout::Builtin(Builtin::Float(float_width)) => *float_width,
|
||||
let float_width = match layout_interner.get(float_layout) {
|
||||
Layout::Builtin(Builtin::Float(float_width)) => float_width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -650,12 +649,12 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
// List.withCapacity : Nat -> List a
|
||||
arguments!(list_len);
|
||||
|
||||
let result_layout = *layout;
|
||||
let result_layout = layout;
|
||||
list_with_capacity(
|
||||
env,
|
||||
layout_interner,
|
||||
list_len.into_int_value(),
|
||||
list_element_layout!(result_layout),
|
||||
list_element_layout!(layout_interner, result_layout),
|
||||
)
|
||||
}
|
||||
ListConcat => {
|
||||
|
@ -665,14 +664,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let second_list = load_symbol(scope, &args[1]);
|
||||
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||
|
||||
list_concat(
|
||||
env,
|
||||
layout_interner,
|
||||
first_list,
|
||||
second_list,
|
||||
*element_layout,
|
||||
element_layout,
|
||||
)
|
||||
}
|
||||
ListAppendUnsafe => {
|
||||
|
@ -698,7 +697,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
debug_assert_eq!(args.len(), 2);
|
||||
|
||||
let (list, list_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||
let spare = load_symbol(scope, &args[1]);
|
||||
|
||||
list_reserve(
|
||||
|
@ -706,7 +705,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
layout_interner,
|
||||
list,
|
||||
spare,
|
||||
*element_layout,
|
||||
element_layout,
|
||||
update_mode,
|
||||
)
|
||||
}
|
||||
|
@ -720,14 +719,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let index_1 = load_symbol(scope, &args[1]);
|
||||
let index_2 = load_symbol(scope, &args[2]);
|
||||
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||
list_swap(
|
||||
env,
|
||||
layout_interner,
|
||||
original_wrapper,
|
||||
index_1.into_int_value(),
|
||||
index_2.into_int_value(),
|
||||
*element_layout,
|
||||
element_layout,
|
||||
update_mode,
|
||||
)
|
||||
}
|
||||
|
@ -740,7 +739,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let start = load_symbol(scope, &args[1]);
|
||||
let len = load_symbol(scope, &args[2]);
|
||||
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||
list_sublist(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -748,7 +747,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
original_wrapper,
|
||||
start.into_int_value(),
|
||||
len.into_int_value(),
|
||||
*element_layout,
|
||||
element_layout,
|
||||
)
|
||||
}
|
||||
ListDropAt => {
|
||||
|
@ -760,14 +759,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let count = load_symbol(scope, &args[1]);
|
||||
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
let element_layout = list_element_layout!(layout_interner, list_layout);
|
||||
list_drop_at(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
count.into_int_value(),
|
||||
*element_layout,
|
||||
element_layout,
|
||||
)
|
||||
}
|
||||
StrGetUnsafe => {
|
||||
|
@ -790,7 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
*list_element_layout!(list_layout),
|
||||
list_element_layout!(layout_interner, list_layout),
|
||||
element_index.into_int_value(),
|
||||
wrapper_struct.into_struct_value(),
|
||||
)
|
||||
|
@ -825,7 +824,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
// Num.toStr : Num a -> Str
|
||||
arguments_with_layouts!((num, num_layout));
|
||||
|
||||
match num_layout {
|
||||
match layout_interner.get(num_layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => {
|
||||
let int = num.into_int_value();
|
||||
|
||||
|
@ -834,14 +833,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
&[],
|
||||
&[int.into()],
|
||||
BitcodeReturns::Str,
|
||||
&bitcode::STR_FROM_INT[*int_width],
|
||||
&bitcode::STR_FROM_INT[int_width],
|
||||
)
|
||||
}
|
||||
Layout::Builtin(Builtin::Float(_float_width)) => {
|
||||
let (float, float_layout) = load_symbol_and_layout(scope, &args[0]);
|
||||
|
||||
let float_width = match float_layout {
|
||||
Layout::Builtin(Builtin::Float(float_width)) => *float_width,
|
||||
let float_width = match layout_interner.get(float_layout) {
|
||||
Layout::Builtin(Builtin::Float(float_width)) => float_width,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
|
@ -862,19 +861,19 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
| NumToIntChecked => {
|
||||
arguments_with_layouts!((arg, arg_layout));
|
||||
|
||||
match arg_layout {
|
||||
match layout_interner.get(arg_layout) {
|
||||
Layout::Builtin(arg_builtin) => {
|
||||
use roc_mono::layout::Builtin::*;
|
||||
|
||||
match arg_builtin {
|
||||
Int(int_width) => {
|
||||
let int_type = convert::int_type_from_int_width(env, *int_width);
|
||||
let int_type = convert::int_type_from_int_width(env, int_width);
|
||||
build_int_unary_op(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
arg.into_int_value(),
|
||||
*int_width,
|
||||
int_width,
|
||||
int_type,
|
||||
op,
|
||||
layout,
|
||||
|
@ -882,10 +881,11 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
Float(float_width) => build_float_unary_op(
|
||||
env,
|
||||
layout_interner,
|
||||
layout,
|
||||
arg.into_float_value(),
|
||||
op,
|
||||
*float_width,
|
||||
float_width,
|
||||
),
|
||||
_ => {
|
||||
unreachable!("Compiler bug: tried to run numeric operation {:?} on invalid builtin layout: ({:?})", op, arg_layout);
|
||||
|
@ -926,7 +926,10 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
use inkwell::FloatPredicate;
|
||||
match (lhs_layout, rhs_layout) {
|
||||
match (
|
||||
layout_interner.get(lhs_layout),
|
||||
layout_interner.get(rhs_layout),
|
||||
) {
|
||||
(Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin))
|
||||
if lhs_builtin == rhs_builtin =>
|
||||
{
|
||||
|
@ -1012,13 +1015,22 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
| NumSubChecked | NumSubSaturated | NumMulWrap | NumMulSaturated | NumMulChecked => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
build_num_binop(env, parent, lhs_arg, lhs_layout, rhs_arg, rhs_layout, op)
|
||||
build_num_binop(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
lhs_arg,
|
||||
lhs_layout,
|
||||
rhs_arg,
|
||||
rhs_layout,
|
||||
op,
|
||||
)
|
||||
}
|
||||
NumBitwiseAnd | NumBitwiseOr | NumBitwiseXor => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
debug_assert_eq!(lhs_layout, rhs_layout);
|
||||
let int_width = intwidth_from_layout(*lhs_layout);
|
||||
let int_width = intwidth_from_layout(lhs_layout);
|
||||
|
||||
build_int_binop(
|
||||
env,
|
||||
|
@ -1032,9 +1044,9 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
NumShiftLeftBy | NumShiftRightBy | NumShiftRightZfBy => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
let int_width = intwidth_from_layout(*lhs_layout);
|
||||
let int_width = intwidth_from_layout(lhs_layout);
|
||||
|
||||
debug_assert_eq!(rhs_layout, &Layout::Builtin(Builtin::Int(IntWidth::U8)));
|
||||
debug_assert_eq!(rhs_layout, Layout::U8);
|
||||
let rhs_arg = if rhs_layout != lhs_layout {
|
||||
// LLVM shift intrinsics expect the left and right sides to have the same type, so
|
||||
// here we cast up `rhs` to the lhs type. Since the rhs was checked to be a U8,
|
||||
|
@ -1062,7 +1074,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
arguments!(arg);
|
||||
|
||||
let to = basic_type_from_layout(env, layout_interner, layout).into_int_type();
|
||||
let to_signed = intwidth_from_layout(*layout).is_signed();
|
||||
let to_signed = intwidth_from_layout(layout).is_signed();
|
||||
|
||||
env.builder
|
||||
.build_int_cast_sign_flag(arg.into_int_value(), to, to_signed, "inc_cast")
|
||||
|
@ -1071,7 +1083,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
NumToFloatCast => {
|
||||
arguments_with_layouts!((arg, arg_layout));
|
||||
|
||||
match arg_layout {
|
||||
match layout_interner.get(arg_layout) {
|
||||
Layout::Builtin(Builtin::Int(width)) => {
|
||||
// Converting from int to float
|
||||
let int_val = arg.into_int_value();
|
||||
|
@ -1199,12 +1211,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
|
||||
fn intwidth_from_layout(layout: Layout) -> IntWidth {
|
||||
match layout {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => int_width,
|
||||
|
||||
_ => unreachable!(),
|
||||
}
|
||||
fn intwidth_from_layout(layout: InLayout) -> IntWidth {
|
||||
layout.to_int_width()
|
||||
}
|
||||
|
||||
fn build_int_binop<'a, 'ctx, 'env>(
|
||||
|
@ -1430,14 +1438,18 @@ fn build_int_binop<'a, 'ctx, 'env>(
|
|||
|
||||
pub fn build_num_binop<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
lhs_arg: BasicValueEnum<'ctx>,
|
||||
lhs_layout: &Layout<'a>,
|
||||
lhs_layout: InLayout<'a>,
|
||||
rhs_arg: BasicValueEnum<'ctx>,
|
||||
rhs_layout: &Layout<'a>,
|
||||
rhs_layout: InLayout<'a>,
|
||||
op: LowLevel,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
match (lhs_layout, rhs_layout) {
|
||||
match (
|
||||
layout_interner.get(lhs_layout),
|
||||
layout_interner.get(rhs_layout),
|
||||
) {
|
||||
(Layout::Builtin(lhs_builtin), Layout::Builtin(rhs_builtin))
|
||||
if lhs_builtin == rhs_builtin =>
|
||||
{
|
||||
|
@ -1447,7 +1459,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
|
|||
Int(int_width) => build_int_binop(
|
||||
env,
|
||||
parent,
|
||||
*int_width,
|
||||
int_width,
|
||||
lhs_arg.into_int_value(),
|
||||
rhs_arg.into_int_value(),
|
||||
op,
|
||||
|
@ -1455,7 +1467,7 @@ pub fn build_num_binop<'a, 'ctx, 'env>(
|
|||
|
||||
Float(float_width) => build_float_binop(
|
||||
env,
|
||||
*float_width,
|
||||
float_width,
|
||||
lhs_arg.into_float_value(),
|
||||
rhs_arg.into_float_value(),
|
||||
op,
|
||||
|
@ -1787,9 +1799,9 @@ fn build_dec_binop<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
lhs: BasicValueEnum<'ctx>,
|
||||
_lhs_layout: &Layout<'a>,
|
||||
_lhs_layout: InLayout<'a>,
|
||||
rhs: BasicValueEnum<'ctx>,
|
||||
_rhs_layout: &Layout<'a>,
|
||||
_rhs_layout: InLayout<'a>,
|
||||
op: LowLevel,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
use roc_module::low_level::LowLevel::*;
|
||||
|
@ -1869,7 +1881,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
arg_width: IntWidth,
|
||||
arg_int_type: IntType<'ctx>,
|
||||
op: LowLevel,
|
||||
return_layout: &Layout<'a>,
|
||||
return_layout: InLayout<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
use roc_module::low_level::LowLevel::*;
|
||||
|
||||
|
@ -1887,9 +1899,9 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
NumToFrac => {
|
||||
// This is an Int, so we need to convert it.
|
||||
|
||||
let target_float_type = match return_layout {
|
||||
let target_float_type = match layout_interner.get(return_layout) {
|
||||
Layout::Builtin(Builtin::Float(float_width)) => {
|
||||
convert::float_type_from_float_width(env, *float_width)
|
||||
convert::float_type_from_float_width(env, float_width)
|
||||
}
|
||||
_ => internal_error!("There can only be floats here!"),
|
||||
};
|
||||
|
@ -1904,16 +1916,10 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
NumToIntChecked => {
|
||||
// return_layout : Result N [OutOfBounds]* ~ { result: N, out_of_bounds: bool }
|
||||
|
||||
let target_int_width = match return_layout {
|
||||
let target_int_width = match layout_interner.get(return_layout) {
|
||||
Layout::Struct { field_layouts, .. } if field_layouts.len() == 2 => {
|
||||
debug_assert!(matches!(field_layouts[1], Layout::Builtin(Builtin::Bool)));
|
||||
match field_layouts[0] {
|
||||
Layout::Builtin(Builtin::Int(iw)) => iw,
|
||||
layout => internal_error!(
|
||||
"There can only be an int layout here, found {:?}!",
|
||||
layout
|
||||
),
|
||||
}
|
||||
debug_assert!(matches!(field_layouts[1], Layout::BOOL));
|
||||
field_layouts[0].to_int_width()
|
||||
}
|
||||
layout => internal_error!(
|
||||
"There can only be a result layout here, found {:?}!",
|
||||
|
@ -2018,7 +2024,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*return_layout,
|
||||
return_layout,
|
||||
roc_return_alloca,
|
||||
"num_to_int",
|
||||
)
|
||||
|
@ -2160,7 +2166,8 @@ fn int_abs_with_overflow<'a, 'ctx, 'env>(
|
|||
|
||||
fn build_float_unary_op<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout: &Layout<'a>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
layout: InLayout<'a>,
|
||||
arg: FloatValue<'ctx>,
|
||||
op: LowLevel,
|
||||
float_width: FloatWidth, // arg width
|
||||
|
@ -2176,8 +2183,8 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
NumSqrtUnchecked => env.call_intrinsic(&LLVM_SQRT[float_width], &[arg.into()]),
|
||||
NumLogUnchecked => env.call_intrinsic(&LLVM_LOG[float_width], &[arg.into()]),
|
||||
NumToFrac => {
|
||||
let return_width = match layout {
|
||||
Layout::Builtin(Builtin::Float(return_width)) => *return_width,
|
||||
let return_width = match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Float(return_width)) => return_width,
|
||||
_ => internal_error!("Layout for returning is not Float : {:?}", layout),
|
||||
};
|
||||
match (float_width, return_width) {
|
||||
|
@ -2198,10 +2205,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
NumCeiling => {
|
||||
let (return_signed, return_type) = match layout {
|
||||
let (return_signed, return_type) = match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => (
|
||||
int_width.is_signed(),
|
||||
convert::int_type_from_int_width(env, *int_width),
|
||||
convert::int_type_from_int_width(env, int_width),
|
||||
),
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
};
|
||||
|
@ -2218,10 +2225,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
NumFloor => {
|
||||
let (return_signed, return_type) = match layout {
|
||||
let (return_signed, return_type) = match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => (
|
||||
int_width.is_signed(),
|
||||
convert::int_type_from_int_width(env, *int_width),
|
||||
convert::int_type_from_int_width(env, int_width),
|
||||
),
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
};
|
||||
|
@ -2238,10 +2245,10 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
)
|
||||
}
|
||||
NumRound => {
|
||||
let (return_signed, return_type) = match layout {
|
||||
let (return_signed, return_type) = match layout_interner.get(layout) {
|
||||
Layout::Builtin(Builtin::Int(int_width)) => (
|
||||
int_width.is_signed(),
|
||||
convert::int_type_from_int_width(env, *int_width),
|
||||
convert::int_type_from_int_width(env, int_width),
|
||||
),
|
||||
_ => internal_error!("Ceiling return layout is not int: {:?}", layout),
|
||||
};
|
||||
|
@ -2278,7 +2285,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
return_layout: &Layout<'a>,
|
||||
return_layout: InLayout<'a>,
|
||||
func_spec: FuncSpec,
|
||||
higher_order: &HigherOrderLowLevel<'a>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
|
@ -2313,7 +2320,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
);
|
||||
|
||||
let (closure, closure_layout) =
|
||||
load_symbol_and_lambda_set(scope, &captured_environment);
|
||||
load_symbol_and_lambda_set(layout_interner, scope, &captured_environment);
|
||||
|
||||
(function, closure, closure_layout)
|
||||
}};
|
||||
|
@ -2326,15 +2333,15 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list_layout, return_layout) {
|
||||
match (
|
||||
layout_interner.get(list_layout),
|
||||
layout_interner.get(return_layout),
|
||||
) {
|
||||
(
|
||||
Layout::Builtin(Builtin::List(element_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element_layout = layout_interner.get(*element_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element_layout];
|
||||
let argument_layouts = &[element_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
|
@ -2345,7 +2352,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
closure_layout,
|
||||
function_owns_closure_data,
|
||||
argument_layouts,
|
||||
*result_layout,
|
||||
result_layout,
|
||||
);
|
||||
|
||||
list_map(
|
||||
|
@ -2366,17 +2373,17 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list1_layout, list2_layout, return_layout) {
|
||||
match (
|
||||
layout_interner.get(list1_layout),
|
||||
layout_interner.get(list2_layout),
|
||||
layout_interner.get(return_layout),
|
||||
) {
|
||||
(
|
||||
Layout::Builtin(Builtin::List(element1_layout)),
|
||||
Layout::Builtin(Builtin::List(element2_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element1_layout, *element2_layout];
|
||||
let argument_layouts = &[element1_layout, element2_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
|
@ -2387,7 +2394,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
closure_layout,
|
||||
function_owns_closure_data,
|
||||
argument_layouts,
|
||||
*result_layout,
|
||||
result_layout,
|
||||
);
|
||||
|
||||
list_map2(
|
||||
|
@ -2412,19 +2419,19 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (list1_layout, list2_layout, list3_layout, return_layout) {
|
||||
match (
|
||||
layout_interner.get(list1_layout),
|
||||
layout_interner.get(list2_layout),
|
||||
layout_interner.get(list3_layout),
|
||||
layout_interner.get(return_layout),
|
||||
) {
|
||||
(
|
||||
Layout::Builtin(Builtin::List(element1_layout)),
|
||||
Layout::Builtin(Builtin::List(element2_layout)),
|
||||
Layout::Builtin(Builtin::List(element3_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let element3_layout = layout_interner.get(*element3_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element1_layout, *element2_layout, *element3_layout];
|
||||
let argument_layouts = &[element1_layout, element2_layout, element3_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
|
@ -2435,7 +2442,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
closure_layout,
|
||||
function_owns_closure_data,
|
||||
argument_layouts,
|
||||
*result_layout,
|
||||
result_layout,
|
||||
);
|
||||
|
||||
list_map3(
|
||||
|
@ -2464,11 +2471,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match (
|
||||
list1_layout,
|
||||
list2_layout,
|
||||
list3_layout,
|
||||
list4_layout,
|
||||
return_layout,
|
||||
layout_interner.get(list1_layout),
|
||||
layout_interner.get(list2_layout),
|
||||
layout_interner.get(list3_layout),
|
||||
layout_interner.get(list4_layout),
|
||||
layout_interner.get(return_layout),
|
||||
) {
|
||||
(
|
||||
Layout::Builtin(Builtin::List(element1_layout)),
|
||||
|
@ -2477,17 +2484,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element4_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let element3_layout = layout_interner.get(*element3_layout);
|
||||
let element4_layout = layout_interner.get(*element4_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[
|
||||
*element1_layout,
|
||||
*element2_layout,
|
||||
*element3_layout,
|
||||
*element4_layout,
|
||||
element1_layout,
|
||||
element2_layout,
|
||||
element3_layout,
|
||||
element4_layout,
|
||||
];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
|
@ -2499,7 +2500,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
closure_layout,
|
||||
function_owns_closure_data,
|
||||
argument_layouts,
|
||||
*result_layout,
|
||||
result_layout,
|
||||
);
|
||||
|
||||
list_map4(
|
||||
|
@ -2527,13 +2528,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let (function, closure, closure_layout) = function_details!();
|
||||
|
||||
match list_layout {
|
||||
match layout_interner.get(list_layout) {
|
||||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
use crate::llvm::bitcode::build_compare_wrapper;
|
||||
|
||||
let element_layout = layout_interner.get(*element_layout);
|
||||
|
||||
let argument_layouts = &[*element_layout, *element_layout];
|
||||
let argument_layouts = &[element_layout, element_layout];
|
||||
|
||||
let compare_wrapper = build_compare_wrapper(
|
||||
env,
|
||||
|
@ -2573,11 +2572,12 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
fn load_symbol_and_lambda_set<'a, 'ctx, 'b>(
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
scope: &'b Scope<'a, 'ctx>,
|
||||
symbol: &Symbol,
|
||||
) -> (BasicValueEnum<'ctx>, LambdaSet<'a>) {
|
||||
match scope.get(symbol) {
|
||||
Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, *lambda_set),
|
||||
match scope.get(symbol).map(|(l, v)| (layout_interner.get(*l), v)) {
|
||||
Some((Layout::LambdaSet(lambda_set), ptr)) => (*ptr, lambda_set),
|
||||
Some((other, ptr)) => panic!("Not a lambda set: {:?}, {:?}", other, ptr),
|
||||
None => panic!("There was no entry for {:?} in scope {:?}", symbol, scope),
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::llvm::build::{
|
|||
add_func, cast_basic_basic, get_tag_id, tag_pointer_clear_tag_id, use_roc_value, Env,
|
||||
WhenRecursive, FAST_CALL_CONV,
|
||||
};
|
||||
use crate::llvm::build_list::{incrementing_elem_loop, list_len, load_list};
|
||||
use crate::llvm::build_list::{incrementing_elem_loop, list_capacity, load_list};
|
||||
use crate::llvm::convert::{basic_type_from_layout, zig_str_type, RocUnion};
|
||||
use bumpalo::collections::Vec;
|
||||
use inkwell::basic_block::BasicBlock;
|
||||
|
@ -15,10 +15,11 @@ use inkwell::values::{
|
|||
BasicValue, BasicValueEnum, FunctionValue, IntValue, PointerValue, StructValue,
|
||||
};
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::Interns;
|
||||
use roc_module::symbol::Symbol;
|
||||
use roc_mono::layout::{Builtin, InLayout, Layout, LayoutIds, STLayoutInterner, UnionLayout};
|
||||
use roc_mono::layout::{
|
||||
Builtin, InLayout, Layout, LayoutIds, LayoutInterner, STLayoutInterner, UnionLayout,
|
||||
};
|
||||
|
||||
use super::build::{cast_if_necessary_for_opaque_recursive_pointers, load_roc_value, FunctionSpec};
|
||||
use super::convert::{argument_type_from_layout, argument_type_from_union_layout};
|
||||
|
@ -112,7 +113,7 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
fn modify<'a, 'env>(
|
||||
&self,
|
||||
mode: CallMode<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
) {
|
||||
|
@ -130,10 +131,10 @@ impl<'ctx> PointerToRefcount<'ctx> {
|
|||
&self,
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
let alignment = layout
|
||||
.allocation_alignment_bytes(layout_interner, env.target_info)
|
||||
let alignment = layout_interner
|
||||
.allocation_alignment_bytes(layout)
|
||||
.max(env.target_info.ptr_width() as u32);
|
||||
|
||||
let context = env.context;
|
||||
|
@ -274,28 +275,28 @@ fn modify_refcount_struct<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layouts: &'a [Layout<'a>],
|
||||
layouts: &'a [InLayout<'a>],
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let layout = Layout::struct_no_name_order(layouts);
|
||||
let layout = layout_interner.insert(Layout::struct_no_name_order(layouts));
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
&env.interns,
|
||||
"increment_struct",
|
||||
"decrement_struct",
|
||||
&layout,
|
||||
layout,
|
||||
mode,
|
||||
);
|
||||
|
||||
let function = match env.module.get_function(fn_name.as_str()) {
|
||||
Some(function_value) => function_value,
|
||||
None => {
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
modify_refcount_struct_help(
|
||||
|
@ -326,7 +327,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
layouts: &[Layout<'a>],
|
||||
layouts: &[InLayout<'a>],
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
) {
|
||||
let builder = env.builder;
|
||||
|
@ -348,7 +349,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
let wrapper_struct = arg_val.into_struct_value();
|
||||
|
||||
for (i, field_layout) in layouts.iter().enumerate() {
|
||||
if field_layout.contains_refcounted(layout_interner) {
|
||||
if layout_interner.contains_refcounted(*field_layout) {
|
||||
let raw_value = env
|
||||
.builder
|
||||
.build_extract_value(wrapper_struct, i as u32, "decrement_struct_field")
|
||||
|
@ -369,7 +370,7 @@ fn modify_refcount_struct_help<'a, 'ctx, 'env>(
|
|||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
field_value,
|
||||
field_layout,
|
||||
*field_layout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +384,7 @@ pub fn increment_refcount_layout<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
inc_amount: u64,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
let amount = env.ptr_int().const_int(inc_amount, false);
|
||||
increment_n_refcount_layout(env, layout_interner, layout_ids, amount, value, layout);
|
||||
|
@ -395,7 +396,7 @@ pub fn increment_n_refcount_layout<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
amount: IntValue<'ctx>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
modify_refcount_layout(
|
||||
env,
|
||||
|
@ -412,7 +413,7 @@ pub fn decrement_refcount_layout<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
modify_refcount_layout(
|
||||
env,
|
||||
|
@ -430,7 +431,7 @@ fn modify_refcount_builtin<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
builtin: &Builtin<'a>,
|
||||
) -> Option<FunctionValue<'ctx>> {
|
||||
use Builtin::*;
|
||||
|
@ -470,7 +471,7 @@ fn modify_refcount_layout<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
call_mode: CallMode<'ctx>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
|
@ -490,7 +491,7 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
|||
call_mode: CallMode<'ctx>,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
value: BasicValueEnum<'ctx>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) {
|
||||
let mode = match call_mode {
|
||||
CallMode::Inc(_) => Mode::Inc,
|
||||
|
@ -509,15 +510,15 @@ fn modify_refcount_layout_help<'a, 'ctx, 'env>(
|
|||
None => return,
|
||||
};
|
||||
|
||||
match layout {
|
||||
match layout_interner.get(layout) {
|
||||
Layout::RecursivePointer => match when_recursive {
|
||||
WhenRecursive::Unreachable => {
|
||||
unreachable!("recursion pointers should never be hashed directly")
|
||||
}
|
||||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(*union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(*union_layout));
|
||||
|
||||
let bt = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let bt = basic_type_from_layout(env, layout_interner, layout);
|
||||
|
||||
// cast the i64 pointer to a pointer to block of memory
|
||||
let field_cast = env.builder.build_pointer_cast(
|
||||
|
@ -568,11 +569,11 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> Option<FunctionValue<'ctx>> {
|
||||
use Layout::*;
|
||||
|
||||
match layout {
|
||||
match layout_interner.get(layout) {
|
||||
Builtin(builtin) => modify_refcount_builtin(
|
||||
env,
|
||||
layout_interner,
|
||||
|
@ -580,11 +581,11 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
mode,
|
||||
when_recursive,
|
||||
layout,
|
||||
builtin,
|
||||
&builtin,
|
||||
),
|
||||
|
||||
Boxed(inner) => {
|
||||
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, *inner);
|
||||
let function = modify_refcount_boxed(env, layout_interner, layout_ids, mode, inner);
|
||||
|
||||
Some(function)
|
||||
}
|
||||
|
@ -617,8 +618,8 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
layout_interner,
|
||||
layout_ids,
|
||||
mode,
|
||||
&WhenRecursive::Loop(*variant),
|
||||
*variant,
|
||||
&WhenRecursive::Loop(variant),
|
||||
variant,
|
||||
);
|
||||
|
||||
Some(function)
|
||||
|
@ -644,7 +645,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
unreachable!("recursion pointers cannot be in/decremented directly")
|
||||
}
|
||||
WhenRecursive::Loop(union_layout) => {
|
||||
let layout = Layout::Union(*union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(*union_layout));
|
||||
|
||||
let function = modify_refcount_layout_build_function(
|
||||
env,
|
||||
|
@ -652,7 +653,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
&layout,
|
||||
layout,
|
||||
)?;
|
||||
|
||||
Some(function)
|
||||
|
@ -664,7 +665,7 @@ fn modify_refcount_layout_build_function<'a, 'ctx, 'env>(
|
|||
layout_ids,
|
||||
mode,
|
||||
when_recursive,
|
||||
&lambda_set.runtime_representation(layout_interner),
|
||||
lambda_set.runtime_representation(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -681,9 +682,9 @@ fn modify_refcount_list<'a, 'ctx, 'env>(
|
|||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
let element_layout = when_recursive.unwrap_recursive_pointer(*element_layout);
|
||||
let element_layout = layout_interner.insert(env.arena.alloc(element_layout));
|
||||
let list_layout = &Layout::Builtin(Builtin::List(element_layout));
|
||||
let element_layout = when_recursive.unwrap_recursive_pointer(element_layout);
|
||||
let element_layout = layout_interner.insert(element_layout);
|
||||
let list_layout = layout_interner.insert(Layout::Builtin(Builtin::List(element_layout)));
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
&env.interns,
|
||||
|
@ -734,7 +735,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
element_layout: InLayout<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
) {
|
||||
|
@ -757,7 +758,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
let parent = fn_val;
|
||||
let original_wrapper = arg_val.into_struct_value();
|
||||
|
||||
let len = list_len(builder, original_wrapper);
|
||||
let len = list_capacity(builder, original_wrapper);
|
||||
|
||||
let is_non_empty = builder.build_int_compare(
|
||||
IntPredicate::UGT,
|
||||
|
@ -774,8 +775,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
|
||||
builder.position_at_end(modification_block);
|
||||
|
||||
let element_layout = layout_interner.get(element_layout);
|
||||
if element_layout.contains_refcounted(layout_interner) {
|
||||
if layout_interner.contains_refcounted(element_layout) {
|
||||
let ptr_type = basic_type_from_layout(env, layout_interner, element_layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
|
@ -797,7 +797,7 @@ fn modify_refcount_list_help<'a, 'ctx, 'env>(
|
|||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
*element_layout,
|
||||
element_layout,
|
||||
ptr,
|
||||
len,
|
||||
"modify_rc_index",
|
||||
|
@ -822,7 +822,7 @@ fn modify_refcount_str<'a, 'ctx, 'env>(
|
|||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
@ -859,7 +859,7 @@ fn modify_refcount_str_help<'a, 'ctx, 'env>(
|
|||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
mode: Mode,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
) {
|
||||
let builder = env.builder;
|
||||
|
@ -935,7 +935,7 @@ fn modify_refcount_boxed<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let boxed_layout = env.arena.alloc(Layout::Boxed(inner_layout));
|
||||
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
|
@ -990,8 +990,8 @@ fn modify_refcount_box_help<'a, 'ctx, 'env>(
|
|||
let boxed = arg_val.into_pointer_value();
|
||||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, boxed);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
let boxed_layout = Layout::Boxed(inner_layout);
|
||||
refcount_ptr.modify(call_mode, &boxed_layout, env, layout_interner);
|
||||
let boxed_layout = layout_interner.insert(Layout::Boxed(inner_layout));
|
||||
refcount_ptr.modify(call_mode, boxed_layout, env, layout_interner);
|
||||
|
||||
// this function returns void
|
||||
builder.build_return(None);
|
||||
|
@ -1096,14 +1096,14 @@ fn build_rec_union<'a, 'ctx, 'env>(
|
|||
when_recursive: &WhenRecursive<'a>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
) -> FunctionValue<'ctx> {
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
|
||||
let (_, fn_name) = function_name_from_mode(
|
||||
layout_ids,
|
||||
&env.interns,
|
||||
"increment_rec_union",
|
||||
"decrement_rec_union",
|
||||
&layout,
|
||||
layout,
|
||||
mode,
|
||||
);
|
||||
|
||||
|
@ -1113,7 +1113,7 @@ fn build_rec_union<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, &layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
build_rec_union_help(
|
||||
|
@ -1148,7 +1148,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
fn_val: FunctionValue<'ctx>,
|
||||
) {
|
||||
let tags = union_layout_tags(env.arena, &union_layout);
|
||||
debug_assert!(!tags.is_empty());
|
||||
debug_assert!(!tags.tags.is_empty());
|
||||
|
||||
let context = &env.context;
|
||||
let builder = env.builder;
|
||||
|
@ -1202,12 +1202,12 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
let refcount_ptr = PointerToRefcount::from_ptr_to_data(env, value_ptr);
|
||||
let call_mode = mode_to_call_mode(fn_val, mode);
|
||||
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
|
||||
match mode {
|
||||
Mode::Inc => {
|
||||
// inc is cheap; we never recurse
|
||||
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
|
||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
|
@ -1224,7 +1224,7 @@ fn build_rec_union_help<'a, 'ctx, 'env>(
|
|||
{
|
||||
env.builder.position_at_end(no_recurse_block);
|
||||
|
||||
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
|
||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
|
@ -1256,10 +1256,11 @@ enum DecOrReuse {
|
|||
Reuse,
|
||||
}
|
||||
|
||||
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[Layout]) -> bool {
|
||||
!field_layouts
|
||||
.iter()
|
||||
.any(|x| x.is_refcounted() || x.contains_refcounted(interner))
|
||||
fn fields_need_no_refcounting(interner: &STLayoutInterner, field_layouts: &[InLayout]) -> bool {
|
||||
!field_layouts.iter().any(|x| {
|
||||
let x = interner.get(*x);
|
||||
x.is_refcounted() || x.contains_refcounted(interner)
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
@ -1271,7 +1272,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
parent: FunctionValue<'ctx>,
|
||||
decrement_fn: FunctionValue<'ctx>,
|
||||
union_layout: UnionLayout<'a>,
|
||||
tags: &[&[Layout<'a>]],
|
||||
tags: UnionLayoutTags<'a>,
|
||||
value_ptr: PointerValue<'ctx>,
|
||||
current_tag_id: IntValue<'ctx>,
|
||||
refcount_ptr: PointerToRefcount<'ctx>,
|
||||
|
@ -1282,13 +1283,24 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
let call_mode = mode_to_call_mode(decrement_fn, mode);
|
||||
let builder = env.builder;
|
||||
|
||||
let UnionLayoutTags { nullable_id, tags } = tags;
|
||||
|
||||
// next, make a jump table for all possible values of the tag_id
|
||||
let mut cases = Vec::with_capacity_in(tags.len(), env.arena);
|
||||
|
||||
let tag_id_int_type =
|
||||
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()).into_int_type();
|
||||
basic_type_from_layout(env, layout_interner, union_layout.tag_id_layout()).into_int_type();
|
||||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
let tag_id = match nullable_id {
|
||||
Some(null_id) if tag_id as u16 >= null_id => {
|
||||
// This tag comes after the nullable tag, so its ID is one higher than the
|
||||
// enumeration says.
|
||||
tag_id + 1
|
||||
}
|
||||
_ => tag_id,
|
||||
};
|
||||
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if fields_need_no_refcounting(layout_interner, field_layouts) {
|
||||
continue;
|
||||
|
@ -1298,11 +1310,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let wrapper_type = basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&Layout::struct_no_name_order(field_layouts),
|
||||
);
|
||||
let fields_struct = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
let wrapper_type = basic_type_from_layout(env, layout_interner, fields_struct);
|
||||
|
||||
// cast the opaque pointer to a pointer of the correct shape
|
||||
let struct_ptr = env.builder.build_pointer_cast(
|
||||
|
@ -1317,7 +1326,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
let mut deferred_nonrec = Vec::new_in(env.arena);
|
||||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||
if let Layout::RecursivePointer = field_layout {
|
||||
if let Layout::RecursivePointer = layout_interner.get(*field_layout) {
|
||||
// this field has type `*i64`, but is really a pointer to the data we want
|
||||
let elem_pointer = env
|
||||
.builder
|
||||
|
@ -1338,12 +1347,12 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
debug_assert!(ptr_as_i64_ptr.is_pointer_value());
|
||||
|
||||
// therefore we must cast it to our desired type
|
||||
let union_type =
|
||||
basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout));
|
||||
let union_layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
|
||||
let recursive_field_ptr = cast_basic_basic(env.builder, ptr_as_i64_ptr, union_type);
|
||||
|
||||
deferred_rec.push(recursive_field_ptr);
|
||||
} else if field_layout.contains_refcounted(layout_interner) {
|
||||
} else if layout_interner.contains_refcounted(*field_layout) {
|
||||
let elem_pointer = env
|
||||
.builder
|
||||
.new_build_struct_gep(
|
||||
|
@ -1376,12 +1385,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
match decrement_or_reuse {
|
||||
DecOrReuse::Reuse => {}
|
||||
DecOrReuse::Dec => {
|
||||
refcount_ptr.modify(
|
||||
call_mode,
|
||||
&Layout::Union(union_layout),
|
||||
env,
|
||||
layout_interner,
|
||||
);
|
||||
let union_layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1393,7 +1398,7 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
mode.to_call_mode(decrement_fn),
|
||||
when_recursive,
|
||||
field,
|
||||
field_layout,
|
||||
*field_layout,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1434,12 +1439,8 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
|
||||
// increment/decrement the cons-cell itself
|
||||
if let DecOrReuse::Dec = decrement_or_reuse {
|
||||
refcount_ptr.modify(
|
||||
call_mode,
|
||||
&Layout::Union(union_layout),
|
||||
env,
|
||||
layout_interner,
|
||||
);
|
||||
let union_layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
refcount_ptr.modify(call_mode, union_layout, env, layout_interner);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1448,20 +1449,44 @@ fn build_rec_union_recursive_decrement<'a, 'ctx, 'env>(
|
|||
}
|
||||
}
|
||||
|
||||
struct UnionLayoutTags<'a> {
|
||||
nullable_id: Option<u16>,
|
||||
tags: &'a [&'a [InLayout<'a>]],
|
||||
}
|
||||
|
||||
fn union_layout_tags<'a>(
|
||||
arena: &'a bumpalo::Bump,
|
||||
union_layout: &UnionLayout<'a>,
|
||||
) -> &'a [&'a [Layout<'a>]] {
|
||||
) -> UnionLayoutTags<'a> {
|
||||
use UnionLayout::*;
|
||||
|
||||
match union_layout {
|
||||
NullableWrapped {
|
||||
other_tags: tags, ..
|
||||
} => tags,
|
||||
NullableUnwrapped { other_fields, .. } => arena.alloc([*other_fields]),
|
||||
NonNullableUnwrapped(fields) => arena.alloc([*fields]),
|
||||
Recursive(tags) => tags,
|
||||
NonRecursive(tags) => tags,
|
||||
other_tags,
|
||||
nullable_id,
|
||||
} => UnionLayoutTags {
|
||||
nullable_id: Some(*nullable_id),
|
||||
tags: other_tags,
|
||||
},
|
||||
NullableUnwrapped {
|
||||
other_fields,
|
||||
nullable_id,
|
||||
} => UnionLayoutTags {
|
||||
nullable_id: Some(*nullable_id as u16),
|
||||
tags: arena.alloc([*other_fields]),
|
||||
},
|
||||
NonNullableUnwrapped(fields) => UnionLayoutTags {
|
||||
nullable_id: None,
|
||||
tags: arena.alloc([*fields]),
|
||||
},
|
||||
Recursive(tags) => UnionLayoutTags {
|
||||
nullable_id: None,
|
||||
tags,
|
||||
},
|
||||
NonRecursive(tags) => UnionLayoutTags {
|
||||
nullable_id: None,
|
||||
tags,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1473,7 +1498,8 @@ pub fn build_reset<'a, 'ctx, 'env>(
|
|||
) -> FunctionValue<'ctx> {
|
||||
let mode = Mode::Dec;
|
||||
|
||||
let layout_id = layout_ids.get(Symbol::DEC, &Layout::Union(union_layout));
|
||||
let union_layout_in = layout_interner.insert(Layout::Union(union_layout));
|
||||
let layout_id = layout_ids.get(Symbol::DEC, &union_layout_in);
|
||||
let fn_name = layout_id.to_symbol_string(Symbol::DEC, &env.interns);
|
||||
let fn_name = format!("{}_reset", fn_name);
|
||||
|
||||
|
@ -1493,8 +1519,7 @@ pub fn build_reset<'a, 'ctx, 'env>(
|
|||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
||||
let basic_type =
|
||||
basic_type_from_layout(env, layout_interner, &Layout::Union(union_layout));
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, union_layout_in);
|
||||
let function_value = build_header(env, basic_type, mode, &fn_name);
|
||||
|
||||
build_reuse_rec_union_help(
|
||||
|
@ -1530,7 +1555,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
|||
) {
|
||||
let tags = union_layout_tags(env.arena, &union_layout);
|
||||
|
||||
debug_assert!(!tags.is_empty());
|
||||
debug_assert!(!tags.tags.is_empty());
|
||||
|
||||
let context = &env.context;
|
||||
let builder = env.builder;
|
||||
|
@ -1580,7 +1605,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
|||
|
||||
env.builder.position_at_end(should_recurse_block);
|
||||
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
|
||||
let do_recurse_block = env.context.append_basic_block(parent, "do_recurse");
|
||||
let no_recurse_block = env.context.append_basic_block(parent, "no_recurse");
|
||||
|
@ -1590,7 +1615,7 @@ fn build_reuse_rec_union_help<'a, 'ctx, 'env>(
|
|||
{
|
||||
env.builder.position_at_end(no_recurse_block);
|
||||
|
||||
refcount_ptr.modify(call_mode, &layout, env, layout_interner);
|
||||
refcount_ptr.modify(call_mode, layout, env, layout_interner);
|
||||
env.builder.build_return(None);
|
||||
}
|
||||
|
||||
|
@ -1620,7 +1645,7 @@ fn function_name_from_mode<'a>(
|
|||
interns: &Interns,
|
||||
if_inc: &'static str,
|
||||
if_dec: &'static str,
|
||||
layout: &Layout<'a>,
|
||||
layout: InLayout<'a>,
|
||||
mode: Mode,
|
||||
) -> (&'static str, String) {
|
||||
// NOTE this is not a typo, we always determine the layout ID
|
||||
|
@ -1628,7 +1653,7 @@ fn function_name_from_mode<'a>(
|
|||
// decremented, so `dec` is used on more layouts. That can cause the
|
||||
// layout ids of the inc and dec versions to be different, which is
|
||||
// rather confusing, so now `inc_x` always corresponds to `dec_x`
|
||||
let layout_id = layout_ids.get(Symbol::DEC, layout);
|
||||
let layout_id = layout_ids.get(Symbol::DEC, &layout);
|
||||
match mode {
|
||||
Mode::Inc => (if_inc, layout_id.to_symbol_string(Symbol::INC, interns)),
|
||||
Mode::Dec => (if_dec, layout_id.to_symbol_string(Symbol::DEC, interns)),
|
||||
|
@ -1641,10 +1666,10 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
fields: &'a [&'a [Layout<'a>]],
|
||||
fields: &'a [&'a [InLayout<'a>]],
|
||||
) -> FunctionValue<'ctx> {
|
||||
let union_layout = UnionLayout::NonRecursive(fields);
|
||||
let layout = Layout::Union(union_layout);
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
|
||||
let block = env.builder.get_insert_block().expect("to be in a function");
|
||||
let di_location = env.builder.get_current_debug_location().unwrap();
|
||||
|
@ -1654,7 +1679,7 @@ fn modify_refcount_nonrecursive<'a, 'ctx, 'env>(
|
|||
&env.interns,
|
||||
"increment_union",
|
||||
"decrement_union",
|
||||
&layout,
|
||||
layout,
|
||||
mode,
|
||||
);
|
||||
|
||||
|
@ -1691,7 +1716,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
layout_ids: &mut LayoutIds<'a>,
|
||||
mode: Mode,
|
||||
when_recursive: &WhenRecursive<'a>,
|
||||
tags: &[&[Layout<'a>]],
|
||||
tags: &'a [&'a [InLayout<'a>]],
|
||||
fn_val: FunctionValue<'ctx>,
|
||||
) {
|
||||
debug_assert!(!tags.is_empty());
|
||||
|
@ -1717,9 +1742,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
let before_block = env.builder.get_insert_block().expect("to be in a function");
|
||||
|
||||
let union_layout = UnionLayout::NonRecursive(tags);
|
||||
let layout = Layout::Union(union_layout);
|
||||
let union_struct_type =
|
||||
basic_type_from_layout(env, layout_interner, &layout).into_struct_type();
|
||||
let layout = layout_interner.insert(Layout::Union(union_layout));
|
||||
let union_struct_type = basic_type_from_layout(env, layout_interner, layout).into_struct_type();
|
||||
|
||||
// read the tag_id
|
||||
let tag_id_ptr = env
|
||||
|
@ -1735,7 +1759,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
let tag_id = env
|
||||
.builder
|
||||
.new_build_load(
|
||||
basic_type_from_layout(env, layout_interner, &union_layout.tag_id_layout()),
|
||||
basic_type_from_layout(env, layout_interner, union_layout.tag_id_layout()),
|
||||
tag_id_ptr,
|
||||
"load_tag_id",
|
||||
)
|
||||
|
@ -1754,21 +1778,18 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
|
||||
for (tag_id, field_layouts) in tags.iter().enumerate() {
|
||||
// if none of the fields are or contain anything refcounted, just move on
|
||||
if !field_layouts
|
||||
.iter()
|
||||
.any(|x| x.is_refcounted() || x.contains_refcounted(layout_interner))
|
||||
{
|
||||
if !field_layouts.iter().any(|x| {
|
||||
let x = layout_interner.get(*x);
|
||||
x.is_refcounted() || x.contains_refcounted(layout_interner)
|
||||
}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let block = env.context.append_basic_block(parent, "tag_id_modify");
|
||||
env.builder.position_at_end(block);
|
||||
|
||||
let data_struct_type = basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&Layout::struct_no_name_order(field_layouts),
|
||||
);
|
||||
let fields_struct = layout_interner.insert(Layout::struct_no_name_order(field_layouts));
|
||||
let data_struct_type = basic_type_from_layout(env, layout_interner, fields_struct);
|
||||
|
||||
debug_assert!(data_struct_type.is_struct_type());
|
||||
let data_struct_type = data_struct_type.into_struct_type();
|
||||
|
@ -1789,7 +1810,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
);
|
||||
|
||||
for (i, field_layout) in field_layouts.iter().enumerate() {
|
||||
if let Layout::RecursivePointer = field_layout {
|
||||
if let Layout::RecursivePointer = layout_interner.get(*field_layout) {
|
||||
let recursive_union_layout = match when_recursive {
|
||||
WhenRecursive::Unreachable => {
|
||||
panic!("non-recursive tag unions cannot contain naked recursion pointers!");
|
||||
|
@ -1818,11 +1839,8 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
debug_assert!(field_value.is_pointer_value());
|
||||
|
||||
// therefore we must cast it to our desired type
|
||||
let union_type = basic_type_from_layout(
|
||||
env,
|
||||
layout_interner,
|
||||
&Layout::Union(*recursive_union_layout),
|
||||
);
|
||||
let union_layout = layout_interner.insert(Layout::Union(*recursive_union_layout));
|
||||
let union_type = basic_type_from_layout(env, layout_interner, union_layout);
|
||||
let recursive_ptr_field_value =
|
||||
cast_basic_basic(env.builder, field_value, union_type);
|
||||
|
||||
|
@ -1833,9 +1851,9 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
recursive_ptr_field_value,
|
||||
&Layout::RecursivePointer,
|
||||
Layout::RECURSIVE_PTR,
|
||||
)
|
||||
} else if field_layout.contains_refcounted(layout_interner) {
|
||||
} else if layout_interner.contains_refcounted(*field_layout) {
|
||||
let field_ptr = env
|
||||
.builder
|
||||
.new_build_struct_gep(
|
||||
|
@ -1846,16 +1864,15 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
let field_value =
|
||||
if field_layout.is_passed_by_reference(layout_interner, env.target_info) {
|
||||
field_ptr.into()
|
||||
} else {
|
||||
env.builder.new_build_load(
|
||||
basic_type_from_layout(env, layout_interner, field_layout),
|
||||
field_ptr,
|
||||
"field_value",
|
||||
)
|
||||
};
|
||||
let field_value = if layout_interner.is_passed_by_reference(*field_layout) {
|
||||
field_ptr.into()
|
||||
} else {
|
||||
env.builder.new_build_load(
|
||||
basic_type_from_layout(env, layout_interner, *field_layout),
|
||||
field_ptr,
|
||||
"field_value",
|
||||
)
|
||||
};
|
||||
|
||||
modify_refcount_layout_help(
|
||||
env,
|
||||
|
@ -1864,7 +1881,7 @@ fn modify_refcount_nonrecursive_help<'a, 'ctx, 'env>(
|
|||
mode.to_call_mode(fn_val),
|
||||
when_recursive,
|
||||
field_value,
|
||||
field_layout,
|
||||
*field_layout,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue