alduin 0.0.1

WIP: A toy compiler backend
Documentation
pub mod reg_alloc;
pub mod x64;

use std::fmt::Debug;
use std::hash::Hash;
use std::sync::Arc;

use crate::compiler::compiled_code::{CompiledCode, Symbol};
use crate::compiler::graph::{cfg::CFG, Graph, NodeId, OpCode};
use crate::compiler::Compiler;
use crate::{compiler::graph::Signature, rt::Value};

pub trait Reg:
    Clone + Copy + PartialEq + Eq + Hash + Debug + 'static + From<usize> + Into<usize>
{
    const MAX_COUNT: usize;
    const GPRS: &'static [Self];
    const FPRS: &'static [Self];

    const RESERVED_GPRS: &'static [Self];
    const RESERVED_FPRS: &'static [Self];

    fn is_gpr(&self) -> bool {
        Self::GPRS.contains(self) || Self::RESERVED_GPRS.contains(self)
    }

    fn is_fpr(&self) -> bool {
        Self::FPRS.contains(self) || Self::RESERVED_FPRS.contains(self)
    }
}

pub trait ISA: 'static {
    /// Physical registers
    type Reg: Reg;

    /// Lowest-level OpCode for codegen
    type Op: OpCode;

    /// Register pre-coloring before register allocation
    fn pre_assign_registers(graph: &mut Graph, node: NodeId);

    /// Code generation
    fn codegen(
        compiler: &Compiler,
        symbol: Symbol,
        cfg: &mut CFG<Self::Op>,
    ) -> Arc<dyn CompiledCode>;

    /// Coalesce live interval by ISA constraints
    fn coalesce_live_intervals(g: &Graph, n: NodeId, coalesce: impl FnMut(NodeId, NodeId));

    /// Flush cache
    fn flush_cache(start: *const u8, bytes: usize);

    fn gen_lazy_compilation_trampoline() -> Vec<u8>;
}

#[cfg(target_arch = "x86_64")]
pub fn invoke_compiled_method(
    signature: &Signature,
    entry: *const u8,
    args: &[Value],
) -> Option<Value> {
    x64::rt::invoke_compiled_method(signature, entry, args)
}