TomBebbington / llvm-rs

LLVM wrappers for Rust
BSD 3-Clause "New" or "Revised" License
68 stars 27 forks source link

with_function fails to pass args properly when number of args > 3 #22

Open dpzmick opened 8 years ago

dpzmick commented 8 years ago

see this example: https://github.com/dpzmick/llvm-rs/blob/master/examples/add3.rs

For me, this spits out nonsense.

built against llvm-3.8, will try against 3.9 and update ticket.

I'm still looking for the source of the issue. It doesn't appear to be an issue with calling conventions but I wouldn't mind being proven wrong about that.

dpzmick commented 8 years ago

it looks like the implementation of get_function() used by with_function() is correct.

llvm-sys doesn't implement llvm::ExecutionEngine::getPointerToFunction() but, looking at the code in 3.9, its basically exactly the same thing as getGlobalValueAddress() so getting the function as a global value seems like it should be fine.

image

dpzmick commented 8 years ago

llvm-3.9 does not resolve the issue.

I've also isolated the issue to this crate. The equivalent example using only llvm-sys works correctly.

see: https://bitbucket.org/dpzmick/llvm-sys.rs/src/622927a96d48e6548b8ed71d75115c5ecc19953c/examples/jit-function.rs?at=default&fileviewer=file-view-default

dpzmick commented 8 years ago

I've found the source of the issue.

Memory layout for tuples is not well defined in rust, so using a tuple in with_function is causing all sorts of havoc.

Doing something like this with the function passed back by with_function fixes the problem:

    ee.with_function(func, |add:extern "C" fn((f64, f64, f64)) -> f64| {
        let f: extern "C" fn(f64, f64, f64) -> f64 = unsafe { mem::transmute(add) };
        println!("{} + {} + {} = {}", 1., 2., 3., f(1., 2., 3.));
    });

I'll start working on a fix