mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
Sorry checker
This commit is contained in:
parent
3e23699bb4
commit
1cd9deffe2
3 changed files with 124 additions and 50 deletions
|
@ -296,7 +296,7 @@ fn build_transform_caller_help<'a, 'ctx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = crate::llvm::build::call_roc_function(
|
let result = crate::llvm::build::call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_function,
|
roc_function,
|
||||||
|
|
|
@ -24,11 +24,11 @@ use inkwell::passes::{PassManager, PassManagerBuilder};
|
||||||
use inkwell::types::{
|
use inkwell::types::{
|
||||||
AnyType, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, StructType,
|
AnyType, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, StructType,
|
||||||
};
|
};
|
||||||
use inkwell::values::BasicValueEnum;
|
|
||||||
use inkwell::values::{
|
use inkwell::values::{
|
||||||
BasicMetadataValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue, PointerValue,
|
BasicMetadataValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue, PointerValue,
|
||||||
StructValue,
|
StructValue,
|
||||||
};
|
};
|
||||||
|
use inkwell::values::{BasicValueEnum, CallableValue};
|
||||||
use inkwell::OptimizationLevel;
|
use inkwell::OptimizationLevel;
|
||||||
use inkwell::{AddressSpace, IntPredicate};
|
use inkwell::{AddressSpace, IntPredicate};
|
||||||
use morphic_lib::{
|
use morphic_lib::{
|
||||||
|
@ -39,7 +39,7 @@ use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_debug_flags::dbg_do;
|
use roc_debug_flags::dbg_do;
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use roc_debug_flags::ROC_PRINT_LLVM_FN_VERIFICATION;
|
use roc_debug_flags::ROC_PRINT_LLVM_FN_VERIFICATION;
|
||||||
use roc_error_macros::todo_lambda_erasure;
|
use roc_error_macros::{internal_error, todo_lambda_erasure};
|
||||||
use roc_module::symbol::{Interns, Symbol};
|
use roc_module::symbol::{Interns, Symbol};
|
||||||
use roc_mono::ir::{
|
use roc_mono::ir::{
|
||||||
BranchInfo, CallType, CrashTag, EntryPoint, GlueLayouts, HostExposedLambdaSet,
|
BranchInfo, CallType, CrashTag, EntryPoint, GlueLayouts, HostExposedLambdaSet,
|
||||||
|
@ -690,7 +690,7 @@ fn promote_to_wasm_test_wrapper<'a, 'ctx>(
|
||||||
let entry = context.append_basic_block(c_function, "entry");
|
let entry = context.append_basic_block(c_function, "entry");
|
||||||
builder.position_at_end(entry);
|
builder.position_at_end(entry);
|
||||||
|
|
||||||
let roc_main_fn_result = call_roc_function(
|
let roc_main_fn_result = call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_main_fn,
|
roc_main_fn,
|
||||||
|
@ -926,7 +926,7 @@ pub(crate) fn build_exp_call<'a, 'ctx>(
|
||||||
let callee_var = CalleeSpecVar(&bytes);
|
let callee_var = CalleeSpecVar(&bytes);
|
||||||
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
||||||
|
|
||||||
roc_call_with_args(
|
roc_call_direct_with_args(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
*ret_layout,
|
*ret_layout,
|
||||||
|
@ -936,8 +936,27 @@ pub(crate) fn build_exp_call<'a, 'ctx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::ByPointer { .. } => {
|
CallType::ByPointer {
|
||||||
todo_lambda_erasure!()
|
pointer,
|
||||||
|
arg_layouts,
|
||||||
|
ret_layout,
|
||||||
|
} => {
|
||||||
|
let mut args: Vec<BasicValueEnum> = Vec::with_capacity_in(arguments.len(), env.arena);
|
||||||
|
|
||||||
|
for symbol in arguments.iter() {
|
||||||
|
args.push(scope.load_symbol(symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
let pointer = scope.load_symbol(pointer).into_pointer_value();
|
||||||
|
|
||||||
|
roc_call_erased_with_args(
|
||||||
|
env,
|
||||||
|
layout_interner,
|
||||||
|
pointer,
|
||||||
|
arg_layouts,
|
||||||
|
*ret_layout,
|
||||||
|
args.into_bump_slice(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
CallType::LowLevel { op, update_mode } => {
|
CallType::LowLevel { op, update_mode } => {
|
||||||
|
@ -3907,7 +3926,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
||||||
builder.position_at_end(entry);
|
builder.position_at_end(entry);
|
||||||
|
|
||||||
let wrapped_layout = roc_call_result_layout(env.arena, return_layout);
|
let wrapped_layout = roc_call_result_layout(env.arena, return_layout);
|
||||||
call_roc_function(
|
call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_function,
|
roc_function,
|
||||||
|
@ -3915,7 +3934,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
||||||
arguments_for_call,
|
arguments_for_call,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
call_roc_function(
|
call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_function,
|
roc_function,
|
||||||
|
@ -4053,7 +4072,7 @@ fn expose_function_to_host_help_c_abi_gen_test<'a, 'ctx>(
|
||||||
|
|
||||||
let wrapper_result = roc_call_result_layout(env.arena, return_layout);
|
let wrapper_result = roc_call_result_layout(env.arena, return_layout);
|
||||||
|
|
||||||
let roc_value = call_roc_function(
|
let roc_value = call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_wrapper_function,
|
roc_wrapper_function,
|
||||||
|
@ -4306,7 +4325,7 @@ fn expose_function_to_host_help_c_abi_v2<'a, 'ctx>(
|
||||||
|
|
||||||
let arguments = Vec::from_iter_in(it, env.arena);
|
let arguments = Vec::from_iter_in(it, env.arena);
|
||||||
|
|
||||||
let value = call_roc_function(
|
let value = call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_function,
|
roc_function,
|
||||||
|
@ -4616,7 +4635,7 @@ fn set_jump_and_catch_long_jump<'a, 'ctx>(
|
||||||
{
|
{
|
||||||
builder.position_at_end(then_block);
|
builder.position_at_end(then_block);
|
||||||
|
|
||||||
let call_result = call_roc_function(
|
let call_result = call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
roc_function,
|
roc_function,
|
||||||
|
@ -5468,7 +5487,7 @@ fn build_closure_caller<'a, 'ctx>(
|
||||||
|
|
||||||
builder.build_store(output, call_result);
|
builder.build_store(output, call_result);
|
||||||
} else {
|
} else {
|
||||||
let call_result = call_roc_function(
|
let call_result = call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
evaluator,
|
evaluator,
|
||||||
|
@ -5665,7 +5684,7 @@ fn function_value_by_name_help<'a, 'ctx>(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn roc_call_with_args<'a, 'ctx>(
|
fn roc_call_direct_with_args<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
result_layout: InLayout<'a>,
|
result_layout: InLayout<'a>,
|
||||||
|
@ -5675,7 +5694,7 @@ fn roc_call_with_args<'a, 'ctx>(
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let fn_val = function_value_by_func_spec(env, func_spec, name.name());
|
let fn_val = function_value_by_func_spec(env, func_spec, name.name());
|
||||||
|
|
||||||
call_roc_function(
|
call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
fn_val,
|
fn_val,
|
||||||
|
@ -5684,14 +5703,70 @@ fn roc_call_with_args<'a, 'ctx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_roc_function<'a, 'ctx>(
|
#[inline(always)]
|
||||||
|
fn roc_call_erased_with_args<'a, 'ctx>(
|
||||||
|
env: &Env<'a, 'ctx, '_>,
|
||||||
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
pointer: PointerValue<'ctx>,
|
||||||
|
argument_layouts: &[InLayout<'a>],
|
||||||
|
result_layout: InLayout<'a>,
|
||||||
|
arguments: &[BasicValueEnum<'ctx>],
|
||||||
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let function_type =
|
||||||
|
fn_ptr::function_type(env, layout_interner, argument_layouts, result_layout);
|
||||||
|
let function_ptr_type = function_type.ptr_type(AddressSpace::default());
|
||||||
|
|
||||||
|
let function_pointer = fn_ptr::cast_to_function_ptr_type(env, pointer, function_ptr_type);
|
||||||
|
let callable_function_pointer = CallableValue::try_from(function_pointer).unwrap();
|
||||||
|
|
||||||
|
let build_call = |arguments: &[BasicMetadataValueEnum<'ctx>]| {
|
||||||
|
env.builder
|
||||||
|
.build_call(callable_function_pointer, arguments, "call")
|
||||||
|
};
|
||||||
|
|
||||||
|
call_roc_function_help(
|
||||||
|
env,
|
||||||
|
layout_interner,
|
||||||
|
build_call,
|
||||||
|
function_type,
|
||||||
|
layout_interner.get_repr(result_layout),
|
||||||
|
arguments,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn call_direct_roc_function<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
roc_function: FunctionValue<'ctx>,
|
roc_function: FunctionValue<'ctx>,
|
||||||
result_layout: LayoutRepr<'a>,
|
result_layout: LayoutRepr<'a>,
|
||||||
arguments: &[BasicValueEnum<'ctx>],
|
arguments: &[BasicValueEnum<'ctx>],
|
||||||
) -> BasicValueEnum<'ctx> {
|
) -> BasicValueEnum<'ctx> {
|
||||||
let pass_by_pointer = roc_function.get_type().get_param_types().len() == arguments.len() + 1;
|
let function_type = roc_function.get_type();
|
||||||
|
|
||||||
|
let build_call = |arguments: &[BasicMetadataValueEnum<'ctx>]| {
|
||||||
|
env.builder.build_call(roc_function, arguments, "call")
|
||||||
|
};
|
||||||
|
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
|
||||||
|
|
||||||
|
call_roc_function_help(
|
||||||
|
env,
|
||||||
|
layout_interner,
|
||||||
|
build_call,
|
||||||
|
function_type,
|
||||||
|
result_layout,
|
||||||
|
arguments,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call_roc_function_help<'a, 'ctx>(
|
||||||
|
env: &Env<'a, 'ctx, '_>,
|
||||||
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
|
build_call: impl FnOnce(&[BasicMetadataValueEnum<'ctx>]) -> CallSiteValue<'ctx>,
|
||||||
|
roc_function_type: FunctionType<'ctx>,
|
||||||
|
result_layout: LayoutRepr<'a>,
|
||||||
|
arguments: &[BasicValueEnum<'ctx>],
|
||||||
|
) -> BasicValueEnum<'ctx> {
|
||||||
|
let pass_by_pointer = roc_function_type.get_param_types().len() == arguments.len() + 1;
|
||||||
|
|
||||||
match RocReturn::from_layout(layout_interner, result_layout) {
|
match RocReturn::from_layout(layout_interner, result_layout) {
|
||||||
RocReturn::ByPointer if !pass_by_pointer => {
|
RocReturn::ByPointer if !pass_by_pointer => {
|
||||||
|
@ -5705,14 +5780,10 @@ pub fn call_roc_function<'a, 'ctx>(
|
||||||
|
|
||||||
arguments.push(result_alloca.into());
|
arguments.push(result_alloca.into());
|
||||||
|
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(roc_function_type.get_param_types().len(), arguments.len());
|
||||||
roc_function.get_type().get_param_types().len(),
|
let call = build_call(&arguments);
|
||||||
arguments.len()
|
|
||||||
);
|
|
||||||
let call = env.builder.build_call(roc_function, &arguments, "call");
|
|
||||||
|
|
||||||
// roc functions should have the fast calling convention
|
// roc functions should have the fast calling convention
|
||||||
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
|
|
||||||
call.set_call_convention(FAST_CALL_CONV);
|
call.set_call_convention(FAST_CALL_CONV);
|
||||||
|
|
||||||
env.builder
|
env.builder
|
||||||
|
@ -5727,14 +5798,10 @@ pub fn call_roc_function<'a, 'ctx>(
|
||||||
|
|
||||||
arguments.push(result_alloca.into());
|
arguments.push(result_alloca.into());
|
||||||
|
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(roc_function_type.get_param_types().len(), arguments.len());
|
||||||
roc_function.get_type().get_param_types().len(),
|
let call = build_call(&arguments);
|
||||||
arguments.len()
|
|
||||||
);
|
|
||||||
let call = env.builder.build_call(roc_function, &arguments, "call");
|
|
||||||
|
|
||||||
// roc functions should have the fast calling convention
|
// roc functions should have the fast calling convention
|
||||||
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
|
|
||||||
call.set_call_convention(FAST_CALL_CONV);
|
call.set_call_convention(FAST_CALL_CONV);
|
||||||
|
|
||||||
if result_layout.is_passed_by_reference(layout_interner) {
|
if result_layout.is_passed_by_reference(layout_interner) {
|
||||||
|
@ -5748,25 +5815,18 @@ pub fn call_roc_function<'a, 'ctx>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RocReturn::Return => {
|
RocReturn::Return => {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(roc_function_type.get_param_types().len(), arguments.len());
|
||||||
roc_function.get_type().get_param_types().len(),
|
|
||||||
arguments.len()
|
|
||||||
);
|
|
||||||
let it = arguments.iter().map(|x| (*x).into());
|
let it = arguments.iter().map(|x| (*x).into());
|
||||||
let arguments = Vec::from_iter_in(it, env.arena);
|
let arguments = Vec::from_iter_in(it, env.arena);
|
||||||
|
|
||||||
let call = env.builder.build_call(roc_function, &arguments, "call");
|
let call = build_call(&arguments);
|
||||||
|
|
||||||
// roc functions should have the fast calling convention
|
// roc functions should have the fast calling convention
|
||||||
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
|
|
||||||
call.set_call_convention(FAST_CALL_CONV);
|
call.set_call_convention(FAST_CALL_CONV);
|
||||||
|
|
||||||
call.try_as_basic_value().left().unwrap_or_else(|| {
|
call.try_as_basic_value()
|
||||||
panic!(
|
.left()
|
||||||
"LLVM error: Invalid call by name for name {:?}",
|
.unwrap_or_else(|| internal_error!("LLVM error: Invalid call by name",))
|
||||||
roc_function.get_name()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6261,7 +6321,7 @@ fn build_foreign_symbol<'a, 'ctx>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
call_roc_function(
|
call_direct_roc_function(
|
||||||
env,
|
env,
|
||||||
layout_interner,
|
layout_interner,
|
||||||
fastcc_function,
|
fastcc_function,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use bumpalo::collections::CollectIn;
|
use bumpalo::collections::CollectIn;
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
types::{FunctionType, PointerType},
|
types::{FunctionType, PointerType},
|
||||||
values::{BasicValueEnum, FunctionValue},
|
values::{BasicValueEnum, FunctionValue, PointerValue},
|
||||||
AddressSpace,
|
AddressSpace,
|
||||||
};
|
};
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
|
@ -14,18 +14,17 @@ use super::{
|
||||||
convert::basic_type_from_layout,
|
convert::basic_type_from_layout,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn function_type<'a, 'ctx>(
|
pub fn function_type<'a, 'ctx>(
|
||||||
env: &Env<'a, 'ctx, '_>,
|
env: &Env<'a, 'ctx, '_>,
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
function_pointer: FunctionPointer<'a>,
|
arguments: &[InLayout<'a>],
|
||||||
|
return_type: InLayout<'a>,
|
||||||
) -> FunctionType<'ctx> {
|
) -> FunctionType<'ctx> {
|
||||||
let FunctionPointer { args, ret } = function_pointer;
|
let args = arguments
|
||||||
|
|
||||||
let args = args
|
|
||||||
.iter()
|
.iter()
|
||||||
.map(|arg| basic_type_from_layout(env, layout_interner, layout_interner.get_repr(*arg)));
|
.map(|arg| basic_type_from_layout(env, layout_interner, layout_interner.get_repr(*arg)));
|
||||||
|
|
||||||
let ret_repr = layout_interner.get_repr(ret);
|
let ret_repr = layout_interner.get_repr(return_type);
|
||||||
let ret = basic_type_from_layout(env, layout_interner, ret_repr);
|
let ret = basic_type_from_layout(env, layout_interner, ret_repr);
|
||||||
|
|
||||||
let roc_return = RocReturn::from_layout(layout_interner, ret_repr);
|
let roc_return = RocReturn::from_layout(layout_interner, ret_repr);
|
||||||
|
@ -40,7 +39,12 @@ pub fn pointer_type<'a, 'ctx>(
|
||||||
layout_interner: &STLayoutInterner<'a>,
|
layout_interner: &STLayoutInterner<'a>,
|
||||||
function_pointer: FunctionPointer<'a>,
|
function_pointer: FunctionPointer<'a>,
|
||||||
) -> PointerType<'ctx> {
|
) -> PointerType<'ctx> {
|
||||||
let function_type = function_type(env, layout_interner, function_pointer);
|
let function_type = function_type(
|
||||||
|
env,
|
||||||
|
layout_interner,
|
||||||
|
function_pointer.args,
|
||||||
|
function_pointer.ret,
|
||||||
|
);
|
||||||
|
|
||||||
function_type.ptr_type(AddressSpace::default())
|
function_type.ptr_type(AddressSpace::default())
|
||||||
}
|
}
|
||||||
|
@ -73,3 +77,13 @@ pub fn build<'a, 'ctx>(
|
||||||
.build_store(alloca, func_value.as_global_value().as_pointer_value());
|
.build_store(alloca, func_value.as_global_value().as_pointer_value());
|
||||||
alloca.into()
|
alloca.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast_to_function_ptr_type<'ctx>(
|
||||||
|
env: &Env<'_, 'ctx, '_>,
|
||||||
|
pointer: PointerValue<'ctx>,
|
||||||
|
function_pointer_type: PointerType<'ctx>,
|
||||||
|
) -> PointerValue<'ctx> {
|
||||||
|
env.builder
|
||||||
|
.build_bitcast(pointer, function_pointer_type, "cast_to_function_ptr")
|
||||||
|
.into_pointer_value()
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue