macroassembler 1.0.5

A library for writing portable x86-64/riscv64/aarch64 assembly code in Rust
Documentation
use std::sync::Arc;

use crate::jit::free_executable_memory;

pub struct ExecutableMemoryHandle {
    rx: *const u8,
    rw: *mut u8,
    size: usize,
}

impl ExecutableMemoryHandle {
    pub(crate) fn new(rx: *const u8, rw: *mut u8, size: usize) -> Arc<Self> {
        Arc::new(ExecutableMemoryHandle { rx, rw, size })
    }

    pub fn contains(&self, address: *const u8) -> bool {
        let start = self.start() as u64;
        let end = self.end() as u64;
        let address = address as u64;
        address >= start && address < end
    }

    pub fn contains_rw(&self, address: *const u8) -> bool {
        let start = self.start_rw() as u64;
        let end = self.end_rw() as u64;
        let address = address as u64;
        address >= start && address < end
    }

    pub fn start(&self) -> *mut u8 {
        self.rx as _
    }

    pub fn size_in_bytes(&self) -> usize {
        self.size
    }

    pub fn end(&self) -> *mut u8 {
        unsafe { self.start().add(self.size) }
    }

    pub fn start_rw(&self) -> *mut u8 {
        self.rw
    }

    pub fn end_rw(&self) -> *mut u8 {
        unsafe { self.rw.add(self.size) }
    }
}

impl Drop for ExecutableMemoryHandle {
    fn drop(&mut self) {
        let _ = unsafe { free_executable_memory(self.rx) };
    }
}

#[derive(Clone)]
pub enum CodeRef {
    SelfManaged((*mut u8, usize)),
    External(Arc<ExecutableMemoryHandle>),
}

impl CodeRef {
    pub fn start(&self) -> *mut u8 {
        match self {
            CodeRef::SelfManaged((start, _)) => *start,
            CodeRef::External(handle) => handle.start(),
        }
    }

    pub fn size_in_bytes(&self) -> usize {
        match self {
            CodeRef::SelfManaged((_, size)) => *size,
            CodeRef::External(handle) => handle.size_in_bytes(),
        }
    }

    pub fn end(&self) -> *mut u8 {
        unsafe { self.start().add(self.size_in_bytes()) }
    }

    pub fn start_rw(&self) -> Option<*mut u8> {
        match self {
            CodeRef::SelfManaged((_, _)) => None,
            CodeRef::External(handle) => Some(handle.start_rw()),
        }
    }

    pub fn end_rw(&self) -> Option<*mut u8> {
        match self {
            CodeRef::SelfManaged((_, _)) => None,
            CodeRef::External(handle) => Some(handle.end_rw()),
        }
    }

    pub fn contains(&self, address: *const u8) -> bool {
        let start = self.start() as usize;
        let end = self.end() as usize;
        let address = address as usize;
        address >= start && address < end
    }

    pub fn is_self_managed(&self) -> bool {
        match self {
            CodeRef::SelfManaged(_) => true,
            CodeRef::External(_) => false,
        }
    }

    pub fn is_external(&self) -> bool {
        match self {
            CodeRef::SelfManaged(_) => false,
            CodeRef::External(_) => true,
        }
    }
}

pub trait Function<R, A> {
    fn call(&self, args: A) -> R;
}