pass arguments (e.g. Msg, Model) by-reference, so the host does not need to know their size

This commit is contained in:
Folkert 2020-12-13 22:08:12 +01:00
parent f80c2aa2f4
commit a5e93cc21b
2 changed files with 50 additions and 18 deletions

View File

@ -2249,12 +2249,10 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
let mut argument_types = Vec::with_capacity_in(arguments.len() + 3, env.arena);
for layout in arguments {
argument_types.push(basic_type_from_layout(
arena,
context,
layout,
env.ptr_bytes,
));
let arg_type = basic_type_from_layout(arena, context, layout, env.ptr_bytes);
let arg_ptr_type = arg_type.ptr_type(AddressSpace::Generic);
argument_types.push(arg_ptr_type.into());
}
let function_pointer_type = {
@ -2310,6 +2308,12 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
let closure_data = builder.build_load(closure_data_ptr, "load_closure_data");
let mut parameters = parameters;
for param in parameters.iter_mut() {
debug_assert!(param.is_pointer_value());
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
parameters.push(closure_data);
let call_result = invoke_and_catch(env, function_value, function_ptr, &parameters, result_type);
@ -2357,12 +2361,10 @@ pub fn build_function_caller<'a, 'ctx, 'env>(
let mut argument_types = Vec::with_capacity_in(arguments.len() + 3, env.arena);
for layout in arguments {
argument_types.push(basic_type_from_layout(
arena,
context,
layout,
env.ptr_bytes,
));
let arg_type = basic_type_from_layout(arena, context, layout, env.ptr_bytes);
let arg_ptr_type = arg_type.ptr_type(AddressSpace::Generic);
argument_types.push(arg_ptr_type.into());
}
let function_pointer_type = {
@ -2429,6 +2431,13 @@ pub fn build_function_caller<'a, 'ctx, 'env>(
.build_bitcast(function_ptr, actual_function_type, "cast")
.into_pointer_value();
let mut parameters = parameters;
for param in parameters.iter_mut() {
debug_assert!(param.is_pointer_value());
*param = builder.build_load(param.into_pointer_value(), "load_param");
}
let call_result = invoke_and_catch(env, function_value, function_ptr, &parameters, result_type);
builder.build_store(output, call_result);

View File

@ -17,7 +17,12 @@ extern "C" {
fn roc_main_size() -> i64;
#[link_name = "roc__mainForHost_1_Init_caller"]
fn call_Init(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> ();
fn _call_Init(
flags: &(),
function_pointer: *const u8,
closure_data: *const u8,
output: *mut u8,
) -> ();
#[link_name = "roc__mainForHost_1_Init_size"]
fn size_Init() -> i64;
@ -27,8 +32,8 @@ extern "C" {
#[link_name = "roc__mainForHost_1_Update_caller"]
fn call_Update(
msg: Msg,
model: Model,
msg: &Msg,
model: &Model,
function_pointer: *const u8,
closure_data: *const u8,
output: *mut u8,
@ -41,7 +46,12 @@ extern "C" {
fn size_Update_result() -> i64;
#[link_name = "roc__mainForHost_1_Fx_caller"]
fn call_Fx(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> ();
fn _call_Fx(
unit: &(),
function_pointer: *const u8,
closure_data: *const u8,
output: *mut u8,
) -> ();
#[link_name = "roc__mainForHost_1_Fx_size"]
fn size_Fx() -> i64;
@ -53,6 +63,17 @@ extern "C" {
fn size_Model() -> i64;
}
unsafe fn call_Fx(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> () {
// Fx (or Cmd on the roc side) is a thunk, so we know its first argument is a (pointer to) unit
_call_Fx(&(), function_pointer, closure_data, output)
}
unsafe fn call_Init(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> () {
// for now, we hardcode flags to be `()` (or `{}` on the roc side)
let flags = ();
_call_Init(&flags, function_pointer, closure_data, output)
}
#[no_mangle]
pub fn roc_fx_putChar(foo: i64) -> () {
let character = foo as u8 as char;
@ -152,9 +173,11 @@ unsafe fn run_update(
let buffer: *mut std::ffi::c_void = buffer;
let buffer: *mut u8 = buffer as *mut u8;
println!("let's try update!");
call_Update(
msg,
model,
&msg,
&model,
function_pointer,
closure_data_ptr,
buffer as *mut u8,