alduin 0.0.1

WIP: A toy compiler backend
Documentation
use dynasmrt::{dynasm, DynasmApi};
use dynasmrt::{x64::X64Relocation, VecAssembler};

use crate::rt::vm::VirtualMachine;

#[no_mangle]
pub unsafe extern "C" fn resolve_function(return_addr: *const u8) -> *const u8 {
    // For now, assume this is just a static call
    let vm = VirtualMachine::get_instance_by_code_interior_pointer(return_addr).unwrap();
    let code = vm
        .compiler
        .code
        .get_code_by_interior_pointer(return_addr)
        .unwrap();
    let call_site = code.get_call_site(return_addr).unwrap();
    trace!("Lazy compile: {:?}", call_site.symbol());
    let entry = vm.resolve(call_site.symbol()).entry();
    call_site.patch(entry);
    entry
}

pub fn gen_lazy_compilation_trampoline() -> Vec<u8> {
    let mut ops = VecAssembler::<X64Relocation>::new(0);

    dynasm! { ops
        ; push rbp
        ; mov rbp, rsp
        // Spill args
        ; push rdi
        ; push rsi
        ; push rdx
        ; push rcx
        ; push r8
        ; push r9
        ; sub rsp, 16
        ; movsd [rsp], xmm0
        ; sub rsp, 16
        ; movsd [rsp], xmm1
        ; sub rsp, 16
        ; movsd [rsp], xmm2
        ; sub rsp, 16
        ; movsd [rsp], xmm3
        ; sub rsp, 16
        ; movsd [rsp], xmm4
        ; sub rsp, 16
        ; movsd [rsp], xmm5
        // Get return address
        ; mov rdi, [rbp + 0x8]
        ; mov rax, QWORD resolve_function as _
        ; call rax
        // resolved function is in rax
        // restore parameters and call the resolved function
        ; movsd xmm5, [rsp]
        ; add rsp, 16
        ; movsd xmm4, [rsp]
        ; add rsp, 16
        ; movsd xmm3, [rsp]
        ; add rsp, 16
        ; movsd xmm2, [rsp]
        ; add rsp, 16
        ; movsd xmm1, [rsp]
        ; add rsp, 16
        ; movsd xmm0, [rsp]
        ; add rsp, 16
        ; pop r9
        ; pop r8
        ; pop rcx
        ; pop rdx
        ; pop rsi
        ; pop rdi
        ; mov rsp, rbp
        ; pop rbp
        ; jmp rax
    };

    ops.finalize().unwrap()
}