use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use crate::{
backend::ISA,
compiler::compiled_code::CompiledCode,
compiler::graph::{cfg, Graph},
};
type Isa = crate::backend::x64::X64;
use super::{
code_space::{CodeBuffer, CodeSpace},
compiled_code::Symbol,
};
pub struct Compiler {
pub(crate) code: CodeSpace,
functions: Mutex<HashMap<Symbol, Box<Graph>>>,
compiled_functions: Mutex<HashMap<Symbol, Arc<dyn CompiledCode>>>,
pub(crate) lazy_compilation_trampoline: CodeBuffer,
}
impl Compiler {
pub fn new() -> Self {
crate::init_logger();
let code = CodeSpace::new(128 << 20);
let lazy_compilation_trampoline =
code.alloc_code_buffer::<Isa>(&Isa::gen_lazy_compilation_trampoline());
Self {
code,
functions: Mutex::new(HashMap::default()),
compiled_functions: Mutex::new(HashMap::default()),
lazy_compilation_trampoline,
}
}
pub fn compile(&self, name: Symbol, graph: Box<Graph>) {
let mut cfg = cfg::schedule::<Isa>(graph);
let compiled_code = {
let compiled_code = Isa::codegen(self, name.clone(), &mut cfg);
compiled_code
};
self.compiled_functions
.lock()
.unwrap()
.insert(name.clone(), compiled_code);
self.functions.lock().unwrap().insert(name, cfg.g);
}
pub fn contains(&self, name: &Symbol) -> bool {
self.functions.lock().unwrap().contains_key(name)
}
pub fn finalize<Isa: ISA>(&mut self) {
let mut symbol_addrs: HashMap<Symbol, *const u8> = HashMap::new();
let mut compiled_functions = self.compiled_functions.lock().unwrap();
for (func, code) in &*compiled_functions {
symbol_addrs.insert(func.clone(), code.entry());
}
for (_, code) in &mut *compiled_functions {
code.link(&symbol_addrs);
}
}
pub fn get(&self, name: &Symbol) -> Arc<dyn CompiledCode> {
let funcs = self.compiled_functions.lock().unwrap();
funcs[name].clone()
}
}