Rust 锈蚀&x2B;LLVM ORC JIT找不到符号地址
我一直在尝试使用Rust中LLVM C绑定的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
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
}