Refactor Luau runtime
This commit is contained in:
parent
3e9bb2986b
commit
3cd41fbb08
345
runtime/luau.lua
345
runtime/luau.lua
@ -1,188 +1,227 @@
|
|||||||
local div = {}
|
local module = {}
|
||||||
|
|
||||||
local le = {}
|
|
||||||
local lt = {}
|
|
||||||
local ge = {}
|
|
||||||
local gt = {}
|
|
||||||
|
|
||||||
local band = {}
|
|
||||||
local bor = {}
|
|
||||||
local bxor = {}
|
|
||||||
local bnot = {}
|
|
||||||
|
|
||||||
local shl = {}
|
|
||||||
local shr = {}
|
|
||||||
|
|
||||||
local extend = {}
|
|
||||||
local wrap = {}
|
|
||||||
|
|
||||||
local load = {}
|
|
||||||
local store = {}
|
|
||||||
|
|
||||||
-- Helper functions
|
|
||||||
local function no_op(x) return x end
|
local function no_op(x) return x end
|
||||||
|
|
||||||
local function unsign_i32(x)
|
do
|
||||||
if x < 0 then x = x + 0x100000000 end
|
local div = {}
|
||||||
|
|
||||||
return x
|
module.div = div
|
||||||
end
|
|
||||||
|
|
||||||
local function unsign_i64(x)
|
function div.i32(lhs, rhs)
|
||||||
if x < 0 then x = x + 0x10000000000000000 end
|
if rhs == 0 then error('division by zero') end
|
||||||
|
|
||||||
return x
|
return math.floor(lhs / rhs)
|
||||||
end
|
|
||||||
|
|
||||||
local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 end
|
|
||||||
|
|
||||||
local function merge_u64(hi, lo) return hi * 0x100000000 + lo end
|
|
||||||
|
|
||||||
local function black_mask_byte(value, offset)
|
|
||||||
local mask = bit32.lshift(0xFF, offset * 8)
|
|
||||||
|
|
||||||
return bit32.band(value, bit32.bnot(mask))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function load_byte(memory, addr)
|
|
||||||
local offset = addr % 4
|
|
||||||
local value = memory.data[(addr - offset) / 4]
|
|
||||||
|
|
||||||
return bit.band(bit.rshift(value, offset * 8), 0xFF)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function store_byte(memory, addr, value)
|
|
||||||
local offset = addr % 4
|
|
||||||
local adjust = (addr - offset) / 4
|
|
||||||
local lhs = bit32.lshift(value, offset * 8)
|
|
||||||
local rhs = black_mask_byte(memory.data[adjust] or 0, offset)
|
|
||||||
|
|
||||||
memory.data[adjust] = bit32.bor(lhs, rhs)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Runtime functions
|
|
||||||
local function grow_page_num(memory, num)
|
|
||||||
local old = memory.min
|
|
||||||
local new = old + num
|
|
||||||
|
|
||||||
if memory.max and new > memory.max then
|
|
||||||
return -1
|
|
||||||
else
|
|
||||||
memory.min = new
|
|
||||||
|
|
||||||
return old
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function div.i32(lhs, rhs)
|
do
|
||||||
if rhs == 0 then error('division by zero') end
|
local le = {}
|
||||||
|
local lt = {}
|
||||||
|
local ge = {}
|
||||||
|
local gt = {}
|
||||||
|
|
||||||
return math.floor(lhs / rhs)
|
module.le = le
|
||||||
|
module.lt = lt
|
||||||
|
module.ge = ge
|
||||||
|
module.gt = gt
|
||||||
|
|
||||||
|
local function unsign_i32(x)
|
||||||
|
if x < 0 then x = x + 0x100000000 end
|
||||||
|
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
|
||||||
|
local function unsign_i64(x)
|
||||||
|
if x < 0 then x = x + 0x10000000000000000 end
|
||||||
|
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
|
||||||
|
function ge.u32(lhs, rhs) return unsign_i32(lhs) >= unsign_i32(rhs) and 1 or 0 end
|
||||||
|
function ge.u64(lhs, rhs) return unsign_i64(lhs) >= unsign_i64(rhs) and 1 or 0 end
|
||||||
|
function gt.u32(lhs, rhs) return unsign_i32(lhs) > unsign_i32(rhs) and 1 or 0 end
|
||||||
|
function gt.u64(lhs, rhs) return unsign_i64(lhs) > unsign_i64(rhs) and 1 or 0 end
|
||||||
|
function le.u32(lhs, rhs) return unsign_i32(lhs) <= unsign_i32(rhs) and 1 or 0 end
|
||||||
|
function le.u64(lhs, rhs) return unsign_i64(lhs) <= unsign_i64(rhs) and 1 or 0 end
|
||||||
|
function lt.u32(lhs, rhs) return unsign_i32(lhs) < unsign_i32(rhs) and 1 or 0 end
|
||||||
|
function lt.u64(lhs, rhs) return unsign_i64(lhs) < unsign_i64(rhs) and 1 or 0 end
|
||||||
end
|
end
|
||||||
|
|
||||||
function le.u32(lhs, rhs) return unsign_i32(lhs) <= unsign_i32(rhs) and 1 or 0 end
|
do
|
||||||
|
local band = {}
|
||||||
|
local bor = {}
|
||||||
|
local bxor = {}
|
||||||
|
local bnot = {}
|
||||||
|
|
||||||
function lt.u32(lhs, rhs) return unsign_i32(lhs) < unsign_i32(rhs) and 1 or 0 end
|
module.band = band
|
||||||
|
module.bor = bor
|
||||||
|
module.bxor = bxor
|
||||||
|
module.bnot = bnot
|
||||||
|
|
||||||
function ge.u32(lhs, rhs) return unsign_i32(lhs) >= unsign_i32(rhs) and 1 or 0 end
|
band.i32 = bit32.band
|
||||||
|
band.i64 = bit32.band
|
||||||
|
bnot.i32 = bit32.bnot
|
||||||
|
bnot.i64 = bit32.bnot
|
||||||
|
bor.i32 = bit32.bor
|
||||||
|
bor.i64 = bit32.bor
|
||||||
|
bxor.i32 = bit32.bxor
|
||||||
|
bxor.i64 = bit32.bxor
|
||||||
|
end
|
||||||
|
|
||||||
function gt.u32(lhs, rhs) return unsign_i32(lhs) > unsign_i32(rhs) and 1 or 0 end
|
do
|
||||||
|
local shl = {}
|
||||||
|
local shr = {}
|
||||||
|
|
||||||
function le.u64(lhs, rhs) return unsign_i64(lhs) <= unsign_i64(rhs) and 1 or 0 end
|
module.shl = shl
|
||||||
|
module.shr = shr
|
||||||
|
|
||||||
function lt.u64(lhs, rhs) return unsign_i64(lhs) < unsign_i64(rhs) and 1 or 0 end
|
shl.i32 = bit32.lshift
|
||||||
|
shl.i64 = bit32.lshift
|
||||||
|
shl.u32 = bit32.lshift
|
||||||
|
shl.u64 = bit32.lshift
|
||||||
|
shr.i32 = bit32.rshift
|
||||||
|
shr.i64 = bit32.rshift
|
||||||
|
shr.u32 = bit32.rshift
|
||||||
|
shr.u64 = bit32.rshift
|
||||||
|
end
|
||||||
|
|
||||||
function ge.u64(lhs, rhs) return unsign_i64(lhs) >= unsign_i64(rhs) and 1 or 0 end
|
do
|
||||||
|
local extend = {}
|
||||||
|
local wrap = {}
|
||||||
|
|
||||||
function gt.u64(lhs, rhs) return unsign_i64(lhs) > unsign_i64(rhs) and 1 or 0 end
|
module.extend = extend
|
||||||
|
module.wrap = wrap
|
||||||
|
|
||||||
band.i32 = bit32.band
|
extend.i32_u64 = no_op
|
||||||
bor.i32 = bit32.bor
|
|
||||||
bxor.i32 = bit32.bxor
|
|
||||||
bnot.i32 = bit32.bnot
|
|
||||||
band.i64 = bit32.band
|
|
||||||
bor.i64 = bit32.bor
|
|
||||||
bxor.i64 = bit32.bxor
|
|
||||||
bnot.i64 = bit32.bnot
|
|
||||||
|
|
||||||
shl.u32 = bit32.lshift
|
function wrap.i64_i32(i) return i % 2 ^ 32 end
|
||||||
shr.u32 = bit32.rshift
|
end
|
||||||
shl.i32 = bit32.lshift
|
|
||||||
shr.i32 = bit32.rshift
|
|
||||||
shl.u64 = bit32.lshift
|
|
||||||
shr.u64 = bit32.rshift
|
|
||||||
shl.i64 = bit32.lshift
|
|
||||||
shr.i64 = bit32.rshift
|
|
||||||
|
|
||||||
extend.i32_u64 = no_op
|
do
|
||||||
|
local load = {}
|
||||||
|
local store = {}
|
||||||
|
|
||||||
function wrap.i64_i32(i) return i % 2 ^ 32 end
|
module.load = load
|
||||||
|
module.store = store
|
||||||
|
|
||||||
function load.i32(memory, addr)
|
local function rip_u64(x) return math.floor(x / 0x100000000), x % 0x100000000 end
|
||||||
if addr % 4 == 0 then
|
|
||||||
-- aligned read
|
|
||||||
return memory.data[addr / 4] or 0
|
|
||||||
else
|
|
||||||
-- unaligned read
|
|
||||||
local b1 = load_byte(memory, addr)
|
|
||||||
local b2 = bit32.lshift(load_byte(memory, addr + 1), 8)
|
|
||||||
local b3 = bit32.lshift(load_byte(memory, addr + 2), 16)
|
|
||||||
local b4 = bit32.lshift(load_byte(memory, addr + 3), 24)
|
|
||||||
|
|
||||||
return bit32.bor(b1, b2, b3, b4)
|
local function merge_u64(hi, lo) return hi * 0x100000000 + lo end
|
||||||
|
|
||||||
|
local function black_mask_byte(value, offset)
|
||||||
|
local mask = bit32.lshift(0xFF, offset * 8)
|
||||||
|
|
||||||
|
return bit32.band(value, bit32.bnot(mask))
|
||||||
|
end
|
||||||
|
|
||||||
|
local function load_byte(memory, addr)
|
||||||
|
local offset = addr % 4
|
||||||
|
local value = memory.data[(addr - offset) / 4]
|
||||||
|
|
||||||
|
return bit.band(bit.rshift(value, offset * 8), 0xFF)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function store_byte(memory, addr, value)
|
||||||
|
local offset = addr % 4
|
||||||
|
local adjust = (addr - offset) / 4
|
||||||
|
local lhs = bit32.lshift(bit32.band(value, 0xFF), offset * 8)
|
||||||
|
local rhs = black_mask_byte(memory.data[adjust] or 0, offset)
|
||||||
|
|
||||||
|
memory.data[adjust] = bit32.bor(lhs, rhs)
|
||||||
|
end
|
||||||
|
|
||||||
|
load.i32_u8 = load_byte
|
||||||
|
|
||||||
|
function load.i32(memory, addr)
|
||||||
|
if addr % 4 == 0 then
|
||||||
|
-- aligned read
|
||||||
|
return memory.data[addr / 4] or 0
|
||||||
|
else
|
||||||
|
-- unaligned read
|
||||||
|
local b1 = load_byte(memory, addr)
|
||||||
|
local b2 = bit32.lshift(load_byte(memory, addr + 1), 8)
|
||||||
|
local b3 = bit32.lshift(load_byte(memory, addr + 2), 16)
|
||||||
|
local b4 = bit32.lshift(load_byte(memory, addr + 3), 24)
|
||||||
|
|
||||||
|
return bit32.bor(b1, b2, b3, b4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function load.i64(memory, addr)
|
||||||
|
local hi = load.i32(memory, addr + 4)
|
||||||
|
local lo = load.i32(memory, addr)
|
||||||
|
|
||||||
|
return merge_u64(hi, lo)
|
||||||
|
end
|
||||||
|
|
||||||
|
store.i32_n8 = store_byte
|
||||||
|
|
||||||
|
function store.i32(memory, addr, value)
|
||||||
|
if addr % 4 == 0 then
|
||||||
|
-- aligned write
|
||||||
|
memory.data[addr / 4] = value
|
||||||
|
else
|
||||||
|
-- unaligned write
|
||||||
|
store_byte(memory, addr, value)
|
||||||
|
store_byte(memory, addr + 1, bit32.rshift(value, 8))
|
||||||
|
store_byte(memory, addr + 2, bit32.rshift(value, 16))
|
||||||
|
store_byte(memory, addr + 3, bit32.rshift(value, 24))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function store.i64(memory, addr, value)
|
||||||
|
local hi, lo = rip_u64(value)
|
||||||
|
|
||||||
|
store.i32(memory, addr, lo)
|
||||||
|
store.i32(memory, addr + 4, hi)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function load.i32_u8(memory, addr)
|
do
|
||||||
local value = load.i32(memory, addr)
|
local memory = {}
|
||||||
|
|
||||||
return bit32.band(value, 0xFF)
|
module.memory = memory
|
||||||
end
|
|
||||||
|
|
||||||
function load.i64(memory, addr)
|
function memory.new(min, max) return {min = min, max = max, data = {}} end
|
||||||
local hi = load.i32(memory, addr + 4)
|
|
||||||
local lo = load.i32(memory, addr)
|
|
||||||
|
|
||||||
return merge_u64(hi, lo)
|
function memory.init(memory, offset, data)
|
||||||
end
|
local store_i8 = module.memory.store.i32_n8
|
||||||
|
local store_i32 = module.memory.store.i32
|
||||||
|
|
||||||
function store.i32(memory, addr, value)
|
local len = #data
|
||||||
if addr % 4 == 0 then
|
local rem = len % 4
|
||||||
-- aligned write
|
|
||||||
memory.data[addr / 4] = value
|
if len >= 4 then
|
||||||
else
|
for i = 1, len, 4 do
|
||||||
-- unaligned write
|
local v = string.unpack('<I4', data, i)
|
||||||
store_byte(memory, addr, value)
|
|
||||||
store_byte(memory, addr + 1, bit32.rshift(value, 8))
|
store_i32(memory, offset + i - 1, v)
|
||||||
store_byte(memory, addr + 2, bit32.rshift(value, 16))
|
end
|
||||||
store_byte(memory, addr + 3, bit32.rshift(value, 24))
|
end
|
||||||
|
|
||||||
|
if rem ~= 0 then
|
||||||
|
for i = len - rem + 1, len do
|
||||||
|
local v = string.byte(data, i)
|
||||||
|
|
||||||
|
store_i8(memory, offset + i - 1, v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function memory.size(memory) return memory.min end
|
||||||
|
|
||||||
|
function memory.grow(memory, num)
|
||||||
|
local old = memory.min
|
||||||
|
local new = old + num
|
||||||
|
|
||||||
|
if memory.max and new > memory.max then
|
||||||
|
return -1
|
||||||
|
else
|
||||||
|
memory.min = new
|
||||||
|
|
||||||
|
return old
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function store.i32_n8(memory, addr, value) store_byte(memory, addr, bit32.band(value, 0xFF)) end
|
return module
|
||||||
|
|
||||||
function store.i64(memory, addr, value)
|
|
||||||
local hi, lo = rip_u64(value)
|
|
||||||
|
|
||||||
store.i32(memory, addr, lo)
|
|
||||||
store.i32(memory, addr + 4, hi)
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
grow_page_num = grow_page_num,
|
|
||||||
div = div,
|
|
||||||
le = le,
|
|
||||||
lt = lt,
|
|
||||||
ge = ge,
|
|
||||||
gt = gt,
|
|
||||||
band = band,
|
|
||||||
bor = bor,
|
|
||||||
bxor = bxor,
|
|
||||||
bnot = bnot,
|
|
||||||
shl = shl,
|
|
||||||
shr = shr,
|
|
||||||
extend = extend,
|
|
||||||
wrap = wrap,
|
|
||||||
load = load,
|
|
||||||
store = store,
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user