Rust 锈蚀&x2B;LLVM ORC JIT找不到符号地址

Rust 锈蚀&x2B;LLVM ORC JIT找不到符号地址,rust,llvm,llvm-c++-api,Rust,Llvm,Llvm C++ Api,我一直在尝试使用Rust中LLVM C绑定的ORC JIT编译器,但我一直遇到这样的问题:llvmorcketsymbolAddress无法在我提供的模块中找到我的函数run的符号。下面的代码结合了我的代码中最重要的部分,不幸的是这些部分不起作用。在foo的最后一部分之前,一切都进展顺利,因为找不到函数,所以返回了一个错误。该函数肯定在模块中,因为LLVMGetNamedFunction能够找到它,但ORC引擎不知何故无法看到它。有人能看出我做错了什么吗?我正在使用LLVM 6.0和LLVM s

我一直在尝试使用Rust中LLVM C绑定的ORC JIT编译器,但我一直遇到这样的问题:
llvmorcketsymbolAddress
无法在我提供的模块中找到我的函数
run
的符号。下面的代码结合了我的代码中最重要的部分,不幸的是这些部分不起作用。在
foo
的最后一部分之前,一切都进展顺利,因为找不到函数,所以返回了一个错误。该函数肯定在模块中,因为
LLVMGetNamedFunction
能够找到它,但ORC引擎不知何故无法看到它。有人能看出我做错了什么吗?我正在使用LLVM 6.0和
LLVM sys
Rust绑定。如果我使用MCJIT,一切都很好,但是我需要ORC进行延迟编译

fn foo(module: LLVMModuleRef) -> Result<I64Func, LlvmError> {
    let def_triple = LLVMGetDefaultTargetTriple();
    let mut target_ref = ptr::null_mut();
    let mut error_str = ptr::null_mut();

    // Get target from default triple
    if LLVMGetTargetFromTriple(def_triple, &mut target_ref, &mut error_str) != 0 {
        let msg = format!("Creating target from triple failed: {}", CStr::from_ptr(error_str).to_str().unwrap());
        LLVMDisposeMessage(def_triple);
        LLVMDisposeMessage(error_str);
        return Err(LlvmError(msg));
    }

    // Check if JIT is available
    if LLVMTargetHasJIT(target_ref) == 0 {
        let msg = format!("Cannot do JIT on this platform");
        LLVMDisposeMessage(def_triple);
        return Err(LlvmError(msg));
    }

    // Create target machine
    let tm_ref = LLVMCreateTargetMachine(target_ref, 
                                         def_triple,
                                         CString::new("").unwrap().as_ptr(), 
                                         CString::new("").unwrap().as_ptr(),
                                         llvm_opt_level(optimization_level)?,
                                         LLVMRelocMode::LLVMRelocDefault,
                                         LLVMCodeModel::LLVMCodeModelJITDefault);
    LLVMDisposeMessage(def_triple);
    let engine = LLVMOrcCreateInstance(tm_ref);

    // Add eagerly compiled IR
    let mut handle = LLVMOrcModuleHandle::default();
    let shared_module = LLVMOrcMakeSharedModule(module);
    let ctx = engine as *mut libc::c_void;
    map_orc_err(engine, LLVMOrcAddEagerlyCompiledIR(engine, 
                                                    &mut handle, 
                                                    shared_module, 
                                                    symbol_resolver_callback, 
                                                    ctx))?;

    // Find function named 'run'
    let c_name = CString::new("run").unwrap().as_ptr();
    let mut func_addr = LLVMOrcTargetAddress::default();
    map_orc_err(engine, LLVMOrcGetSymbolAddress(engine, &mut func_addr, c_name))?;
    if func_addr == 0 {
        // This errors always gets thrown
        return Err(LlvmError(format!("No function named {} in module", name)));
    }
    let function: I64Func = mem::transmute(func_addr);

    Ok(function)
}

extern "C" fn symbol_resolver_callback(symbol: *const libc::c_char, ctx: *mut libc::c_void) -> LLVMOrcTargetAddress {
    let mut address = LLVMOrcTargetAddress::default();
    let engine: LLVMOrcJITStackRef = ctx as LLVMOrcJITStackRef;

    unsafe { LLVMOrcGetSymbolAddress(engine, &mut address, symbol) };

    address
}

unsafe fn map_orc_err(engine: LLVMOrcJITStackRef, error_code: LLVMOrcErrorCode) -> Result<(), LlvmError> {
    match error_code {
        LLVMOrcErrorCode::LLVMOrcErrSuccess => Ok(()),
        LLVMOrcErrorCode::LLVMOrcErrGeneric => {
            let c_str: &CStr = CStr::from_ptr(LLVMOrcGetErrorMsg(engine));
            let str_slice: &str = c_str.to_str().unwrap();
            let str_buf: String = str_slice.to_owned();
            Err(LlvmError(str_buf))
        }
    }
}
编辑2:以下是引擎无法找到功能地址的一些基本IR:

define i64 @bar(i64 %arg) {
    %1 = add i64 %arg, 1
    ret i64 %1
}

define i64 @run(i64 %arg) {
    %1 = add i64 %arg, 1
    %2 = call i64 @bar(i64 %1)
    ret i64 %2
}

AFAIK LLVMulcGETMealStand只查看导出的符号(在C++ API中,这是可选的)。是否存在任何可疑的函数属性?这在Windows上也可能失败,因为在标志转换中有(或曾经有)一个错误,但我猜从您的文件名来看,您没有使用它。这就是IR(优化后)中运行函数的样子:define i64@run(i64%r.input)local_unnamed_addr{}我没有使用Windows实际上,我在MacOS上。仅查看导出符号意味着什么?对不起,我对编译器有点陌生。我的代码是基于在LLVM()的单元测试中发现的内容编写的,它似乎也在做同样的事情。在C中,一个
静态
函数不会被导出(到其他翻译单元)。AFAIK JIT中的决策是使用操作系统特定的属性做出的。我只是在这方面遇到了类似的问题,你的问题很可能与此无关。如果您有时间从源代码构建LLVM,您可以通过编辑LLVMorGetSymbolAddress以传递
false
作为FindSymbolAddress的最后一个参数来检查这一点。谢谢,我将尝试从源代码构建它,看看会发生什么。出于好奇,你还记得最后为你修复了什么吗?在Windows上,底层LLVM错误在当时没有被固定,我们不得不使它暴露出未导出的符号,这对我们的用例来说是没有问题的,并且很容易用C++ API来实现。在MacOS和Linux上,JIT得到了更好的支持,因此LLVM缺陷似乎不太可能出现。如果您的程序使用修改后的findSymbol,您可以使用一些IR扩展您的问题,并尝试找出符号未导出的原因。
define i64 @bar(i64 %arg) {
    %1 = add i64 %arg, 1
    ret i64 %1
}

define i64 @run(i64 %arg) {
    %1 = add i64 %arg, 1
    %2 = call i64 @bar(i64 %1)
    ret i64 %2
}