mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +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,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
|
|
|
@ -24,11 +24,11 @@ use inkwell::passes::{PassManager, PassManagerBuilder};
|
|||
use inkwell::types::{
|
||||
AnyType, BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType, IntType, StructType,
|
||||
};
|
||||
use inkwell::values::BasicValueEnum;
|
||||
use inkwell::values::{
|
||||
BasicMetadataValueEnum, CallSiteValue, FunctionValue, InstructionValue, IntValue, PointerValue,
|
||||
StructValue,
|
||||
};
|
||||
use inkwell::values::{BasicValueEnum, CallableValue};
|
||||
use inkwell::OptimizationLevel;
|
||||
use inkwell::{AddressSpace, IntPredicate};
|
||||
use morphic_lib::{
|
||||
|
@ -39,7 +39,7 @@ use roc_collections::all::{MutMap, MutSet};
|
|||
use roc_debug_flags::dbg_do;
|
||||
#[cfg(debug_assertions)]
|
||||
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_mono::ir::{
|
||||
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");
|
||||
builder.position_at_end(entry);
|
||||
|
||||
let roc_main_fn_result = call_roc_function(
|
||||
let roc_main_fn_result = call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_main_fn,
|
||||
|
@ -926,7 +926,7 @@ pub(crate) fn build_exp_call<'a, 'ctx>(
|
|||
let callee_var = CalleeSpecVar(&bytes);
|
||||
let func_spec = func_spec_solutions.callee_spec(callee_var).unwrap();
|
||||
|
||||
roc_call_with_args(
|
||||
roc_call_direct_with_args(
|
||||
env,
|
||||
layout_interner,
|
||||
*ret_layout,
|
||||
|
@ -936,8 +936,27 @@ pub(crate) fn build_exp_call<'a, 'ctx>(
|
|||
)
|
||||
}
|
||||
|
||||
CallType::ByPointer { .. } => {
|
||||
todo_lambda_erasure!()
|
||||
CallType::ByPointer {
|
||||
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 } => {
|
||||
|
@ -3907,7 +3926,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
builder.position_at_end(entry);
|
||||
|
||||
let wrapped_layout = roc_call_result_layout(env.arena, return_layout);
|
||||
call_roc_function(
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
|
@ -3915,7 +3934,7 @@ fn expose_function_to_host_help_c_abi_generic<'a, 'ctx>(
|
|||
arguments_for_call,
|
||||
)
|
||||
} else {
|
||||
call_roc_function(
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
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 roc_value = call_roc_function(
|
||||
let roc_value = call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
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 value = call_roc_function(
|
||||
let value = call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
|
@ -4616,7 +4635,7 @@ fn set_jump_and_catch_long_jump<'a, 'ctx>(
|
|||
{
|
||||
builder.position_at_end(then_block);
|
||||
|
||||
let call_result = call_roc_function(
|
||||
let call_result = call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
roc_function,
|
||||
|
@ -5468,7 +5487,7 @@ fn build_closure_caller<'a, 'ctx>(
|
|||
|
||||
builder.build_store(output, call_result);
|
||||
} else {
|
||||
let call_result = call_roc_function(
|
||||
let call_result = call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
evaluator,
|
||||
|
@ -5665,7 +5684,7 @@ fn function_value_by_name_help<'a, 'ctx>(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn roc_call_with_args<'a, 'ctx>(
|
||||
fn roc_call_direct_with_args<'a, 'ctx>(
|
||||
env: &Env<'a, 'ctx, '_>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
result_layout: InLayout<'a>,
|
||||
|
@ -5675,7 +5694,7 @@ fn roc_call_with_args<'a, 'ctx>(
|
|||
) -> BasicValueEnum<'ctx> {
|
||||
let fn_val = function_value_by_func_spec(env, func_spec, name.name());
|
||||
|
||||
call_roc_function(
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
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, '_>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
roc_function: FunctionValue<'ctx>,
|
||||
result_layout: LayoutRepr<'a>,
|
||||
arguments: &[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) {
|
||||
RocReturn::ByPointer if !pass_by_pointer => {
|
||||
|
@ -5705,14 +5780,10 @@ pub fn call_roc_function<'a, 'ctx>(
|
|||
|
||||
arguments.push(result_alloca.into());
|
||||
|
||||
debug_assert_eq!(
|
||||
roc_function.get_type().get_param_types().len(),
|
||||
arguments.len()
|
||||
);
|
||||
let call = env.builder.build_call(roc_function, &arguments, "call");
|
||||
debug_assert_eq!(roc_function_type.get_param_types().len(), arguments.len());
|
||||
let call = build_call(&arguments);
|
||||
|
||||
// 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);
|
||||
|
||||
env.builder
|
||||
|
@ -5727,14 +5798,10 @@ pub fn call_roc_function<'a, 'ctx>(
|
|||
|
||||
arguments.push(result_alloca.into());
|
||||
|
||||
debug_assert_eq!(
|
||||
roc_function.get_type().get_param_types().len(),
|
||||
arguments.len()
|
||||
);
|
||||
let call = env.builder.build_call(roc_function, &arguments, "call");
|
||||
debug_assert_eq!(roc_function_type.get_param_types().len(), arguments.len());
|
||||
let call = build_call(&arguments);
|
||||
|
||||
// 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);
|
||||
|
||||
if result_layout.is_passed_by_reference(layout_interner) {
|
||||
|
@ -5748,25 +5815,18 @@ pub fn call_roc_function<'a, 'ctx>(
|
|||
}
|
||||
}
|
||||
RocReturn::Return => {
|
||||
debug_assert_eq!(
|
||||
roc_function.get_type().get_param_types().len(),
|
||||
arguments.len()
|
||||
);
|
||||
debug_assert_eq!(roc_function_type.get_param_types().len(), arguments.len());
|
||||
let it = arguments.iter().map(|x| (*x).into());
|
||||
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
|
||||
debug_assert_eq!(roc_function.get_call_conventions(), FAST_CALL_CONV);
|
||||
call.set_call_convention(FAST_CALL_CONV);
|
||||
|
||||
call.try_as_basic_value().left().unwrap_or_else(|| {
|
||||
panic!(
|
||||
"LLVM error: Invalid call by name for name {:?}",
|
||||
roc_function.get_name()
|
||||
)
|
||||
})
|
||||
call.try_as_basic_value()
|
||||
.left()
|
||||
.unwrap_or_else(|| internal_error!("LLVM error: Invalid call by name",))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6261,7 +6321,7 @@ fn build_foreign_symbol<'a, 'ctx>(
|
|||
}
|
||||
};
|
||||
|
||||
call_roc_function(
|
||||
call_direct_roc_function(
|
||||
env,
|
||||
layout_interner,
|
||||
fastcc_function,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use bumpalo::collections::CollectIn;
|
||||
use inkwell::{
|
||||
types::{FunctionType, PointerType},
|
||||
values::{BasicValueEnum, FunctionValue},
|
||||
values::{BasicValueEnum, FunctionValue, PointerValue},
|
||||
AddressSpace,
|
||||
};
|
||||
use roc_error_macros::internal_error;
|
||||
|
@ -14,18 +14,17 @@ use super::{
|
|||
convert::basic_type_from_layout,
|
||||
};
|
||||
|
||||
fn function_type<'a, 'ctx>(
|
||||
pub fn function_type<'a, 'ctx>(
|
||||
env: &Env<'a, 'ctx, '_>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
function_pointer: FunctionPointer<'a>,
|
||||
arguments: &[InLayout<'a>],
|
||||
return_type: InLayout<'a>,
|
||||
) -> FunctionType<'ctx> {
|
||||
let FunctionPointer { args, ret } = function_pointer;
|
||||
|
||||
let args = args
|
||||
let args = arguments
|
||||
.iter()
|
||||
.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 roc_return = RocReturn::from_layout(layout_interner, ret_repr);
|
||||
|
@ -40,7 +39,12 @@ pub fn pointer_type<'a, 'ctx>(
|
|||
layout_interner: &STLayoutInterner<'a>,
|
||||
function_pointer: FunctionPointer<'a>,
|
||||
) -> 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())
|
||||
}
|
||||
|
@ -73,3 +77,13 @@ pub fn build<'a, 'ctx>(
|
|||
.build_store(alloca, func_value.as_global_value().as_pointer_value());
|
||||
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