Sorry checker

This commit is contained in:
Ayaz Hafiz 2023-07-07 11:13:06 -05:00
parent 3e23699bb4
commit 1cd9deffe2
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 124 additions and 50 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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()
}