diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-09 12:33:01 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-07-09 12:33:01 -0300 |
| commit | 7c519dfbd0c68b952f0849e01deaa3750e1f8153 (patch) | |
| tree | dde3ddbba310877db725df37a0d9f2cbe4e2a8f9 /testes/code.lua | |
| parent | f59e6a93c0ad38a27a420e51abf8f13d962446b5 (diff) | |
| download | lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.gz lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.tar.bz2 lua-7c519dfbd0c68b952f0849e01deaa3750e1f8153.zip | |
Added manual and tests for version 5.4-w2
Diffstat (limited to 'testes/code.lua')
| -rw-r--r-- | testes/code.lua | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/testes/code.lua b/testes/code.lua new file mode 100644 index 00000000..e39c62ad --- /dev/null +++ b/testes/code.lua | |||
| @@ -0,0 +1,347 @@ | |||
| 1 | -- $Id: code.lua,v 1.55 2018/03/12 14:19:36 roberto Exp $ | ||
| 2 | -- See Copyright Notice in file all.lua | ||
| 3 | |||
| 4 | if T==nil then | ||
| 5 | (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n') | ||
| 6 | return | ||
| 7 | end | ||
| 8 | print "testing code generation and optimizations" | ||
| 9 | |||
| 10 | |||
| 11 | -- this code gave an error for the code checker | ||
| 12 | do | ||
| 13 | local function f (a) | ||
| 14 | for k,v,w in a do end | ||
| 15 | end | ||
| 16 | end | ||
| 17 | |||
| 18 | |||
| 19 | -- testing reuse in constant table | ||
| 20 | local function checkKlist (func, list) | ||
| 21 | local k = T.listk(func) | ||
| 22 | assert(#k == #list) | ||
| 23 | for i = 1, #k do | ||
| 24 | assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i])) | ||
| 25 | end | ||
| 26 | end | ||
| 27 | |||
| 28 | local function foo () | ||
| 29 | local a | ||
| 30 | a = 3; | ||
| 31 | a = 0; a = 0.0; a = -7 + 7 | ||
| 32 | a = 3.78/4; a = 3.78/4 | ||
| 33 | a = -3.78/4; a = 3.78/4; a = -3.78/4 | ||
| 34 | a = -3.79/4; a = 0.0; a = -0; | ||
| 35 | a = 3; a = 3.0; a = 3; a = 3.0 | ||
| 36 | end | ||
| 37 | |||
| 38 | checkKlist(foo, {3.78/4, -3.78/4, -3.79/4}) | ||
| 39 | |||
| 40 | |||
| 41 | -- testing opcodes | ||
| 42 | |||
| 43 | function check (f, ...) | ||
| 44 | local arg = {...} | ||
| 45 | local c = T.listcode(f) | ||
| 46 | for i=1, #arg do | ||
| 47 | local opcode = string.match(c[i], "%u%w+") | ||
| 48 | -- print(arg[i], opcode) | ||
| 49 | assert(arg[i] == opcode) | ||
| 50 | end | ||
| 51 | assert(c[#arg+2] == undef) | ||
| 52 | end | ||
| 53 | |||
| 54 | |||
| 55 | function checkequal (a, b) | ||
| 56 | a = T.listcode(a) | ||
| 57 | b = T.listcode(b) | ||
| 58 | for i = 1, #a do | ||
| 59 | a[i] = string.gsub(a[i], '%b()', '') -- remove line number | ||
| 60 | b[i] = string.gsub(b[i], '%b()', '') -- remove line number | ||
| 61 | assert(a[i] == b[i]) | ||
| 62 | end | ||
| 63 | end | ||
| 64 | |||
| 65 | |||
| 66 | -- some basic instructions | ||
| 67 | check(function () | ||
| 68 | (function () end){f()} | ||
| 69 | end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN') | ||
| 70 | |||
| 71 | |||
| 72 | -- sequence of LOADNILs | ||
| 73 | check(function () | ||
| 74 | local a,b,c | ||
| 75 | local d; local e; | ||
| 76 | local f,g,h; | ||
| 77 | d = nil; d=nil; b=nil; a=nil; c=nil; | ||
| 78 | end, 'LOADNIL', 'RETURN0') | ||
| 79 | |||
| 80 | check(function () | ||
| 81 | local a,b,c,d = 1,1,1,1 | ||
| 82 | d=nil;c=nil;b=nil;a=nil | ||
| 83 | end, 'LOADI', 'LOADI', 'LOADI', 'LOADI', 'LOADNIL', 'RETURN0') | ||
| 84 | |||
| 85 | do | ||
| 86 | local a,b,c,d = 1,1,1,1 | ||
| 87 | d=nil;c=nil;b=nil;a=nil | ||
| 88 | assert(a == nil and b == nil and c == nil and d == nil) | ||
| 89 | end | ||
| 90 | |||
| 91 | |||
| 92 | -- single return | ||
| 93 | check (function (a,b,c) return a end, 'RETURN1') | ||
| 94 | |||
| 95 | |||
| 96 | -- infinite loops | ||
| 97 | check(function () while true do local a = -1 end end, | ||
| 98 | 'LOADI', 'JMP', 'RETURN0') | ||
| 99 | |||
| 100 | check(function () while 1 do local a = -1 end end, | ||
| 101 | 'LOADI', 'JMP', 'RETURN0') | ||
| 102 | |||
| 103 | check(function () repeat local x = 1 until true end, | ||
| 104 | 'LOADI', 'RETURN0') | ||
| 105 | |||
| 106 | |||
| 107 | -- concat optimization | ||
| 108 | check(function (a,b,c,d) return a..b..c..d end, | ||
| 109 | 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN1') | ||
| 110 | |||
| 111 | -- not | ||
| 112 | check(function () return not not nil end, 'LOADBOOL', 'RETURN1') | ||
| 113 | check(function () return not not false end, 'LOADBOOL', 'RETURN1') | ||
| 114 | check(function () return not not true end, 'LOADBOOL', 'RETURN1') | ||
| 115 | check(function () return not not 1 end, 'LOADBOOL', 'RETURN1') | ||
| 116 | |||
| 117 | -- direct access to locals | ||
| 118 | check(function () | ||
| 119 | local a,b,c,d | ||
| 120 | a = b*a | ||
| 121 | c.x, a[b] = -((a + d/b - a[b]) ^ a.x), b | ||
| 122 | end, | ||
| 123 | 'LOADNIL', | ||
| 124 | 'MUL', | ||
| 125 | 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETFIELD', 'POW', | ||
| 126 | 'UNM', 'SETTABLE', 'SETFIELD', 'RETURN0') | ||
| 127 | |||
| 128 | |||
| 129 | -- direct access to constants | ||
| 130 | check(function () | ||
| 131 | local a,b | ||
| 132 | a.x = 3.2 | ||
| 133 | a.x = b | ||
| 134 | a[b] = 'x' | ||
| 135 | end, | ||
| 136 | 'LOADNIL', 'SETFIELD', 'SETFIELD', 'SETTABLE', 'RETURN0') | ||
| 137 | |||
| 138 | -- "get/set table" with numeric indices | ||
| 139 | check(function (a) | ||
| 140 | a[1] = a[100] | ||
| 141 | a[255] = a[256] | ||
| 142 | a[256] = 5 | ||
| 143 | end, | ||
| 144 | 'GETI', 'SETI', | ||
| 145 | 'LOADI', 'GETTABLE', 'SETI', | ||
| 146 | 'LOADI', 'SETTABLE', 'RETURN0') | ||
| 147 | |||
| 148 | check(function () | ||
| 149 | local a,b | ||
| 150 | a = a - a | ||
| 151 | b = a/a | ||
| 152 | b = 5-4 | ||
| 153 | end, | ||
| 154 | 'LOADNIL', 'SUB', 'DIV', 'LOADI', 'RETURN0') | ||
| 155 | |||
| 156 | check(function () | ||
| 157 | local a,b | ||
| 158 | a[true] = false | ||
| 159 | end, | ||
| 160 | 'LOADNIL', 'LOADBOOL', 'SETTABLE', 'RETURN0') | ||
| 161 | |||
| 162 | |||
| 163 | -- equalities | ||
| 164 | check(function (a) if a == 1 then return 2 end end, | ||
| 165 | 'EQI', 'JMP', 'LOADI', 'RETURN1') | ||
| 166 | |||
| 167 | check(function (a) if -4.0 == a then return 2 end end, | ||
| 168 | 'EQI', 'JMP', 'LOADI', 'RETURN1') | ||
| 169 | |||
| 170 | check(function (a) if a == "hi" then return 2 end end, | ||
| 171 | 'EQK', 'JMP', 'LOADI', 'RETURN1') | ||
| 172 | |||
| 173 | check(function (a) if a == 10000 then return 2 end end, | ||
| 174 | 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large | ||
| 175 | |||
| 176 | check(function (a) if -10000 == a then return 2 end end, | ||
| 177 | 'EQK', 'JMP', 'LOADI', 'RETURN1') -- number too large | ||
| 178 | |||
| 179 | -- comparisons | ||
| 180 | |||
| 181 | check(function (a) if -10 <= a then return 2 end end, | ||
| 182 | 'GEI', 'JMP', 'LOADI', 'RETURN1') | ||
| 183 | |||
| 184 | check(function (a) if 128.0 > a then return 2 end end, | ||
| 185 | 'LTI', 'JMP', 'LOADI', 'RETURN1') | ||
| 186 | |||
| 187 | check(function (a) if -127.0 < a then return 2 end end, | ||
| 188 | 'GTI', 'JMP', 'LOADI', 'RETURN1') | ||
| 189 | |||
| 190 | check(function (a) if 10 < a then return 2 end end, | ||
| 191 | 'GTI', 'JMP', 'LOADI', 'RETURN1') | ||
| 192 | |||
| 193 | check(function (a) if 129 < a then return 2 end end, | ||
| 194 | 'LOADI', 'LT', 'JMP', 'LOADI', 'RETURN1') | ||
| 195 | |||
| 196 | check(function (a) if a >= 23.0 then return 2 end end, | ||
| 197 | 'GEI', 'JMP', 'LOADI', 'RETURN1') | ||
| 198 | |||
| 199 | check(function (a) if a >= 23.1 then return 2 end end, | ||
| 200 | 'LOADK', 'LE', 'JMP', 'LOADI', 'RETURN1') | ||
| 201 | |||
| 202 | check(function (a) if a > 2300.0 then return 2 end end, | ||
| 203 | 'LOADF', 'LT', 'JMP', 'LOADI', 'RETURN1') | ||
| 204 | |||
| 205 | |||
| 206 | -- constant folding | ||
| 207 | local function checkK (func, val) | ||
| 208 | check(func, 'LOADK', 'RETURN1') | ||
| 209 | local k = T.listk(func) | ||
| 210 | assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) | ||
| 211 | assert(func() == val) | ||
| 212 | end | ||
| 213 | |||
| 214 | local function checkI (func, val) | ||
| 215 | check(func, 'LOADI', 'RETURN1') | ||
| 216 | assert(#T.listk(func) == 0) | ||
| 217 | assert(func() == val) | ||
| 218 | end | ||
| 219 | |||
| 220 | local function checkF (func, val) | ||
| 221 | check(func, 'LOADF', 'RETURN1') | ||
| 222 | assert(#T.listk(func) == 0) | ||
| 223 | assert(func() == val) | ||
| 224 | end | ||
| 225 | |||
| 226 | checkF(function () return 0.0 end, 0.0) | ||
| 227 | checkI(function () return 0 end, 0) | ||
| 228 | checkI(function () return -0//1 end, 0) | ||
| 229 | checkK(function () return 3^-1 end, 1/3) | ||
| 230 | checkK(function () return (1 + 1)^(50 + 50) end, 2^100) | ||
| 231 | checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0) | ||
| 232 | checkF(function () return (-3^0 + 5) // 3.0 end, 1.0) | ||
| 233 | checkI(function () return -3 % 5 end, 2) | ||
| 234 | checkF(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0) | ||
| 235 | checkF(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0) | ||
| 236 | checkI(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4) | ||
| 237 | checkI(function () return ~(~0xFF0 | 0xFF0) end, 0) | ||
| 238 | checkI(function () return ~~-1024.0 end, -1024) | ||
| 239 | checkI(function () return ((100 << 6) << -4) >> 2 end, 100) | ||
| 240 | |||
| 241 | -- borders around MAXARG_sBx ((((1 << 17) - 1) >> 1) == 65535) | ||
| 242 | local sbx = ((1 << "17") - 1) >> 1 -- avoid folding | ||
| 243 | checkI(function () return 65535 end, sbx) | ||
| 244 | checkI(function () return -65535 end, -sbx) | ||
| 245 | checkI(function () return 65536 end, sbx + 1) | ||
| 246 | checkK(function () return 65537 end, sbx + 2) | ||
| 247 | checkK(function () return -65536 end, -(sbx + 1)) | ||
| 248 | |||
| 249 | checkF(function () return 65535.0 end, sbx + 0.0) | ||
| 250 | checkF(function () return -65535.0 end, -sbx + 0.0) | ||
| 251 | checkF(function () return 65536.0 end, (sbx + 1.0)) | ||
| 252 | checkK(function () return 65537.0 end, (sbx + 2.0)) | ||
| 253 | checkK(function () return -65536.0 end, -(sbx + 1.0)) | ||
| 254 | |||
| 255 | |||
| 256 | -- immediate operands | ||
| 257 | check(function (x) return x + 1 end, 'ADDI', 'RETURN1') | ||
| 258 | check(function (x) return 128 + x end, 'ADDI', 'RETURN1') | ||
| 259 | check(function (x) return x * -127 end, 'MULI', 'RETURN1') | ||
| 260 | check(function (x) return 20 * x end, 'MULI', 'RETURN1') | ||
| 261 | check(function (x) return x ^ -2 end, 'POWI', 'RETURN1') | ||
| 262 | check(function (x) return x / 40 end, 'DIVI', 'RETURN1') | ||
| 263 | check(function (x) return x // 1 end, 'IDIVI', 'RETURN1') | ||
| 264 | check(function (x) return x % (100 - 10) end, 'MODI', 'RETURN1') | ||
| 265 | check(function (x) return 1 << x end, 'SHLI', 'RETURN1') | ||
| 266 | check(function (x) return x << 2 end, 'SHRI', 'RETURN1') | ||
| 267 | check(function (x) return x >> 2 end, 'SHRI', 'RETURN1') | ||
| 268 | check(function (x) return x & 1 end, 'BANDK', 'RETURN1') | ||
| 269 | check(function (x) return 10 | x end, 'BORK', 'RETURN1') | ||
| 270 | check(function (x) return -10 ~ x end, 'BXORK', 'RETURN1') | ||
| 271 | |||
| 272 | -- no foldings (and immediate operands) | ||
| 273 | check(function () return -0.0 end, 'LOADF', 'UNM', 'RETURN1') | ||
| 274 | check(function () return 3/0 end, 'LOADI', 'DIVI', 'RETURN1') | ||
| 275 | check(function () return 0%0 end, 'LOADI', 'MODI', 'RETURN1') | ||
| 276 | check(function () return -4//0 end, 'LOADI', 'IDIVI', 'RETURN1') | ||
| 277 | check(function (x) return x >> 2.0 end, 'LOADF', 'SHR', 'RETURN1') | ||
| 278 | check(function (x) return x & 2.0 end, 'LOADF', 'BAND', 'RETURN1') | ||
| 279 | |||
| 280 | -- basic 'for' loops | ||
| 281 | check(function () for i = -10, 10.5 do end end, | ||
| 282 | 'LOADI', 'LOADK', 'LOADI', 'FORPREP1', 'FORLOOP1', 'RETURN0') | ||
| 283 | check(function () for i = 0xfffffff, 10.0, 1 do end end, | ||
| 284 | 'LOADK', 'LOADF', 'LOADI', 'FORPREP1', 'FORLOOP1', 'RETURN0') | ||
| 285 | |||
| 286 | -- bug in constant folding for 5.1 | ||
| 287 | check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN1') | ||
| 288 | |||
| 289 | |||
| 290 | check(function () | ||
| 291 | local a,b,c | ||
| 292 | b[c], a = c, b | ||
| 293 | b[a], a = c, b | ||
| 294 | a, b = c, a | ||
| 295 | a = a | ||
| 296 | end, | ||
| 297 | 'LOADNIL', | ||
| 298 | 'MOVE', 'MOVE', 'SETTABLE', | ||
| 299 | 'MOVE', 'MOVE', 'MOVE', 'SETTABLE', | ||
| 300 | 'MOVE', 'MOVE', 'MOVE', | ||
| 301 | -- no code for a = a | ||
| 302 | 'RETURN0') | ||
| 303 | |||
| 304 | |||
| 305 | -- x == nil , x ~= nil | ||
| 306 | -- checkequal(function (b) if (a==nil) then a=1 end; if a~=nil then a=1 end end, | ||
| 307 | -- function () if (a==9) then a=1 end; if a~=9 then a=1 end end) | ||
| 308 | |||
| 309 | -- check(function () if a==nil then a='a' end end, | ||
| 310 | -- 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN') | ||
| 311 | |||
| 312 | do -- tests for table access in upvalues | ||
| 313 | local t | ||
| 314 | check(function () t.x = t.y end, 'GETTABUP', 'SETTABUP') | ||
| 315 | check(function (a) t[a()] = t[a()] end, | ||
| 316 | 'MOVE', 'CALL', 'GETUPVAL', 'MOVE', 'CALL', | ||
| 317 | 'GETUPVAL', 'GETTABLE', 'SETTABLE') | ||
| 318 | end | ||
| 319 | |||
| 320 | -- de morgan | ||
| 321 | checkequal(function () local a; if not (a or b) then b=a end end, | ||
| 322 | function () local a; if (not a and not b) then b=a end end) | ||
| 323 | |||
| 324 | checkequal(function (l) local a; return 0 <= a and a <= l end, | ||
| 325 | function (l) local a; return not (not(a >= 0) or not(a <= l)) end) | ||
| 326 | |||
| 327 | |||
| 328 | -- if-goto optimizations | ||
| 329 | check(function (a, b, c, d, e) | ||
| 330 | if a == b then goto l1; | ||
| 331 | elseif a == c then goto l2; | ||
| 332 | elseif a == d then goto l2; | ||
| 333 | else if a == e then goto l3; | ||
| 334 | else goto l3 | ||
| 335 | end | ||
| 336 | end | ||
| 337 | ::l1:: ::l2:: ::l3:: ::l4:: | ||
| 338 | end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', | ||
| 339 | 'CLOSE', 'CLOSE', 'CLOSE', 'CLOSE', 'RETURN0') | ||
| 340 | |||
| 341 | checkequal( | ||
| 342 | function (a) while a < 10 do a = a + 1 end end, | ||
| 343 | function (a) while true do if not(a < 10) then break end; a = a + 1; end end | ||
| 344 | ) | ||
| 345 | |||
| 346 | print 'OK' | ||
| 347 | |||
