alduin 0.0.1

WIP: A toy compiler backend
Documentation
use std::{borrow::Cow, collections::HashMap, fmt::Debug};

use crate::rt::Value;

use super::{code_space::CodeBuffer, graph::Signature};

/// A buffer of the generated binary machine code, with corresponding relocation information
pub trait CompiledCode: Debug + Send + Sync + 'static {
    /// Get symbol.
    fn symbol(&self) -> &Symbol;
    /// The function signature.
    fn signature(&self) -> &Signature;
    /// The code buffer.
    fn code_buffer(&self) -> &CodeBuffer;
    /// Entrypoint offset within the buffer.
    fn entry_offset(&self) -> usize;
    /// Entrypoint pointer.
    fn entry(&self) -> *const u8 {
        &self.code_buffer()[self.entry_offset()] as *const u8
    }
    /// Get callsite info for a return address
    fn get_call_site(&self, return_address: *const u8) -> Option<&dyn CallSite>;
    /// Resolve all the relocatable symbols.
    fn link(&self, symbols: &HashMap<Symbol, *const u8>);
    /// Invoke this function.
    fn invoke(&self, args: &[Value]) -> Option<Value>;
    /// Dump asm code in text format, to stdout.
    fn dump(&self);
}

/// Metadata for a callsite in a compiled code object
pub trait CallSite: Send + Sync {
    fn symbol(&self) -> &Symbol;
    fn patch(&self, addr: *const u8);
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub enum Symbol {
    /// Static dispatch to an named function
    NamedFn(Cow<'static, str>),
    /// Static dispatch to a numbered function. i.e. a function with a integer, not a string, as it's name
    NumberedFn(usize),
    /// Static dispatch to an external function with known adderss
    ExternFn(*const u8),
}

impl Symbol {
    pub fn named(name: &'static str) -> Self {
        Self::NamedFn(Cow::Borrowed(name))
    }
}

unsafe impl Send for Symbol {}
unsafe impl Sync for Symbol {}