use crate::{ir::Module, logical_result::LogicalResult, string_ref::StringRef, Error};
use mlir_sys::{
mlirExecutionEngineCreate, mlirExecutionEngineDestroy, mlirExecutionEngineInvokePacked,
MlirExecutionEngine,
};
use std::ffi::c_void;
pub struct ExecutionEngine {
raw: MlirExecutionEngine,
}
impl ExecutionEngine {
pub fn new(module: &Module, optimization_level: usize, shared_library_paths: &[&str]) -> Self {
Self {
raw: unsafe {
mlirExecutionEngineCreate(
module.to_raw(),
optimization_level as i32,
shared_library_paths.len() as i32,
shared_library_paths
.iter()
.map(|&string| StringRef::from(string).to_raw())
.collect::<Vec<_>>()
.as_ptr(),
)
},
}
}
pub unsafe fn invoke_packed(&self, name: &str, arguments: &mut [*mut ()]) -> Result<(), Error> {
let result = LogicalResult::from_raw(mlirExecutionEngineInvokePacked(
self.raw,
StringRef::from(name).to_raw(),
arguments.as_mut_ptr() as *mut *mut c_void,
));
if result.is_success() {
Ok(())
} else {
Err(Error::InvokeFunction)
}
}
}
impl Drop for ExecutionEngine {
fn drop(&mut self) {
unsafe { mlirExecutionEngineDestroy(self.raw) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
context::Context,
dialect, pass,
utility::{register_all_dialects, register_all_llvm_translations},
};
#[test]
fn invoke_packed() {
let registry = dialect::Registry::new();
register_all_dialects(®istry);
let context = Context::new();
context.append_dialect_registry(®istry);
register_all_llvm_translations(&context);
let mut module = Module::parse(
&context,
r#"
module {
func.func @add(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } {
%res = arith.addi %arg0, %arg0 : i32
return %res : i32
}
}
"#,
)
.unwrap();
let pass_manager = pass::Manager::new(&context);
pass_manager.add_pass(pass::conversion::convert_func_to_llvm());
pass_manager
.nested_under("func.func")
.add_pass(pass::conversion::convert_arithmetic_to_llvm());
assert_eq!(pass_manager.run(&mut module), Ok(()));
let engine = ExecutionEngine::new(&module, 2, &[]);
let mut argument = 42;
let mut result = -1;
assert_eq!(
unsafe {
engine.invoke_packed(
"add",
&mut [
&mut argument as *mut i32 as *mut (),
&mut result as *mut i32 as *mut (),
],
)
},
Ok(())
);
assert_eq!(argument, 42);
assert_eq!(result, 84);
}
}