use crate::util::{AsUsize};
use super::{code, Engine, CaseId};
use super::target::{Label, Word, Target};
use code::{Marshal, EBB};
array_index! {
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct EntryId(std::num::NonZeroUsize) {
debug_name: "EntryId",
UInt: usize,
}
}
#[derive(Debug)]
struct Entry {
label: Label,
case: CaseId,
is_defined: bool,
}
#[derive(Debug)]
pub struct Jit<T: Target> {
engine: Engine<T>,
entries: Vec<Entry>,
}
macro_rules! get {
($self: expr, $id: expr) => ($self.entries[$id.as_usize()])
}
impl<T: Target> Jit<T> {
pub fn new(target: T) -> Self {
Self {
engine: Engine::new(target),
entries: Vec::new(),
}
}
pub fn new_entry(&mut self, marshal: &Marshal, exit_value: i64) -> EntryId {
let (label, case) = self.engine.new_entry(marshal, exit_value);
let id = EntryId::new(self.entries.len()).unwrap();
self.entries.push(Entry {label, case, is_defined: false});
id
}
pub fn define(&mut self, entry: EntryId, ebb: &EBB<EntryId>) {
assert!(!get!(self, entry).is_defined);
self.engine.build(get!(self, entry).case, ebb, &|e| get!(self, e).case);
get!(self, entry).is_defined = true;
}
pub unsafe fn run<G>(&mut self, entry: EntryId, global: &mut G) -> Word {
let label = &get!(self, entry).label;
self.engine.run(label, global as *mut G as *mut ())
}
}
#[cfg(test)]
pub mod tests {
use super::super::target::{native};
use super::super::factorial::*;
#[test]
pub fn factorial() {
let mut jit = Factorial::new(native());
let result = jit.run(5);
assert_eq!(result, 120);
}
}