217 lines
5.5 KiB
Rust
217 lines
5.5 KiB
Rust
use std::ffi::{c_void, c_int, c_ushort, c_uint};
|
|
use std::mem::ManuallyDrop;
|
|
use std::ptr::{addr_of_mut, NonNull};
|
|
|
|
use crate::{Closure, GCheader, Proto, StkId, Table, TString, TValue, Udata, UpVal};
|
|
|
|
opaque! {
|
|
pub type global_State;
|
|
|
|
pub type Instruction;
|
|
}
|
|
|
|
extern "C" {
|
|
pub static luaO_nilobject_: TValue;
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn luaO_nilobject() -> NonNull<TValue> {
|
|
unsafe { NonNull::new_unchecked(std::ptr::addr_of!(luaO_nilobject_).cast_mut()) }
|
|
}
|
|
|
|
/// Union of all collectible objects
|
|
#[repr(C)]
|
|
pub union GCObject
|
|
{
|
|
pub gch: ManuallyDrop<GCheader>,
|
|
pub ts: ManuallyDrop<TString>,
|
|
pub u: ManuallyDrop<Udata>,
|
|
pub cl: ManuallyDrop<Closure>,
|
|
pub h: ManuallyDrop<Table>,
|
|
pub p: ManuallyDrop<Proto>,
|
|
pub uv: ManuallyDrop<UpVal>,
|
|
/// thread
|
|
pub th: ManuallyDrop<lua_State>,
|
|
}
|
|
|
|
impl std::fmt::Debug for GCObject {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(f, "GCObject({:?})", unsafe { self.gch })
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
#[repr(transparent)]
|
|
pub struct GCObjectPtr(pub *mut GCObject);
|
|
|
|
impl GCObjectPtr {
|
|
pub fn hdr(self) -> *mut GCheader {
|
|
unsafe { addr_of_mut!(*(*self.0).gch) }
|
|
}
|
|
}
|
|
|
|
impl From<GCObjectPtr> for *mut GCObject {
|
|
#[inline(always)]
|
|
fn from(value: GCObjectPtr) -> Self {
|
|
value.0
|
|
}
|
|
}
|
|
|
|
impl From<*mut GCObject> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut GCObject) -> Self {
|
|
Self(value)
|
|
}
|
|
}
|
|
|
|
impl From<*mut GCheader> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut GCheader) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut TString> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut TString) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut Udata> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut Udata) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut Closure> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut Closure) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut Table> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut Table) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut Proto> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut Proto) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut UpVal> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut UpVal) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
impl From<*mut lua_State> for GCObjectPtr {
|
|
#[inline(always)]
|
|
fn from(value: *mut lua_State) -> Self {
|
|
unsafe { GCObjectPtr(std::mem::transmute(value)) }
|
|
}
|
|
}
|
|
|
|
/// See docs at <https://github.com/Roblox/luau/blob/a02eb78c96f695a4287e7dd1beaccab3642c35f3/VM/src/lstate.h#L29-L29>
|
|
#[derive(Debug)]
|
|
#[repr(C)]
|
|
pub struct CallInfo {
|
|
/// base for this function.
|
|
pub base: StkId,
|
|
/// function index in the stack
|
|
pub func: StkId,
|
|
/// top for this function
|
|
///
|
|
/// Seems to indicate the allocated stack size, not used.
|
|
pub top: StkId,
|
|
|
|
pub saved_pc: *const Instruction,
|
|
|
|
/// expected number of results from this function
|
|
pub n_results: c_int,
|
|
|
|
/// call frame flags, see LUA_CALLINFO_*
|
|
pub flags: c_uint,
|
|
}
|
|
|
|
/// should the interpreter return after returning from this callinfo? first frame must have this set
|
|
pub const LUA_CALLINFO_RETURN: c_uint = 1 << 0;
|
|
/// should the error thrown during execution get handled by continuation from this callinfo? func must be C
|
|
pub const LUA_CALLINFO_HANDLE: c_uint = 1 << 1;
|
|
/// should this function be executed using execution callback for native code
|
|
pub const LUA_CALLINFO_NATIVE: c_uint = 1 << 2;
|
|
|
|
/// A raw Lua state associated with a thread.
|
|
#[derive(Debug)]
|
|
#[repr(C)]
|
|
pub struct lua_State {
|
|
pub tt: u8,
|
|
pub marked: u8,
|
|
pub memcat: u8,
|
|
|
|
pub status: u8,
|
|
|
|
/// memory category that is used for new GC object allocations
|
|
pub active_memcat: u8,
|
|
|
|
/// thread is currently executing, stack may be mutated without barriers
|
|
pub is_active: bool,
|
|
/// call debugstep hook after each instruction
|
|
pub single_step: bool,
|
|
|
|
|
|
/// first free slot in the stack
|
|
pub top: StkId,
|
|
/// base of current function
|
|
pub base: StkId,
|
|
pub global: *mut global_State,
|
|
/// call info for current function
|
|
pub ci: *mut CallInfo,
|
|
/// last free slot in the stack
|
|
pub stack_last: StkId,
|
|
/// stack base
|
|
pub stack: StkId,
|
|
|
|
|
|
/// points after end of ci array
|
|
pub end_ci: *mut CallInfo,
|
|
/// array of [`CallInfo`]s
|
|
pub base_ci: *mut CallInfo,
|
|
|
|
|
|
/// The current allocated size of the entire thread stack.
|
|
pub stack_size: c_int,
|
|
/// size of array [`base_ci']
|
|
pub size_ci: c_int,
|
|
|
|
|
|
/// number of nested C calls
|
|
pub n_c_calls: c_ushort,
|
|
/// nested C calls when resuming coroutine
|
|
pub base_c_calls: c_ushort,
|
|
|
|
/// when table operations or `INDEX`/`NEWINDEX` is invoked from Luau, what is the expected slot for lookup?
|
|
pub cached_slot: c_int,
|
|
|
|
/// table of globals
|
|
pub globals: *mut Table,
|
|
/// list of open upvalues in this stack
|
|
pub open_upval: *mut UpVal,
|
|
pub gc_list: *mut GCObject,
|
|
|
|
/// when invoked from Luau using `NAMECALL`, what method do we need to invoke?
|
|
pub namecall: *mut TString,
|
|
|
|
pub userdata: *mut c_void,
|
|
|
|
_marker: core::marker::PhantomData<(*mut u8, core::marker::PhantomPinned)>,
|
|
}
|