mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
Push mutable layout interner through llvm backend
This commit is contained in:
parent
e4b5252e51
commit
512a1721ae
8 changed files with 1289 additions and 555 deletions
|
@ -13,7 +13,7 @@ use roc_intern::Interner;
|
|||
use roc_module::{low_level::LowLevel, symbol::Symbol};
|
||||
use roc_mono::{
|
||||
ir::HigherOrderLowLevel,
|
||||
layout::{Builtin, LambdaSet, Layout, LayoutIds},
|
||||
layout::{Builtin, LambdaSet, Layout, LayoutIds, STLayoutInterner},
|
||||
};
|
||||
use roc_target::PtrWidth;
|
||||
|
||||
|
@ -62,6 +62,7 @@ macro_rules! list_element_layout {
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
|
@ -256,7 +257,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
);
|
||||
|
||||
let roc_return_type =
|
||||
basic_type_from_layout(env, layout).ptr_type(AddressSpace::Generic);
|
||||
basic_type_from_layout(env, layout_interner, layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let roc_return_alloca = env.builder.build_pointer_cast(
|
||||
zig_return_alloca,
|
||||
|
@ -264,7 +266,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
"cast_to_roc",
|
||||
);
|
||||
|
||||
load_roc_value(env, *layout, roc_return_alloca, "str_to_num_result")
|
||||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*layout,
|
||||
roc_return_alloca,
|
||||
"str_to_num_result",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +294,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
call_bitcode_fn_fixing_for_convention(
|
||||
env,
|
||||
layout_interner,
|
||||
bitcode_return_type,
|
||||
&[string],
|
||||
layout,
|
||||
|
@ -298,7 +307,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
};
|
||||
|
||||
// zig passes the result as a packed integer sometimes, instead of a struct. So we cast
|
||||
let expected_type = basic_type_from_layout(env, layout);
|
||||
let expected_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let actual_type = result.get_type();
|
||||
|
||||
if expected_type != actual_type {
|
||||
|
@ -487,7 +496,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
bitcode::STR_GET_SCALAR_UNSAFE,
|
||||
);
|
||||
|
||||
let return_type = basic_type_from_layout(env, layout);
|
||||
let return_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let cast_result = env.builder.build_pointer_cast(
|
||||
result,
|
||||
return_type.ptr_type(AddressSpace::Generic),
|
||||
|
@ -510,7 +519,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
match env.target_info.ptr_width() {
|
||||
PtrWidth::Bytes8 => result,
|
||||
PtrWidth::Bytes4 => {
|
||||
let to = basic_type_from_layout(env, layout);
|
||||
let to = basic_type_from_layout(env, layout_interner, layout);
|
||||
complex_bitcast_check_size(env, result, to, "to_roc_record")
|
||||
}
|
||||
}
|
||||
|
@ -645,6 +654,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let result_layout = *layout;
|
||||
list_with_capacity(
|
||||
env,
|
||||
layout_interner,
|
||||
list_len.into_int_value(),
|
||||
list_element_layout!(result_layout),
|
||||
)
|
||||
|
@ -658,7 +668,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let element_layout = list_element_layout!(list_layout);
|
||||
|
||||
list_concat(env, first_list, second_list, *element_layout)
|
||||
list_concat(
|
||||
env,
|
||||
layout_interner,
|
||||
first_list,
|
||||
second_list,
|
||||
*element_layout,
|
||||
)
|
||||
}
|
||||
ListAppendUnsafe => {
|
||||
// List.appendUnsafe : List elem, elem -> List elem
|
||||
|
@ -667,7 +683,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
||||
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
list_append_unsafe(env, original_wrapper, elem, elem_layout)
|
||||
list_append_unsafe(env, layout_interner, original_wrapper, elem, elem_layout)
|
||||
}
|
||||
ListPrepend => {
|
||||
// List.prepend : List elem, elem -> List elem
|
||||
|
@ -676,7 +692,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let original_wrapper = load_symbol(scope, &args[0]).into_struct_value();
|
||||
let (elem, elem_layout) = load_symbol_and_layout(scope, &args[1]);
|
||||
|
||||
list_prepend(env, original_wrapper, elem, elem_layout)
|
||||
list_prepend(env, layout_interner, original_wrapper, elem, elem_layout)
|
||||
}
|
||||
ListReserve => {
|
||||
// List.reserve : List elem, Nat -> List elem
|
||||
|
@ -686,7 +702,14 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
let spare = load_symbol(scope, &args[1]);
|
||||
|
||||
list_reserve(env, list, spare, *element_layout, update_mode)
|
||||
list_reserve(
|
||||
env,
|
||||
layout_interner,
|
||||
list,
|
||||
spare,
|
||||
*element_layout,
|
||||
update_mode,
|
||||
)
|
||||
}
|
||||
ListSwap => {
|
||||
// List.swap : List elem, Nat, Nat -> List elem
|
||||
|
@ -701,6 +724,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
list_swap(
|
||||
env,
|
||||
layout_interner,
|
||||
original_wrapper,
|
||||
index_1.into_int_value(),
|
||||
index_2.into_int_value(),
|
||||
|
@ -720,6 +744,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
list_sublist(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
start.into_int_value(),
|
||||
|
@ -739,6 +764,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let element_layout = list_element_layout!(list_layout);
|
||||
list_drop_at(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
original_wrapper,
|
||||
count.into_int_value(),
|
||||
|
@ -763,6 +789,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_get_unsafe(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
*list_element_layout!(list_layout),
|
||||
element_index.into_int_value(),
|
||||
|
@ -774,6 +801,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_replace_unsafe(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
list,
|
||||
index.into_int_value(),
|
||||
|
@ -844,6 +872,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
let int_type = convert::int_type_from_int_width(env, *int_width);
|
||||
build_int_unary_op(
|
||||
env,
|
||||
layout_interner,
|
||||
parent,
|
||||
arg.into_int_value(),
|
||||
*int_width,
|
||||
|
@ -1033,7 +1062,7 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
NumIntCast => {
|
||||
arguments!(arg);
|
||||
|
||||
let to = basic_type_from_layout(env, layout).into_int_type();
|
||||
let to = basic_type_from_layout(env, layout_interner, layout).into_int_type();
|
||||
let to_signed = intwidth_from_layout(*layout).is_signed();
|
||||
|
||||
env.builder
|
||||
|
@ -1047,7 +1076,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::Int(width)) => {
|
||||
// Converting from int to float
|
||||
let int_val = arg.into_int_value();
|
||||
let dest = basic_type_from_layout(env, layout).into_float_type();
|
||||
let dest =
|
||||
basic_type_from_layout(env, layout_interner, layout).into_float_type();
|
||||
|
||||
if width.is_signed() {
|
||||
env.builder
|
||||
|
@ -1061,7 +1091,8 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
}
|
||||
Layout::Builtin(Builtin::Float(_)) => {
|
||||
// Converting from float to float - e.g. F64 to F32, or vice versa
|
||||
let dest = basic_type_from_layout(env, layout).into_float_type();
|
||||
let dest =
|
||||
basic_type_from_layout(env, layout_interner, layout).into_float_type();
|
||||
|
||||
env.builder
|
||||
.build_float_cast(arg.into_float_value(), dest, "cast_float_to_float")
|
||||
|
@ -1083,12 +1114,28 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
Eq => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
generic_eq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
generic_eq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_arg,
|
||||
rhs_arg,
|
||||
lhs_layout,
|
||||
rhs_layout,
|
||||
)
|
||||
}
|
||||
NotEq => {
|
||||
arguments_with_layouts!((lhs_arg, lhs_layout), (rhs_arg, rhs_layout));
|
||||
|
||||
generic_neq(env, layout_ids, lhs_arg, rhs_arg, lhs_layout, rhs_layout)
|
||||
generic_neq(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
lhs_arg,
|
||||
rhs_arg,
|
||||
lhs_layout,
|
||||
rhs_layout,
|
||||
)
|
||||
}
|
||||
And => {
|
||||
// The (&&) operator
|
||||
|
@ -1137,13 +1184,13 @@ pub(crate) fn run_low_level<'a, 'ctx, 'env>(
|
|||
unreachable!("Not used in LLVM backend: {:?}", op);
|
||||
}
|
||||
|
||||
Unreachable => match RocReturn::from_layout(env, layout) {
|
||||
Unreachable => match RocReturn::from_layout(env, layout_interner, layout) {
|
||||
RocReturn::Return => {
|
||||
let basic_type = basic_type_from_layout(env, layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
basic_type.const_zero()
|
||||
}
|
||||
RocReturn::ByPointer => {
|
||||
let basic_type = basic_type_from_layout(env, layout);
|
||||
let basic_type = basic_type_from_layout(env, layout_interner, layout);
|
||||
let ptr = env.builder.build_alloca(basic_type, "unreachable_alloca");
|
||||
env.builder.build_store(ptr, basic_type.const_zero());
|
||||
|
||||
|
@ -1817,6 +1864,7 @@ fn int_type_signed_min(int_type: IntType) -> IntValue {
|
|||
|
||||
fn build_int_unary_op<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
parent: FunctionValue<'ctx>,
|
||||
arg: IntValue<'ctx>,
|
||||
arg_width: IntWidth,
|
||||
|
@ -1887,8 +1935,8 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
|| // Or if the two types are the same, they trivially fit.
|
||||
arg_width == target_int_width;
|
||||
|
||||
let return_type =
|
||||
convert::basic_type_from_layout(env, return_layout).into_struct_type();
|
||||
let return_type = convert::basic_type_from_layout(env, layout_interner, return_layout)
|
||||
.into_struct_type();
|
||||
|
||||
if arg_always_fits_in_target {
|
||||
// This is guaranteed to succeed so we can just make it an int cast and let LLVM
|
||||
|
@ -1958,8 +2006,9 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
intrinsic,
|
||||
);
|
||||
|
||||
let roc_return_type = basic_type_from_layout(env, return_layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
let roc_return_type =
|
||||
basic_type_from_layout(env, layout_interner, return_layout)
|
||||
.ptr_type(AddressSpace::Generic);
|
||||
|
||||
let roc_return_alloca = env.builder.build_pointer_cast(
|
||||
zig_return_alloca,
|
||||
|
@ -1967,7 +2016,13 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
"cast_to_roc",
|
||||
);
|
||||
|
||||
load_roc_value(env, *return_layout, roc_return_alloca, "num_to_int")
|
||||
load_roc_value(
|
||||
env,
|
||||
layout_interner,
|
||||
*return_layout,
|
||||
roc_return_alloca,
|
||||
"num_to_int",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1978,6 +2033,7 @@ fn build_int_unary_op<'a, 'ctx, 'env>(
|
|||
|
||||
call_bitcode_fn_fixing_for_convention(
|
||||
env,
|
||||
layout_interner,
|
||||
bitcode_return_type,
|
||||
&[arg.into()],
|
||||
return_layout,
|
||||
|
@ -2221,6 +2277,7 @@ fn build_float_unary_op<'a, 'ctx, 'env>(
|
|||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
||||
env: &Env<'a, 'ctx, 'env>,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
scope: &Scope<'a, 'ctx>,
|
||||
return_layout: &Layout<'a>,
|
||||
|
@ -2276,13 +2333,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element_layout = env.layout_interner.get(*element_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element_layout = layout_interner.get(*element_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2292,7 +2350,14 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
*result_layout,
|
||||
);
|
||||
|
||||
list_map(env, roc_function_call, list, element_layout, result_layout)
|
||||
list_map(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function_call,
|
||||
list,
|
||||
element_layout,
|
||||
result_layout,
|
||||
)
|
||||
}
|
||||
_ => unreachable!("invalid list layout"),
|
||||
}
|
||||
|
@ -2309,14 +2374,15 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element2_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = env.layout_interner.get(*element1_layout);
|
||||
let element2_layout = env.layout_interner.get(*element2_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element1_layout, *element2_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2328,6 +2394,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_map2(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
list1,
|
||||
|
@ -2354,15 +2421,16 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element3_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = env.layout_interner.get(*element1_layout);
|
||||
let element2_layout = env.layout_interner.get(*element2_layout);
|
||||
let element3_layout = env.layout_interner.get(*element3_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let element3_layout = layout_interner.get(*element3_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[*element1_layout, *element2_layout, *element3_layout];
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2374,6 +2442,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_map3(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
list1,
|
||||
|
@ -2410,11 +2479,11 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element4_layout)),
|
||||
Layout::Builtin(Builtin::List(result_layout)),
|
||||
) => {
|
||||
let element1_layout = env.layout_interner.get(*element1_layout);
|
||||
let element2_layout = env.layout_interner.get(*element2_layout);
|
||||
let element3_layout = env.layout_interner.get(*element3_layout);
|
||||
let element4_layout = env.layout_interner.get(*element4_layout);
|
||||
let result_layout = env.layout_interner.get(*result_layout);
|
||||
let element1_layout = layout_interner.get(*element1_layout);
|
||||
let element2_layout = layout_interner.get(*element2_layout);
|
||||
let element3_layout = layout_interner.get(*element3_layout);
|
||||
let element4_layout = layout_interner.get(*element4_layout);
|
||||
let result_layout = layout_interner.get(*result_layout);
|
||||
|
||||
let argument_layouts = &[
|
||||
*element1_layout,
|
||||
|
@ -2425,6 +2494,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2436,6 +2506,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_map4(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
roc_function_call,
|
||||
list1,
|
||||
|
@ -2462,17 +2533,23 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
Layout::Builtin(Builtin::List(element_layout)) => {
|
||||
use crate::llvm::bitcode::build_compare_wrapper;
|
||||
|
||||
let element_layout = env.layout_interner.get(*element_layout);
|
||||
let element_layout = layout_interner.get(*element_layout);
|
||||
|
||||
let argument_layouts = &[*element_layout, *element_layout];
|
||||
|
||||
let compare_wrapper =
|
||||
build_compare_wrapper(env, function, closure_layout, element_layout)
|
||||
.as_global_value()
|
||||
.as_pointer_value();
|
||||
let compare_wrapper = build_compare_wrapper(
|
||||
env,
|
||||
layout_interner,
|
||||
function,
|
||||
closure_layout,
|
||||
element_layout,
|
||||
)
|
||||
.as_global_value()
|
||||
.as_pointer_value();
|
||||
|
||||
let roc_function_call = roc_function_call(
|
||||
env,
|
||||
layout_interner,
|
||||
layout_ids,
|
||||
function,
|
||||
closure,
|
||||
|
@ -2484,6 +2561,7 @@ pub(crate) fn run_higher_order_low_level<'a, 'ctx, 'env>(
|
|||
|
||||
list_sort_with(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function_call,
|
||||
compare_wrapper,
|
||||
list,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue