mirror of
https://github.com/luau-lang/luau.git
synced 2024-12-13 13:30:40 +00:00
7105c81579
# What's changed? * Fixed a bug in type cloning by maintaining persistent types. * We now parse imprecise integer literals to report the imprecision as a warning to developers. * Add a compiler flag to specify the name of the statistics output file. ### New type solver * Renamed `ConstraintGraphBuilder` to `ConstraintGenerator` * LValues now take into account the type being assigned during constraint generation. * Normalization performance has been improved by 33% by replacing the an internal usage of `std::unordered_set` with `DenseHashMap`. * Normalization now has a helper to identify types that are equivalent to `unknown`, which is being used to fix some bugs in subtyping. * Uses of the old unifier in the new type solver have been eliminated. * Improved error explanations for subtyping errors in `TypeChecker2`. ### Native code generation * Expanded some of the statistics recorded during compilation to include the number of instructions and blocks. * Introduce instruction and block count limiters for controlling what bytecode is translated into native code. * Implement code generation for byteswap instruction. ### Internal Contributors Co-authored-by: Aaron Weiss <aaronweiss@roblox.com> Co-authored-by: Alexander McCord <amccord@roblox.com> Co-authored-by: Andy Friesen <afriesen@roblox.com> Co-authored-by: Aviral Goel <agoel@roblox.com> Co-authored-by: Lily Brown <lbrown@roblox.com>
180 lines
6.3 KiB
Lua
180 lines
6.3 KiB
Lua
-- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
|
|
-- This file is based on Lua 5.x tests -- https://github.com/lua/lua/tree/master/testes
|
|
print("testing bitwise operations")
|
|
|
|
assert(bit32.band() == bit32.bnot(0))
|
|
assert(bit32.btest() == true)
|
|
assert(bit32.bor() == 0)
|
|
assert(bit32.bxor() == 0)
|
|
|
|
assert(bit32.band() == bit32.band(0xffffffff))
|
|
assert(bit32.band(1,2) == 0)
|
|
|
|
|
|
-- out-of-range numbers
|
|
assert(bit32.band(-1) == 0xffffffff)
|
|
assert(bit32.band(2^33 - 1) == 0xffffffff)
|
|
assert(bit32.band(-2^33 - 1) == 0xffffffff)
|
|
assert(bit32.band(2^33 + 1) == 1)
|
|
assert(bit32.band(-2^33 + 1) == 1)
|
|
assert(bit32.band(-2^40) == 0)
|
|
assert(bit32.band(2^40) == 0)
|
|
assert(bit32.band(-2^40 - 2) == 0xfffffffe)
|
|
assert(bit32.band(2^40 - 4) == 0xfffffffc)
|
|
|
|
assert(bit32.lrotate(0, -1) == 0)
|
|
assert(bit32.lrotate(0, 7) == 0)
|
|
assert(bit32.lrotate(0x12345678, 4) == 0x23456781)
|
|
assert(bit32.rrotate(0x12345678, -4) == 0x23456781)
|
|
assert(bit32.lrotate(0x12345678, -8) == 0x78123456)
|
|
assert(bit32.rrotate(0x12345678, 8) == 0x78123456)
|
|
assert(bit32.lrotate(0xaaaaaaaa, 2) == 0xaaaaaaaa)
|
|
assert(bit32.lrotate(0xaaaaaaaa, -2) == 0xaaaaaaaa)
|
|
for i = -50, 50 do
|
|
assert(bit32.lrotate(0x89abcdef, i) == bit32.lrotate(0x89abcdef, i%32))
|
|
end
|
|
|
|
assert(bit32.lshift(0x12345678, 4) == 0x23456780)
|
|
assert(bit32.lshift(0x12345678, 8) == 0x34567800)
|
|
assert(bit32.lshift(0x12345678, -4) == 0x01234567)
|
|
assert(bit32.lshift(0x12345678, -8) == 0x00123456)
|
|
assert(bit32.lshift(0x12345678, 32) == 0)
|
|
assert(bit32.lshift(0x12345678, -32) == 0)
|
|
assert(bit32.rshift(0x12345678, 4) == 0x01234567)
|
|
assert(bit32.rshift(0x12345678, 8) == 0x00123456)
|
|
assert(bit32.rshift(0x12345678, 32) == 0)
|
|
assert(bit32.rshift(0x12345678, -32) == 0)
|
|
assert(bit32.arshift(0x12345678, 0) == 0x12345678)
|
|
assert(bit32.arshift(0x12345678, 1) == 0x12345678 / 2)
|
|
assert(bit32.arshift(0x12345678, -1) == 0x12345678 * 2)
|
|
assert(bit32.arshift(-1, 1) == 0xffffffff)
|
|
assert(bit32.arshift(-1, 24) == 0xffffffff)
|
|
assert(bit32.arshift(-1, 32) == 0xffffffff)
|
|
assert(bit32.arshift(-1, -1) == (-1 * 2) % 2^32)
|
|
|
|
print("+")
|
|
-- some special cases
|
|
local c = {0, 1, 2, 3, 10, 0x80000000, 0xaaaaaaaa, 0x55555555,
|
|
0xffffffff, 0x7fffffff}
|
|
|
|
for _, b in pairs(c) do
|
|
assert(bit32.band(b) == b)
|
|
assert(bit32.band(b, b) == b)
|
|
assert(bit32.btest(b, b) == (b ~= 0))
|
|
assert(bit32.band(b, b, b) == b)
|
|
assert(bit32.btest(b, b, b) == (b ~= 0))
|
|
assert(bit32.band(b, bit32.bnot(b)) == 0)
|
|
assert(bit32.bor(b, bit32.bnot(b)) == bit32.bnot(0))
|
|
assert(bit32.bor(b) == b)
|
|
assert(bit32.bor(b, b) == b)
|
|
assert(bit32.bor(b, b, b) == b)
|
|
assert(bit32.bxor(b) == b)
|
|
assert(bit32.bxor(b, b) == 0)
|
|
assert(bit32.bxor(b, 0) == b)
|
|
assert(bit32.bxor(b, b, b) == b)
|
|
assert(bit32.bnot(b) ~= b)
|
|
assert(bit32.bnot(bit32.bnot(b)) == b)
|
|
assert(bit32.bnot(b) == 2^32 - 1 - b)
|
|
assert(bit32.lrotate(b, 32) == b)
|
|
assert(bit32.rrotate(b, 32) == b)
|
|
assert(bit32.lshift(bit32.lshift(b, -4), 4) == bit32.band(b, bit32.bnot(0xf)))
|
|
assert(bit32.rshift(bit32.rshift(b, 4), -4) == bit32.band(b, bit32.bnot(0xf)))
|
|
for i = -40, 40 do
|
|
assert(bit32.lshift(b, i) == math.floor((b * 2^i) % 2^32))
|
|
end
|
|
end
|
|
|
|
assert(not pcall(bit32.band, {}))
|
|
assert(not pcall(bit32.bnot, "a"))
|
|
assert(not pcall(bit32.lshift, 45))
|
|
assert(not pcall(bit32.lshift, 45, print))
|
|
assert(not pcall(bit32.rshift, 45, print))
|
|
|
|
print("+")
|
|
|
|
|
|
-- testing extract/replace
|
|
|
|
assert(bit32.extract(0x12345678, 0, 4) == 8)
|
|
assert(bit32.extract(0x12345678, 4, 4) == 7)
|
|
assert(bit32.extract(0xa0001111, 28, 4) == 0xa)
|
|
assert(bit32.extract(0xa0001111, 31, 1) == 1)
|
|
assert(bit32.extract(0x50000111, 31, 1) == 0)
|
|
assert(bit32.extract(0xf2345679, 0, 32) == 0xf2345679)
|
|
assert(bit32.extract(0xa0001111, 0) == 1)
|
|
assert(bit32.extract(0xa0001111, 16) == 0)
|
|
assert(bit32.extract(0xa0001111, 31) == 1)
|
|
assert(bit32.extract(42, 1, 3) == 5)
|
|
|
|
local pos pos = 1
|
|
assert(bit32.extract(42, pos, 3) == 5) -- test bit32.extract builtin instead of bit32.extractk
|
|
|
|
assert(not pcall(bit32.extract, 0, -1))
|
|
assert(not pcall(bit32.extract, 0, 32))
|
|
assert(not pcall(bit32.extract, 0, 0, 33))
|
|
assert(not pcall(bit32.extract, 0, 31, 2))
|
|
|
|
assert(bit32.replace(0x12345678, 5, 28, 4) == 0x52345678)
|
|
assert(bit32.replace(0x12345678, 0x87654321, 0, 32) == 0x87654321)
|
|
assert(bit32.replace(0, 1, 2) == 2^2)
|
|
assert(bit32.replace(0, -1, 4) == 2^4)
|
|
assert(bit32.replace(-1, 0, 31) == 2^31 - 1)
|
|
assert(bit32.replace(-1, 0, 1, 2) == 2^32 - 7)
|
|
|
|
-- testing countlz/countrc
|
|
assert(bit32.countlz(0) == 32)
|
|
assert(bit32.countlz(42) == 26)
|
|
assert(bit32.countlz(0xffffffff) == 0)
|
|
assert(bit32.countlz(0x80000000) == 0)
|
|
assert(bit32.countlz(0x7fffffff) == 1)
|
|
|
|
assert(bit32.countrz(0) == 32)
|
|
assert(bit32.countrz(1) == 0)
|
|
assert(bit32.countrz(42) == 1)
|
|
assert(bit32.countrz(0x80000000) == 31)
|
|
assert(bit32.countrz(0x40000000) == 30)
|
|
assert(bit32.countrz(0x7fffffff) == 0)
|
|
|
|
-- testing byteswap
|
|
assert(bit32.byteswap(0x10203040) == 0x40302010)
|
|
assert(bit32.byteswap(0) == 0)
|
|
assert(bit32.byteswap(-1) == 0xffffffff)
|
|
|
|
-- bit32.bor(n, 0) must clear top bits
|
|
-- we check this obscuring the constant through a global to make sure this gets evaluated fully
|
|
high32 = 0x42_1234_5678
|
|
assert(bit32.bor(high32, 0) == 0x1234_5678)
|
|
|
|
--[[
|
|
This test verifies a fix in luauF_replace() where if the 4th
|
|
parameter was not a number, but the first three are numbers, it will
|
|
cause the Luau math library to crash.
|
|
]]--
|
|
|
|
assert(bit32.replace(-1, 0, 1, "2") == 2^32 - 7)
|
|
|
|
-- many of the tests above go through fastcall path
|
|
-- to make sure the basic implementations are also correct we test some functions with string->number coercions
|
|
assert(bit32.lrotate("0x12345678", 4) == 0x23456781)
|
|
assert(bit32.rrotate("0x12345678", -4) == 0x23456781)
|
|
assert(bit32.arshift("0x12345678", 1) == 0x12345678 / 2)
|
|
assert(bit32.arshift("-1", 32) == 0xffffffff)
|
|
assert(bit32.arshift("-1", 1) == 0xffffffff)
|
|
assert(bit32.bnot("1") == 0xfffffffe)
|
|
assert(bit32.band("1", 3) == 1)
|
|
assert(bit32.band(1, "3") == 1)
|
|
assert(bit32.band(1, 3, "5") == 1)
|
|
assert(bit32.bor("1", 2) == 3)
|
|
assert(bit32.bor(1, "2") == 3)
|
|
assert(bit32.bor(1, 3, "5") == 7)
|
|
assert(bit32.bxor("1", 3) == 2)
|
|
assert(bit32.bxor(1, "3") == 2)
|
|
assert(bit32.bxor(1, 3, "5") == 7)
|
|
assert(bit32.btest(1, "3") == true)
|
|
assert(bit32.btest("1", 3) == true)
|
|
assert(bit32.countlz("42") == 26)
|
|
assert(bit32.countrz("42") == 1)
|
|
assert(bit32.extract("42", 1, 3) == 5)
|
|
assert(bit32.byteswap("0xa1b2c3d4") == 0xd4c3b2a1)
|
|
|
|
return('OK')
|