#pragma once
#include "types.h"
#include <map>
#include <string>
#if defined(_WIN32)
enum class PageProtect : u32
{
NoAccess = 0x01,
ReadOnly = 0x02,
ReadWrite = 0x04,
ReadExecute = 0x20,
ReadWriteExecute = 0x40,
};
#elif defined(__APPLE__)
#include <mach/mach_vm.h>
enum class PageProtect : u32
{
NoAccess = VM_PROT_NONE,
ReadOnly = VM_PROT_READ,
ReadWrite = VM_PROT_READ | VM_PROT_WRITE,
ReadExecute = VM_PROT_READ | VM_PROT_EXECUTE,
ReadWriteExecute = VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE,
};
#else
#include <sys/mman.h>
enum class PageProtect : u32
{
NoAccess = PROT_NONE,
ReadOnly = PROT_READ,
ReadWrite = PROT_READ | PROT_WRITE,
ReadExecute = PROT_READ | PROT_EXEC,
ReadWriteExecute = PROT_READ | PROT_WRITE | PROT_EXEC,
};
#endif
class Error;
namespace MemMap {
u32 GetRuntimePageSize();
std::string GetFileMappingName(const char* prefix);
void* CreateSharedMemory(const char* name, size_t size, Error* error);
void DeleteSharedMemory(const char* name);
void DestroySharedMemory(void* ptr);
void* MapSharedMemory(void* handle, size_t offset, void* baseaddr, size_t size, PageProtect mode);
void UnmapSharedMemory(void* baseaddr, size_t size);
bool MemProtect(void* baseaddr, size_t size, PageProtect mode);
const void* GetBaseAddress();
void* AllocateJITMemory(size_t size);
void ReleaseJITMemory(void* ptr, size_t size);
#if !defined(CPU_ARCH_ARM32) && !defined(CPU_ARCH_ARM64) && !defined(CPU_ARCH_RISCV64)
ALWAYS_INLINE static void FlushInstructionCache(void* address, size_t size) { }
#else
void FlushInstructionCache(void* address, size_t size);
#endif
#if !defined(__APPLE__) || !defined(__aarch64__)
ALWAYS_INLINE static void BeginCodeWrite() { }
ALWAYS_INLINE static void EndCodeWrite() { }
#else
void BeginCodeWrite();
void EndCodeWrite();
#endif
}
class SharedMemoryMappingArea
{
public:
SharedMemoryMappingArea();
~SharedMemoryMappingArea();
ALWAYS_INLINE size_t GetSize() const { return m_size; }
ALWAYS_INLINE size_t GetNumPages() const { return m_num_pages; }
ALWAYS_INLINE u8* BasePointer() const { return m_base_ptr; }
ALWAYS_INLINE u8* OffsetPointer(size_t offset) const { return m_base_ptr + offset; }
ALWAYS_INLINE u8* PagePointer(size_t page) const { return m_base_ptr + (page << HOST_PAGE_SHIFT); }
bool Create(size_t size);
void Destroy();
u8* Map(void* file_handle, size_t file_offset, void* map_base, size_t map_size, PageProtect mode);
bool Unmap(void* map_base, size_t map_size);
private:
u8* m_base_ptr = nullptr;
size_t m_size = 0;
size_t m_num_pages = 0;
size_t m_num_mappings = 0;
#ifdef _WIN32
using PlaceholderMap = std::map<size_t, size_t>;
PlaceholderMap::iterator FindPlaceholder(size_t page);
PlaceholderMap m_placeholder_ranges;
#endif
};