picoalloc 5.2.0

Simple, small and fast memory allocator
Documentation
use crate::Size;

#[cold]
pub fn abort() -> ! {
    #[cfg(target_arch = "x86_64")]
    unsafe {
        core::arch::asm!("ud2", options(noreturn, nostack));
    }

    #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
    unsafe {
        core::arch::asm!("unimp", options(noreturn, nostack));
    }

    #[cfg(target_family = "wasm")]
    {
        core::arch::wasm32::unreachable();
    }

    #[cfg(not(any(target_arch = "x86_64", target_arch = "riscv32", target_arch = "riscv64", target_family = "wasm")))]
    unreachable!();
}

pub trait Env {
    fn total_space(&self) -> Size;
    unsafe fn allocate_address_space(&mut self) -> *mut u8;
    unsafe fn expand_memory_until(&mut self, base: *mut u8, size: Size) -> bool;
    unsafe fn free_address_space(&mut self, base: *mut u8);
}

#[repr(align(32))]
pub struct Array<const SIZE: usize>(pub [u8; SIZE]);

#[repr(transparent)]
pub struct ArrayPointer<const SIZE: usize>(*mut Array<SIZE>);

impl<const SIZE: usize> ArrayPointer<SIZE> {
    pub const unsafe fn new(array: *mut Array<SIZE>) -> Self {
        ArrayPointer(array)
    }
}

impl<const SIZE: usize> Env for ArrayPointer<SIZE> {
    fn total_space(&self) -> Size {
        const { Size::from_bytes_usize(SIZE).unwrap() }
    }

    unsafe fn allocate_address_space(&mut self) -> *mut u8 {
        self.0.cast()
    }

    unsafe fn expand_memory_until(&mut self, _base: *mut u8, size: Size) -> bool {
        size <= const { Size::from_bytes_usize(SIZE).unwrap() }
    }

    unsafe fn free_address_space(&mut self, _base: *mut u8) {}
}

pub struct System<const SIZE: usize>;

#[cfg(all(target_arch = "x86_64", target_os = "linux"))]
mod linux;

#[cfg(all(target_env = "polkavm", not(feature = "corevm")))]
mod polkavm;

#[cfg(all(target_env = "polkavm", feature = "corevm"))]
mod corevm;

#[cfg(target_family = "wasm")]
mod wasm;