diff --git a/codegen/luau/runtime/runtime.lua b/codegen/luau/runtime/runtime.lua index dd2c993..8b4691b 100644 --- a/codegen/luau/runtime/runtime.lua +++ b/codegen/luau/runtime/runtime.lua @@ -2,7 +2,6 @@ local module = {} local to_u32 = bit32.band -local bit_or = bit32.bor local bit_and = bit32.band local bit_lshift = bit32.lshift local bit_rshift = bit32.rshift @@ -139,14 +138,18 @@ do end end - function copysign.f32(lhs, rhs) - local packed = string_pack("= 0x80 then - return -math_abs(lhs) + local buffer_write_f64 = buffer.writef64 + local buffer_read_i8 = buffer.readi8 + + function copysign.f32(lhs, rhs) + buffer_write_f64(CP_INSTANCE, 0, rhs) + + if buffer_read_i8(CP_INSTANCE, 7) >= 0 then + return (math_abs(lhs)) else - return math_abs(lhs) + return -math_abs(lhs) end end @@ -154,10 +157,10 @@ do local result = math_round(num) if (math_abs(num) + 0.5) % 2 == 1 then - result = result - math_sign(result) + return result - math_sign(result) + else + return result end - - return result end neg.f64 = neg.f32 @@ -376,9 +379,6 @@ do local math_floor = math.floor local math_clamp = math.clamp - local string_pack = string.pack - local string_unpack = string.unpack - local NUM_ZERO = Integer.ZERO local NUM_MIN_I64 = num_from_u32(0, 0x80000000) local NUM_MAX_I64 = num_from_u32(0xFFFFFFFF, 0x7FFFFFFF) @@ -576,30 +576,44 @@ do promote.f64_f32 = no_op - function reinterpret.i32_f32(num) - local packed = string_pack("f", num) + local RE_INSTANCE = buffer.create(8) - return string_unpack("I4", packed) + local buffer_read_f32 = buffer.readf32 + local buffer_read_f64 = buffer.readf64 + local buffer_read_u32 = buffer.readu32 + + local buffer_write_f32 = buffer.writef32 + local buffer_write_f64 = buffer.writef64 + local buffer_write_u32 = buffer.writeu32 + + function reinterpret.i32_f32(num) + buffer_write_f32(RE_INSTANCE, 0, num) + + return buffer_read_u32(RE_INSTANCE, 0) end function reinterpret.i64_f64(num) - local packed = string_pack("d", num) - local data_1, data_2 = string_unpack("I4I4", packed) + buffer_write_f64(RE_INSTANCE, 0, num) + + local data_1 = buffer_read_u32(RE_INSTANCE, 0) + local data_2 = buffer_read_u32(RE_INSTANCE, 4) return num_from_u32(data_1, data_2) end function reinterpret.f32_i32(num) - local packed = string_pack("I4", num) + buffer_write_u32(RE_INSTANCE, 0, num) - return string_unpack("f", packed) + return buffer_read_f32(RE_INSTANCE, 0) end function reinterpret.f64_i64(num) local data_1, data_2 = num_into_u32(num) - local packed = string_pack("I4I4", data_1, data_2) - return string_unpack("d", packed) + buffer_write_u32(RE_INSTANCE, 0, data_1) + buffer_write_u32(RE_INSTANCE, 4, data_2) + + return buffer_read_f64(RE_INSTANCE, 0) end module.wrap = wrap @@ -617,357 +631,214 @@ do local store = {} local allocator = {} - local bit_extract = bit32.extract - local bit_replace = bit32.replace + local string_sub = string.sub - local math_floor = math.floor + local buffer_create = buffer.create + local buffer_to_string = buffer.tostring + local buffer_from_string = buffer.fromstring - local string_byte = string.byte - local string_char = string.char - local string_unpack = string.unpack + local buffer_len = buffer.len + local buffer_copy = buffer.copy + local buffer_fill = buffer.fill - local reinterpret_f32_i32 = module.reinterpret.f32_i32 - local reinterpret_f64_i64 = module.reinterpret.f64_i64 - local reinterpret_i32_f32 = module.reinterpret.i32_f32 - local reinterpret_i64_f64 = module.reinterpret.i64_f64 + local buffer_read_i8 = buffer.readi8 + local buffer_read_u8 = buffer.readu8 + local buffer_read_i16 = buffer.readi16 + local buffer_read_u16 = buffer.readu16 + local buffer_read_i32 = buffer.readi32 + local buffer_read_u32 = buffer.readu32 + local buffer_read_f32 = buffer.readf32 + local buffer_read_f64 = buffer.readf64 - local function load_byte(data, addr) - local value = data[math_floor(addr / 4)] or 0 - - return bit_extract(value, addr % 4 * 8, 8) - end - - local function store_byte(data, addr, value) - local adjust = math_floor(addr / 4) - - data[adjust] = bit_replace(data[adjust] or 0, value, addr % 4 * 8, 8) - end + local buffer_write_u8 = buffer.writeu8 + local buffer_write_u16 = buffer.writeu16 + local buffer_write_u32 = buffer.writeu32 + local buffer_write_f32 = buffer.writef32 + local buffer_write_f64 = buffer.writef64 function load.i32_i8(memory, addr) - local temp = load_byte(memory.data, addr) + local value = buffer_read_i8(memory.data, addr) - if temp >= 0x80 then - return to_u32(temp - 0x100) + if value >= 0 then + return value else - return temp + return value + 0x100000000 end end function load.i32_u8(memory, addr) - return load_byte(memory.data, addr) + return buffer_read_u8(memory.data, addr) end function load.i32_i16(memory, addr) - local data = memory.data - local temp + local value = buffer_read_i16(memory.data, addr) - if addr % 4 == 0 then - temp = bit_and(data[addr / 4] or 0, 0xFFFF) + if value >= 0 then + return value else - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - - temp = bit_or(b1, b2) - end - - if temp >= 0x8000 then - return to_u32(temp - 0x10000) - else - return temp + return value + 0x100000000 end end function load.i32_u16(memory, addr) - local data = memory.data - - if addr % 4 == 0 then - return bit_and(data[addr / 4] or 0, 0xFFFF) - else - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - - return bit_or(b1, b2) - end + return buffer_read_u16(memory.data, addr) end function load.i32(memory, addr) - local data = memory.data - - if addr % 4 == 0 then - -- aligned read - return data[addr / 4] or 0 - else - -- unaligned read - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - local b3 = bit_lshift(load_byte(data, addr + 2), 16) - local b4 = bit_lshift(load_byte(data, addr + 3), 24) - - return bit_or(b1, b2, b3, b4) - end + return buffer_read_u32(memory.data, addr) end function load.i64_i8(memory, addr) - local data_1 = load_byte(memory.data, addr) - local data_2 + local value = buffer_read_i8(memory.data, addr) - if data_1 >= 0x80 then - data_1 = to_u32(data_1 - 0x100) - data_2 = 0xFFFFFFFF + if value >= 0 then + return num_from_u32(value, 0) else - data_2 = 0 + return num_from_u32(value + 0x100000000, 0xFFFFFFFF) end - - return num_from_u32(data_1, data_2) end function load.i64_u8(memory, addr) - local temp = load_byte(memory.data, addr) - - return num_from_u32(temp, 0) + return num_from_u32(buffer_read_u8(memory.data, addr), 0) end function load.i64_i16(memory, addr) - local data = memory.data - local data_1, data_2 + local value = buffer_read_i16(memory.data, addr) - if addr % 4 == 0 then - data_1 = bit_and(data[addr / 4] or 0, 0xFFFF) + if value >= 0 then + return num_from_u32(value, 0) else - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - - data_1 = bit_or(b1, b2) + return num_from_u32(value + 0x100000000, 0xFFFFFFFF) end - - if data_1 >= 0x8000 then - data_1 = to_u32(data_1 - 0x10000) - data_2 = 0xFFFFFFFF - else - data_2 = 0 - end - - return num_from_u32(data_1, data_2) end function load.i64_u16(memory, addr) - local data = memory.data - local temp - - if addr % 4 == 0 then - temp = bit_and(data[addr / 4] or 0, 0xFFFF) - else - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - - temp = bit_or(b1, b2) - end - - return num_from_u32(temp, 0) + return num_from_u32(buffer_read_u16(memory.data, addr), 0) end function load.i64_i32(memory, addr) - local data = memory.data - local data_1, data_2 + local value = buffer_read_i32(memory.data, addr) - if addr % 4 == 0 then - data_1 = data[addr / 4] or 0 + if value >= 0 then + return num_from_u32(value, 0) else - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - local b3 = bit_lshift(load_byte(data, addr + 2), 16) - local b4 = bit_lshift(load_byte(data, addr + 3), 24) - - data_1 = bit_or(b1, b2, b3, b4) + return num_from_u32(value + 0x100000000, 0xFFFFFFFF) end - - if data_1 >= 0x80000000 then - data_1 = to_u32(data_1 - 0x100000000) - data_2 = 0xFFFFFFFF - else - data_2 = 0 - end - - return num_from_u32(data_1, data_2) end function load.i64_u32(memory, addr) - local data = memory.data - local temp - - if addr % 4 == 0 then - temp = data[addr / 4] or 0 - else - local b1 = load_byte(data, addr) - local b2 = bit_lshift(load_byte(data, addr + 1), 8) - local b3 = bit_lshift(load_byte(data, addr + 2), 16) - local b4 = bit_lshift(load_byte(data, addr + 3), 24) - - temp = bit_or(b1, b2, b3, b4) - end - - return num_from_u32(temp, 0) + return num_from_u32(buffer_read_u32(memory.data, addr), 0) end - local load_i32 = load.i32 - function load.i64(memory, addr) - local data_1 = load_i32(memory, addr) - local data_2 = load_i32(memory, addr + 4) + local data = memory.data + local value_1 = buffer_read_u32(data, addr) + local value_2 = buffer_read_u32(data, addr + 4) - return num_from_u32(data_1, data_2) + return num_from_u32(value_1, value_2) end - local load_i64 = load.i64 - function load.f32(memory, addr) - local raw = load_i32(memory, addr) - - return reinterpret_f32_i32(raw) + return buffer_read_f32(memory.data, addr) end function load.f64(memory, addr) - local raw = load_i64(memory, addr) - - return reinterpret_f64_i64(raw) + return buffer_read_f64(memory.data, addr) end function load.string(memory, addr, len) - local buffer = table.create(len) - local data = memory.data + local temp = buffer_create(len) - for i = 1, len do - local raw = load_byte(data, addr + i - 1) + buffer_copy(temp, 0, memory.data, addr, len) - buffer[i] = string_char(raw) - end - - return table.concat(buffer) + return buffer_to_string(temp) end function store.i32_n8(memory, addr, value) - store_byte(memory.data, addr, value) + buffer_write_u8(memory.data, addr, value) end function store.i32_n16(memory, addr, value) - store_byte(memory.data, addr, value) - store_byte(memory.data, addr + 1, bit_rshift(value, 8)) + buffer_write_u16(memory.data, addr, value) end function store.i32(memory, addr, value) - local data = memory.data - - if addr % 4 == 0 then - -- aligned write - data[addr / 4] = value - else - -- unaligned write - store_byte(data, addr, value) - store_byte(data, addr + 1, bit_rshift(value, 8)) - store_byte(data, addr + 2, bit_rshift(value, 16)) - store_byte(data, addr + 3, bit_rshift(value, 24)) - end + buffer_write_u32(memory.data, addr, value) end - local store_i32 = store.i32 - local store_i32_n8 = store.i32_n8 - local store_i32_n16 = store.i32_n16 - function store.i64_n8(memory, addr, value) - local data_1, _ = num_into_u32(value) + local value_1, _ = num_into_u32(value) - store_i32_n8(memory, addr, data_1) + buffer_write_u8(memory.data, addr, value_1) end function store.i64_n16(memory, addr, value) - local data_1, _ = num_into_u32(value) + local value_1, _ = num_into_u32(value) - store_i32_n16(memory, addr, data_1) + buffer_write_u16(memory.data, addr, value_1) end function store.i64_n32(memory, addr, value) - local data_1, _ = num_into_u32(value) + local value_1, _ = num_into_u32(value) - store_i32(memory, addr, data_1) + buffer_write_u32(memory.data, addr, value_1) end function store.i64(memory, addr, value) - local data_1, data_2 = num_into_u32(value) + local data = memory.data + local value_1, value_2 = num_into_u32(value) - store_i32(memory, addr, data_1) - store_i32(memory, addr + 4, data_2) + buffer_write_u32(data, addr, value_1) + buffer_write_u32(data, addr + 4, value_2) end - local store_i64 = store.i64 - function store.f32(memory, addr, value) - store_i32(memory, addr, reinterpret_i32_f32(value)) + buffer_write_f32(memory.data, addr, value) end function store.f64(memory, addr, value) - store_i64(memory, addr, reinterpret_i64_f64(value)) + buffer_write_f64(memory.data, addr, value) end function store.string(memory, addr, data, len) - len = if len then len else #data + local content = if not len or len == #data then data else string_sub(data, 1, len) + local temp = buffer_from_string(content) - local rem = len % 4 - - for i = 1, len - rem, 4 do - local v = string_unpack(" memory.max then - return to_u32(-1) - else - memory.min = new + if new <= memory.max then + local reallocated = buffer_create(new * WASM_PAGE_SIZE) + + buffer_copy(reallocated, 0, memory.data) + + memory.data = reallocated return old + else + return 0xFFFFFFFF end end @@ -977,4 +848,3 @@ do end return module - diff --git a/codegen/luau/src/backend/expression.rs b/codegen/luau/src/backend/expression.rs index 804f199..320486f 100644 --- a/codegen/luau/src/backend/expression.rs +++ b/codegen/luau/src/backend/expression.rs @@ -85,7 +85,7 @@ impl Driver for LoadAt { impl Driver for MemorySize { fn write(&self, _mng: &mut Manager, w: &mut dyn Write) -> Result<()> { - write!(w, "memory_at_{}.min", self.memory()) + write!(w, "rt.allocator.size(memory_at_{})", self.memory()) } } diff --git a/dev-test/tests/luau_assert.lua b/dev-test/tests/luau_assert.lua index ed70e7c..f2f762f 100644 --- a/dev-test/tests/luau_assert.lua +++ b/dev-test/tests/luau_assert.lua @@ -2,7 +2,7 @@ do local WASM_PAGE_SIZE = 65536 local function is_valid_address(memory, addr, size) - return addr >= 0 and addr + size <= memory.min * WASM_PAGE_SIZE + return addr >= 0 and addr + size <= rt.allocator.size(memory) * WASM_PAGE_SIZE end local function load_checked(name, size)