///|
/// Raw address returned by the native JIT-memory allocator.
type MemPointer = UInt64
///|
/// Opaque handle returned by `dlopen`.
#external
priv type LibHandle
///|
/// Raw C function address returned by `dlsym`.
type FnPointer = UInt64
///|
/// Allocate one RW memory region for generated code.
extern "c" fn __mmap(length : UInt64) -> MemPointer = "asm_dot_mbt_mmap"
///|
/// Check whether a raw mmap result is `MAP_FAILED`.
extern "c" fn mmap_failed(pointer : MemPointer) -> Bool = "asm_dot_mbt_mmap_failed"
///|
/// Return the current C `errno` value.
extern "c" fn errno() -> Int32 = "asm_dot_mbt_errno"
///|
/// Allocate one RW memory region for generated code, raising on failure.
fn mmap(length : UInt64) -> MemPointer raise ASMContextError {
let pointer = __mmap(length)
if mmap_failed(pointer) {
raise ExecutableMemoryAllocationFailed(length, errno())
}
pointer
}
///|
/// Switch a generated-code mapping from RW to RX.
extern "c" fn __mprotect_rx(start : UInt64, length : UInt64) -> Int32 = "asm_dot_mbt_mprotect_rx"
///|
/// Switch a generated-code mapping from RW to RX, raising on failure.
fn mprotect_rx(start : UInt64, length : UInt64) -> Unit raise ASMContextError {
if __mprotect_rx(start, length) != 0 {
raise ExecutableMemoryProtectionFailed(start, length, errno())
}
}
///|
/// Open the current process as a dynamic-library handle.
extern "c" fn dlopen() -> LibHandle = "asm_dot_mbt_dlopen"
///|
/// Resolve a symbol from a dynamic-library handle.
#borrow(symbol)
extern "c" fn __dlsym(handle : LibHandle, symbol : Bytes) -> FnPointer = "dlsym"
///|
/// Resolve a UTF-8 symbol name to a raw function address.
fn dlsym(handle : LibHandle, symbol : String) -> FnPointer {
let symbol = @utf8.encode(symbol)
__dlsym(handle, symbol)
}
///|
/// Look up a Linux syscall number by canonical syscall name, such as
/// `"getpid"` or `"write"`.
///
/// Returns `None` when the current native target does not expose that syscall
/// macro, or when the name is not in the stub's syscall table.
pub fn linux_syscall_number(name : String) -> Int32? {
let number = __linux_syscall_number(@utf8.encode(name))
if number >= 0 {
Some(number)
} else {
None
}
}
///|
/// Raw Linux syscall lookup backed by `SYS_*` macros in the C stub.
#borrow(name)
extern "c" fn __linux_syscall_number(name : Bytes) -> Int32 = "asm_dot_mbt_linux_syscall_number"
///|
/// Copy generated bytes into writable JIT memory.
#borrow(machcode)
extern "c" fn copy_code(start : UInt64, machcode : Bytes, len : UInt64) -> Unit = "asm_dot_mbt_copy_code"
///|
/// Cast a finalized code address to a nullary Int64 function reference.
extern "c" fn code_func_ref_i64(start : UInt64) -> FuncRef[() -> Int64] = "asm_dot_mbt_func_ref_i64"