check if exposed function is defined already

This commit is contained in:
Folkert 2021-10-03 00:57:54 +02:00
parent dbb8acbe67
commit 9e97a09a87

View file

@ -5637,6 +5637,22 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
let builder = env.builder; let builder = env.builder;
let context = env.context; let context = env.context;
let fastcc_function_name = format!("{}_fastcc_wrapper", foreign.as_str());
let (fastcc_function, arguments) = match env.module.get_function(fastcc_function_name.as_str())
{
Some(function_value) => {
let mut arguments = Vec::with_capacity_in(argument_symbols.len(), env.arena);
for symbol in argument_symbols {
let (value, _) = load_symbol_and_layout(scope, symbol);
arguments.push(value);
}
(function_value, arguments)
}
None => {
// Here we build two functions: // Here we build two functions:
// //
// - an C_CALL_CONV extern that will be provided by the host, e.g. `roc_fx_putLine` // - an C_CALL_CONV extern that will be provided by the host, e.g. `roc_fx_putLine`
@ -5647,8 +5663,10 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
let return_type = basic_type_from_layout(env, ret_layout); let return_type = basic_type_from_layout(env, ret_layout);
let cc_return = to_cc_return(env, ret_layout); let cc_return = to_cc_return(env, ret_layout);
let mut cc_argument_types = Vec::with_capacity_in(argument_symbols.len() + 1, env.arena); let mut cc_argument_types =
let mut fastcc_argument_types = Vec::with_capacity_in(argument_symbols.len(), env.arena); Vec::with_capacity_in(argument_symbols.len() + 1, env.arena);
let mut fastcc_argument_types =
Vec::with_capacity_in(argument_symbols.len(), env.arena);
let mut arguments = Vec::with_capacity_in(argument_symbols.len(), env.arena); let mut arguments = Vec::with_capacity_in(argument_symbols.len(), env.arena);
for symbol in argument_symbols { for symbol in argument_symbols {
@ -5677,7 +5695,7 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
let fastcc_function = add_func( let fastcc_function = add_func(
env.module, env.module,
&format!("{}_fastcc_wrapper", foreign.as_str()), &fastcc_function_name,
fastcc_type, fastcc_type,
Linkage::Private, Linkage::Private,
FAST_CALL_CONV, FAST_CALL_CONV,
@ -5691,13 +5709,16 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
let return_pointer = env.builder.build_alloca(return_type, "return_value"); let return_pointer = env.builder.build_alloca(return_type, "return_value");
let fastcc_parameters = fastcc_function.get_params(); let fastcc_parameters = fastcc_function.get_params();
let mut cc_arguments = Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena); let mut cc_arguments =
Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena);
for (param, cc_type) in fastcc_parameters.into_iter().zip(cc_argument_types.iter()) { for (param, cc_type) in fastcc_parameters.into_iter().zip(cc_argument_types.iter())
{
if param.get_type() == *cc_type { if param.get_type() == *cc_type {
cc_arguments.push(param); cc_arguments.push(param);
} else { } else {
let as_cc_type = complex_bitcast(env.builder, param, *cc_type, "to_cc_type"); let as_cc_type =
complex_bitcast(env.builder, param, *cc_type, "to_cc_type");
cc_arguments.push(as_cc_type); cc_arguments.push(as_cc_type);
} }
} }
@ -5720,6 +5741,11 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
} }
builder.position_at_end(old); builder.position_at_end(old);
(fastcc_function, arguments)
}
};
let call = env.builder.build_call(fastcc_function, &arguments, "tmp"); let call = env.builder.build_call(fastcc_function, &arguments, "tmp");
call.set_call_convention(FAST_CALL_CONV); call.set_call_convention(FAST_CALL_CONV);
return call.try_as_basic_value().left().unwrap(); return call.try_as_basic_value().left().unwrap();