use llvm_sys::prelude::LLVMBool;
pub trait McjitMemoryManager: std::fmt::Debug {
fn allocate_code_section(
&mut self,
size: libc::uintptr_t,
alignment: libc::c_uint,
section_id: libc::c_uint,
section_name: &str,
) -> *mut u8;
fn allocate_data_section(
&mut self,
size: libc::uintptr_t,
alignment: libc::c_uint,
section_id: libc::c_uint,
section_name: &str,
is_read_only: bool,
) -> *mut u8;
fn finalize_memory(&mut self) -> Result<(), String>;
fn destroy(&mut self);
}
#[derive(Debug)]
pub struct MemoryManagerAdapter {
pub memory_manager: Box<dyn McjitMemoryManager>,
}
pub(crate) extern "C" fn allocate_code_section_adapter(
opaque: *mut libc::c_void,
size: libc::uintptr_t,
alignment: libc::c_uint,
section_id: libc::c_uint,
section_name: *const libc::c_char,
) -> *mut u8 {
let adapter = unsafe { &mut *(opaque as *mut MemoryManagerAdapter) };
let sname = unsafe { c_str_to_str(section_name) };
adapter
.memory_manager
.allocate_code_section(size, alignment, section_id, sname)
}
pub(crate) extern "C" fn allocate_data_section_adapter(
opaque: *mut libc::c_void,
size: libc::uintptr_t,
alignment: libc::c_uint,
section_id: libc::c_uint,
section_name: *const libc::c_char,
is_read_only: LLVMBool,
) -> *mut u8 {
let adapter = unsafe { &mut *(opaque as *mut MemoryManagerAdapter) };
let sname = unsafe { c_str_to_str(section_name) };
adapter
.memory_manager
.allocate_data_section(size, alignment, section_id, sname, is_read_only != 0)
}
pub(crate) extern "C" fn finalize_memory_adapter(
opaque: *mut libc::c_void,
err_msg_out: *mut *mut libc::c_char,
) -> libc::c_int {
let adapter = unsafe { &mut *(opaque as *mut MemoryManagerAdapter) };
match adapter.memory_manager.finalize_memory() {
Ok(()) => 0,
Err(e) => {
let cstring = std::ffi::CString::new(e).unwrap_or_default();
unsafe {
*err_msg_out = cstring.into_raw();
}
1
},
}
}
pub(crate) extern "C" fn destroy_adapter(opaque: *mut libc::c_void) {
let mut adapter = unsafe { Box::from_raw(opaque as *mut MemoryManagerAdapter) };
adapter.memory_manager.destroy();
}
unsafe fn c_str_to_str<'a>(ptr: *const libc::c_char) -> &'a str {
if ptr.is_null() {
""
} else {
unsafe { std::ffi::CStr::from_ptr(ptr) }.to_str().unwrap_or("")
}
}