我正在编写一个库,它将利用 LLVM(通过inkwell)来JIT 编译一些函数。这些函数需要能够回调到我的代码中的一些 rust 函数中。
我让它工作了,但我的单元测试不起作用,因为似乎在构建测试时回调函数被优化掉了。这些回调函数不会被 Rust 代码本身调用——只能被动态生成的 JIT 函数调用——所以我猜链接器认为它们没有被使用并删除它们。
如果我在单元测试中从 rust 代码中调用它们,那么它们不会被删除 - 但这不是一个理想的解决方法。另请注意,当包作为库构建时,函数不会被删除,只有在构建测试时才会删除。
下面是一个MVCE。
// lib.rs
use inkwell::{OptimizationLevel, context::Context};
use inkwell::execution_engine::JitFunction;
#[no_mangle]
pub extern "C" fn my_callback(x:i64) {
println!("Called Back x={}", x);
}
type FuncType = unsafe extern "C" fn();
pub fn compile_fn() {
let context = Context::create();
let module = context.create_module("test");
let execution_engine = module.create_jit_execution_engine(OptimizationLevel::None).unwrap();
let builder = context.create_builder();
let func_type = context.void_type().fn_type(&[], false);
let function = module.add_function("test", func_type, None);
let basic_block = context.append_basic_block(function, "entry");
builder.position_at_end(basic_block);
let cb_fn_type = context.void_type().fn_type(&[context.i64_type().into()], false);
let cb_fn = module.add_function("my_callback", cb_fn_type, None);
let x = context.i64_type().const_int(42, false);
builder.build_call(cb_fn, &[x.into()], "callback");
builder.build_return(None);
function.print_to_stderr();
let jit_func:JitFunction<FuncType> = unsafe { execution_engine.get_function("test").unwrap() };
unsafe { jit_func.call() };
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
// If I uncomment this line, it works, otherwise it segfaults
//super::my_callback(1);
super::compile_fn();
}
}
Run Code Online (Sandbox Code Playgroud)
# Cargo.toml
[package]
name = "so_example_lib"
version = "0.1.0"
authors = ["harmic <harmic@no-reply.com>"]
edition = "2018"
[dependencies]
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm7-0"] }
Run Code Online (Sandbox Code Playgroud)
# Cargo.toml
[package]
name = "so_example_lib"
version = "0.1.0"
authors = ["harmic <harmic@no-reply.com>"]
edition = "2018"
[dependencies]
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "master", features = ["llvm7-0"] }
Run Code Online (Sandbox Code Playgroud)
您可以通过nm在生成的测试二进制文件上运行来判断该函数已被删除。当您运行测试时,它会出现段错误。如果您在 gdb 中运行它,您可以看到它正在尝试调用0x0000000000000000.
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff7ff201f in test ()
Run Code Online (Sandbox Code Playgroud)
如何指示 Rust 不要删除这些函数?
| 归档时间: |
|
| 查看次数: |
68 次 |
| 最近记录: |