mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 14:24:45 +00:00
make fastcc wrapper return by pointer if return type is large
This commit is contained in:
parent
430a82810b
commit
b2e05b92d1
1 changed files with 35 additions and 10 deletions
|
@ -6212,6 +6212,7 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
// - a FAST_CALL_CONV wrapper that we make here, e.g. `roc_fx_putLine_fastcc_wrapper`
|
// - a FAST_CALL_CONV wrapper that we make here, e.g. `roc_fx_putLine_fastcc_wrapper`
|
||||||
|
|
||||||
let return_type = basic_type_from_layout(env, ret_layout);
|
let return_type = basic_type_from_layout(env, ret_layout);
|
||||||
|
let roc_return = RocReturn::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 =
|
let mut cc_argument_types =
|
||||||
|
@ -6249,8 +6250,17 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
let cc_function = get_foreign_symbol(env, foreign.clone(), cc_type);
|
let cc_function = get_foreign_symbol(env, foreign.clone(), cc_type);
|
||||||
|
|
||||||
let fastcc_type =
|
let fastcc_type = match roc_return {
|
||||||
return_type.fn_type(&function_arguments(env, &fastcc_argument_types), false);
|
RocReturn::Return => {
|
||||||
|
return_type.fn_type(&function_arguments(env, &fastcc_argument_types), false)
|
||||||
|
}
|
||||||
|
RocReturn::ByPointer => {
|
||||||
|
fastcc_argument_types.push(return_type.ptr_type(AddressSpace::Generic).into());
|
||||||
|
env.context
|
||||||
|
.void_type()
|
||||||
|
.fn_type(&function_arguments(env, &fastcc_argument_types), false)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let fastcc_function = add_func(
|
let fastcc_function = add_func(
|
||||||
env.module,
|
env.module,
|
||||||
|
@ -6265,12 +6275,16 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
let entry = context.append_basic_block(fastcc_function, "entry");
|
let entry = context.append_basic_block(fastcc_function, "entry");
|
||||||
{
|
{
|
||||||
builder.position_at_end(entry);
|
builder.position_at_end(entry);
|
||||||
let return_pointer = env.builder.build_alloca(return_type, "return_value");
|
|
||||||
|
|
||||||
let fastcc_parameters = fastcc_function.get_params();
|
let mut fastcc_parameters = fastcc_function.get_params();
|
||||||
let mut cc_arguments =
|
let mut cc_arguments =
|
||||||
Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena);
|
Vec::with_capacity_in(fastcc_parameters.len() + 1, env.arena);
|
||||||
|
|
||||||
|
let return_pointer = match roc_return {
|
||||||
|
RocReturn::Return => env.builder.build_alloca(return_type, "return_value"),
|
||||||
|
RocReturn::ByPointer => fastcc_parameters.pop().unwrap().into_pointer_value(),
|
||||||
|
};
|
||||||
|
|
||||||
let it = fastcc_parameters.into_iter().zip(cc_argument_types.iter());
|
let it = fastcc_parameters.into_iter().zip(cc_argument_types.iter());
|
||||||
for (param, cc_type) in it {
|
for (param, cc_type) in it {
|
||||||
if param.get_type() == *cc_type {
|
if param.get_type() == *cc_type {
|
||||||
|
@ -6289,14 +6303,25 @@ fn build_foreign_symbol<'a, 'ctx, 'env>(
|
||||||
let call = env.builder.build_call(cc_function, &cc_arguments, "tmp");
|
let call = env.builder.build_call(cc_function, &cc_arguments, "tmp");
|
||||||
call.set_call_convention(C_CALL_CONV);
|
call.set_call_convention(C_CALL_CONV);
|
||||||
|
|
||||||
let return_value = match cc_return {
|
match roc_return {
|
||||||
CCReturn::Return => call.try_as_basic_value().left().unwrap(),
|
RocReturn::Return => {
|
||||||
|
let return_value = match cc_return {
|
||||||
|
CCReturn::Return => call.try_as_basic_value().left().unwrap(),
|
||||||
|
|
||||||
CCReturn::ByPointer => env.builder.build_load(return_pointer, "read_result"),
|
CCReturn::ByPointer => {
|
||||||
CCReturn::Void => return_type.const_zero(),
|
env.builder.build_load(return_pointer, "read_result")
|
||||||
};
|
}
|
||||||
|
CCReturn::Void => return_type.const_zero(),
|
||||||
|
};
|
||||||
|
|
||||||
builder.build_return(Some(&return_value));
|
builder.build_return(Some(&return_value));
|
||||||
|
}
|
||||||
|
RocReturn::ByPointer => {
|
||||||
|
debug_assert!(matches!(cc_return, CCReturn::ByPointer));
|
||||||
|
|
||||||
|
builder.build_return(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.position_at_end(old);
|
builder.position_at_end(old);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue