inkwell icon indicating copy to clipboard operation
inkwell copied to clipboard

Segmentation Fault While Running Kaleidoscope

Open fiveseven-lambda opened this issue 3 years ago • 4 comments

Describe the Bug Running examples/kaleidoscope/main.rs on my environment causes a segmentation fault when given the following inputs:

?> extern printd(double)

?> printd(10)

To Reproduce (1) run cargo init, (2) put examples/kaleidoscope/main.rs in src/, (3) add inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm12-0"] } to Cargo.toml, (4) run cargo run or cargo run --release, and (5) type extern printd(double) and printd(10).

Expected Behavior printd function defined in main.rs (lines 1202 - 1207) should be called.

LLVM Version (please complete the following information):

  • LLVM Version: 12.0
  • Inkwell Branch Used: master
$ yay -Q llvm
llvm 12.0.1-2
$ tail -n1 Cargo.toml 
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm12-0"] }

Desktop (please complete the following information):

  • OS: Arch Linux

Additional Context

$ rustc --version
rustc 1.54.0 (a178d0322 2021-07-26)

fiveseven-lambda avatar Jul 31 '21 02:07 fiveseven-lambda

I think I'm seeing this behavior as well in a small test program I'm running.

Somewhat relatedly is there a canonical (and small) example of writing function in rust that the JIT linker can find and call appropriately? I assume that's what the #[used] EXTERNAL_FNS provides here. Is there any way to tell the JIT about symbols more explicitly?

besquared avatar Nov 04 '21 01:11 besquared

We probably want https://thedan64.github.io/inkwell/llvm_sys/support/fn.LLVMAddSymbol.html but it doesn't look like we currently wrap it? Probably due to wild unsafety. I wouldn't be opposed to someone adding an unsafe wrapper to it

TheDan64 avatar Nov 04 '21 01:11 TheDan64

For anyone wanting to remedy this with LLVMAddSymbol, it's not super involved.

I created a file to put all the 'library' functions in and defined a static cstr name for each.

macro_rules! cstr {
    ($str:expr) => {
        unsafe { CStr::from_bytes_with_nul_unchecked(concat!($str, "\0").as_bytes()) }
    };
}

static PUTCHARD_NAME: &'static CStr = cstr!("putchard");
#[no_mangle]
pub extern "C" fn putchard(x: f64) -> f64 {

then I created a struct to track the type and name of these print functions, and made a static array of all of them, e.g.

pub static PRINT_FNS: [PrintFunc; 2] = [ ... ];

Then I defined a shim function like this

fn shim_lib_functions() {
    for func in &crate::library::PRINT_FNS {
        let fn_name = func.name.as_ptr();
        let fn_ptr = func.func_pointer as *mut c_void;
        unsafe { LLVMAddSymbol(fn_name, fn_ptr) };
    }
}

and called it before the repl's main loop:

fn run(&mut self) -> Result<(), std::io::Error> {
    Self::shim_lib_functions();

    loop {
    ...

pejato avatar Mar 05 '22 21:03 pejato

Should there be an issue open to get the kaleidoscope example running with the current state of the library? Perhaps providing a wrapper over LLVMAddSymbol and using it when compiling external function prototypes?

I was able to get the example running using the above suggestion but its not as clean or safe as I would want.

countzero1000 avatar Aug 16 '22 20:08 countzero1000