make it actually work

This commit is contained in:
Folkert 2020-11-05 00:02:49 +01:00
parent cb28e533b8
commit 0289fe37a5
5 changed files with 63 additions and 38 deletions

View file

@ -125,7 +125,7 @@ pub fn gen_from_mono_module(
} }
// Uncomment this to see the module's optimized LLVM instruction output: // Uncomment this to see the module's optimized LLVM instruction output:
env.module.print_to_stderr(); // env.module.print_to_stderr();
mpm.run_on(module); mpm.run_on(module);

View file

@ -2158,6 +2158,8 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
let context = &env.context; let context = &env.context;
let builder = env.builder; let builder = env.builder;
// STEP 1: build function header
let function_name = format!( let function_name = format!(
"{}_{}_caller", "{}_{}_caller",
def_name, def_name,
@ -2215,7 +2217,7 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
function_value.set_call_conventions(C_CALL_CONV); function_value.set_call_conventions(C_CALL_CONV);
// BUILD FUNCTION BODY // STEP 2: build function body
let entry = context.append_basic_block(function_value, "entry"); let entry = context.append_basic_block(function_value, "entry");
@ -2235,18 +2237,36 @@ pub fn build_closure_caller<'a, 'ctx, 'env>(
let result = call.try_as_basic_value().left().unwrap(); let result = call.try_as_basic_value().left().unwrap();
// TODO here we just assume success (first i64 is 0)
unsafe { unsafe {
let tag_ptr = builder.build_struct_gep(output, 0, "gep"); // let tag_ptr = builder.build_struct_gep(output, 0, "gep");
let result_ptr = builder.build_struct_gep(output, 1, "gep"); let result_ptr = builder.build_struct_gep(output, 1, "gep");
// let v33 = context.i64_type().const_int(33, false);
// builder.build_store(tag_ptr, v33);
builder.build_store(result_ptr, result); builder.build_store(result_ptr, result);
} }
//builder.build_store(output, roc_call_result);
builder.build_return(None); builder.build_return(None);
// STEP 3: build a {} -> u64 function that gives the size of the return type
let size_function_type = env.context.i64_type().fn_type(&[], false);
let size_function_name: String = format!(
"{}_{}_size",
def_name,
alias_symbol.ident_string(&env.interns)
);
let size_function = env.module.add_function(
size_function_name.as_str(),
size_function_type,
Some(Linkage::External),
);
let entry = context.append_basic_block(size_function, "entry");
builder.position_at_end(entry);
let size: BasicValueEnum = roc_call_result_type.size_of().unwrap().into();
builder.build_return(Some(&size));
} }
#[allow(dead_code)] #[allow(dead_code)]

View file

@ -3,6 +3,7 @@ app Closure provides [ makeClosure ] imports []
makeClosure : ({} -> Int) as MyClosure makeClosure : ({} -> Int) as MyClosure
makeClosure = makeClosure =
x = 42 x = 42
y = 42
\{} -> x \{} -> x + y

View file

@ -1,6 +1,6 @@
use roc_std::alloca;
use std::alloc::Layout; use std::alloc::Layout;
use std::ffi::CString; use std::ffi::CString;
use std::mem::MaybeUninit;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::time::SystemTime; use std::time::SystemTime;
use RocCallResult::*; use RocCallResult::*;
@ -9,40 +9,36 @@ extern "C" {
#[link_name = "makeClosure_1_exposed"] #[link_name = "makeClosure_1_exposed"]
fn make_closure(output: *mut u8) -> (); fn make_closure(output: *mut u8) -> ();
#[link_name = "makeClosure_1_MyClosure_caller"]
fn call_MyClosure(
unit: (),
function_pointer: *const u8,
closure_data: *const u8,
output: *mut u8,
) -> ();
#[link_name = "makeClosure_1_size"] #[link_name = "makeClosure_1_size"]
fn closure_size() -> i64; fn closure_size() -> i64;
#[link_name = "makeClosure_1_MyClosure_caller"]
fn call_MyClosure(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> ();
#[link_name = "makeClosure_1_MyClosure_size"]
fn size_MyClosure() -> i64;
} }
unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 { unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 {
// wow let size = size_MyClosure() as usize;
let layout = Layout::array::<u8>(100).unwrap();
// let buffer = std::alloc::alloc(layout);
let mut foo = (0, 0);
let buffer: *mut (i64, i64) = &mut foo;
call_MyClosure( alloca::with_stack_bytes(size, |buffer| {
(), let buffer: *mut std::ffi::c_void = buffer;
function_pointer, let buffer: *mut u8 = buffer as *mut u8;
closure_data_ptr as *const u8,
buffer as *mut u8,
);
dbg!(*buffer); call_MyClosure(
function_pointer,
closure_data_ptr as *const u8,
buffer as *mut u8,
);
let output = &*(buffer as *mut RocCallResult<i64>); let output = &*(buffer as *mut RocCallResult<i64>);
match output.into() { match output.into() {
Ok(v) => v, Ok(v) => v,
Err(e) => panic!("failed with {}", e), Err(e) => panic!("failed with {}", e),
} }
})
} }
#[no_mangle] #[no_mangle]
@ -57,12 +53,19 @@ pub fn rust_main() -> isize {
make_closure(buffer); make_closure(buffer);
let output = &*(buffer as *mut RocCallResult<(*const u8, ())>); let output = &*(buffer as *mut RocCallResult<((), ())>);
match output.into() { match output.into() {
Ok((function_pointer, _)) => { Ok((_, _)) => {
let function_pointer = {
// this is a pointer to the location where the function pointer is stored
// we pass just the function pointer
let temp = buffer.offset(8) as *const i64;
(*temp) as *const u8
};
let closure_data_ptr = buffer.offset(16); let closure_data_ptr = buffer.offset(16);
dbg!(*closure_data_ptr);
call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8) call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8)
} }

View file

@ -63,7 +63,8 @@ unsafe fn malloc_or_alloca(bytes: usize) -> *mut c_void {
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
#[inline(always)] #[inline(always)]
unsafe fn malloc_or_alloca(bytes: usize) -> *mut c_void { unsafe fn malloc_or_alloca(bytes: usize) -> *mut c_void {
c_alloca(bytes) // c_alloca(bytes)
libc::malloc(bytes)
} }
#[cfg(debug_assertions)] #[cfg(debug_assertions)]