use crate::error::LaminaError;
use crate::mir::Module as MirModule;
use crate::mir_codegen::validate_module_call_parameters;
use lamina_platform::{TargetArchitecture, TargetOperatingSystem};
use ras::RasRuntime;
use std::collections::HashMap;
pub struct RuntimeCompiler {
target_arch: TargetArchitecture,
#[allow(dead_code)] runtime: RasRuntime,
code_cache: HashMap<String, ras::ExecutableMemory>,
}
impl RuntimeCompiler {
pub fn new(target_arch: TargetArchitecture, target_os: TargetOperatingSystem) -> Self {
Self {
target_arch,
runtime: RasRuntime::new(target_arch, target_os),
code_cache: HashMap::new(),
}
}
pub fn compile(
&mut self,
_module: &MirModule,
_function_name: Option<&str>,
) -> Result<ras::ExecutableMemory, LaminaError> {
#[cfg(feature = "encoder")]
{
validate_module_call_parameters(_module, self.target_arch)?;
self.runtime.compile_to_memory(_module).map_err(|e| {
let error_msg = format!("{}", e);
if error_msg.contains("not yet implemented")
|| error_msg.contains("Unsupported target")
{
LaminaError::ValidationError(format!(
"JIT compilation is not supported for this target (or the MIR uses an unsupported construct).\n\
Error: {}\n\
JIT machine code is emitted only for x86_64 and AArch64.\n\
Consider AOT compilation instead (run without --jit).",
error_msg
))
} else {
LaminaError::ValidationError(format!("Runtime compilation failed: {}", e))
}
})
}
#[cfg(not(feature = "encoder"))]
{
Err(LaminaError::ValidationError(
"Runtime compilation requires the 'encoder' feature to be enabled in ras"
.to_string(),
))
}
}
pub unsafe fn compile_function<T>(
&mut self,
module: &MirModule,
function_name: &str,
) -> Result<unsafe extern "C" fn() -> T, LaminaError> {
let memory = self.compile(module, Some(function_name))?;
unsafe {
let ptr = memory.code_start();
if ptr.is_null() {
return Err(LaminaError::ValidationError(
"ExecutableMemory has null ptr".to_string(),
));
}
let f: unsafe extern "C" fn() -> T = std::mem::transmute(ptr);
Ok(f)
}
}
pub fn invalidate(&mut self, function_name: &str) {
self.code_cache.remove(function_name);
}
pub fn clear_cache(&mut self) {
self.code_cache.clear();
}
}