2
0

code.lua 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. -- $Id: code.lua,v 1.42 2016/11/07 13:04:32 roberto Exp $
  2. -- See Copyright Notice in file all.lua
  3. if T==nil then
  4. (Message or print)('\n >>> testC not active: skipping opcode tests <<<\n')
  5. return
  6. end
  7. print "testing code generation and optimizations"
  8. -- this code gave an error for the code checker
  9. do
  10. local function f (a)
  11. for k,v,w in a do end
  12. end
  13. end
  14. -- testing reuse in constant table
  15. local function checkKlist (func, list)
  16. local k = T.listk(func)
  17. assert(#k == #list)
  18. for i = 1, #k do
  19. assert(k[i] == list[i] and math.type(k[i]) == math.type(list[i]))
  20. end
  21. end
  22. local function foo ()
  23. local a
  24. a = 3;
  25. a = 0; a = 0.0; a = -7 + 7
  26. a = 3.78/4; a = 3.78/4
  27. a = -3.78/4; a = 3.78/4; a = -3.78/4
  28. a = -3.79/4; a = 0.0; a = -0;
  29. a = 3; a = 3.0; a = 3; a = 3.0
  30. end
  31. checkKlist(foo, {3, 0, 0.0, 3.78/4, -3.78/4, -3.79/4, 3.0})
  32. -- testing opcodes
  33. function check (f, ...)
  34. local arg = {...}
  35. local c = T.listcode(f)
  36. for i=1, #arg do
  37. -- print(arg[i], c[i])
  38. assert(string.find(c[i], '- '..arg[i]..' *%d'))
  39. end
  40. assert(c[#arg+2] == nil)
  41. end
  42. function checkequal (a, b)
  43. a = T.listcode(a)
  44. b = T.listcode(b)
  45. for i = 1, #a do
  46. a[i] = string.gsub(a[i], '%b()', '') -- remove line number
  47. b[i] = string.gsub(b[i], '%b()', '') -- remove line number
  48. assert(a[i] == b[i])
  49. end
  50. end
  51. -- some basic instructions
  52. check(function ()
  53. (function () end){f()}
  54. end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
  55. -- sequence of LOADNILs
  56. check(function ()
  57. local a,b,c
  58. local d; local e;
  59. local f,g,h;
  60. d = nil; d=nil; b=nil; a=nil; c=nil;
  61. end, 'LOADNIL', 'RETURN')
  62. check(function ()
  63. local a,b,c,d = 1,1,1,1
  64. d=nil;c=nil;b=nil;a=nil
  65. end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN')
  66. do
  67. local a,b,c,d = 1,1,1,1
  68. d=nil;c=nil;b=nil;a=nil
  69. assert(a == nil and b == nil and c == nil and d == nil)
  70. end
  71. -- single return
  72. check (function (a,b,c) return a end, 'RETURN')
  73. -- infinite loops
  74. check(function () while true do local a = -1 end end,
  75. 'LOADK', 'JMP', 'RETURN')
  76. check(function () while 1 do local a = -1 end end,
  77. 'LOADK', 'JMP', 'RETURN')
  78. check(function () repeat local x = 1 until true end,
  79. 'LOADK', 'RETURN')
  80. -- concat optimization
  81. check(function (a,b,c,d) return a..b..c..d end,
  82. 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
  83. -- not
  84. check(function () return not not nil end, 'LOADBOOL', 'RETURN')
  85. check(function () return not not false end, 'LOADBOOL', 'RETURN')
  86. check(function () return not not true end, 'LOADBOOL', 'RETURN')
  87. check(function () return not not 1 end, 'LOADBOOL', 'RETURN')
  88. -- direct access to locals
  89. check(function ()
  90. local a,b,c,d
  91. a = b*2
  92. c[2], a[b] = -((a + d/2 - a[b]) ^ a.x), b
  93. end,
  94. 'LOADNIL',
  95. 'MUL',
  96. 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
  97. 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
  98. -- direct access to constants
  99. check(function ()
  100. local a,b
  101. a.x = 3.2
  102. a.x = b
  103. a[b] = 'x'
  104. end,
  105. 'LOADNIL', 'SETTABLE', 'SETTABLE', 'SETTABLE', 'RETURN')
  106. check(function ()
  107. local a,b
  108. a = 1 - a
  109. b = 1/a
  110. b = 5-4
  111. end,
  112. 'LOADNIL', 'SUB', 'DIV', 'LOADK', 'RETURN')
  113. check(function ()
  114. local a,b
  115. a[true] = false
  116. end,
  117. 'LOADNIL', 'SETTABLE', 'RETURN')
  118. -- constant folding
  119. local function checkK (func, val)
  120. check(func, 'LOADK', 'RETURN')
  121. local k = T.listk(func)
  122. assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val))
  123. assert(func() == val)
  124. end
  125. checkK(function () return 0.0 end, 0.0)
  126. checkK(function () return 0 end, 0)
  127. checkK(function () return -0//1 end, 0)
  128. checkK(function () return 3^-1 end, 1/3)
  129. checkK(function () return (1 + 1)^(50 + 50) end, 2^100)
  130. checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0)
  131. checkK(function () return (-3^0 + 5) // 3.0 end, 1.0)
  132. checkK(function () return -3 % 5 end, 2)
  133. checkK(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0)
  134. checkK(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0)
  135. checkK(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4)
  136. checkK(function () return ~(~0xFF0 | 0xFF0) end, 0)
  137. checkK(function () return ~~-100024.0 end, -100024)
  138. checkK(function () return ((100 << 6) << -4) >> 2 end, 100)
  139. -- no foldings
  140. check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN')
  141. check(function () return 3/0 end, 'DIV', 'RETURN')
  142. check(function () return 0%0 end, 'MOD', 'RETURN')
  143. check(function () return -4//0 end, 'IDIV', 'RETURN')
  144. -- bug in constant folding for 5.1
  145. check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN')
  146. check(function ()
  147. local a,b,c
  148. b[c], a = c, b
  149. b[a], a = c, b
  150. a, b = c, a
  151. a = a
  152. end,
  153. 'LOADNIL',
  154. 'MOVE', 'MOVE', 'SETTABLE',
  155. 'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
  156. 'MOVE', 'MOVE', 'MOVE',
  157. -- no code for a = a
  158. 'RETURN')
  159. -- x == nil , x ~= nil
  160. checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end,
  161. function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
  162. check(function () if a==nil then a='a' end end,
  163. 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
  164. -- de morgan
  165. checkequal(function () local a; if not (a or b) then b=a end end,
  166. function () local a; if (not a and not b) then b=a end end)
  167. checkequal(function (l) local a; return 0 <= a and a <= l end,
  168. function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
  169. -- if-goto optimizations
  170. check(function (a, b, c, d, e)
  171. if a == b then goto l1
  172. elseif a == c then goto l2
  173. elseif a == d then goto l2
  174. else if a == e then goto l3
  175. else goto l3
  176. end
  177. end
  178. ::l1:: ::l2:: ::l3:: ::l4::
  179. end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN')
  180. checkequal(
  181. function (a) while a < 10 do a = a + 1 end end,
  182. function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1;
  183. goto L2; ::L1:: end
  184. )
  185. checkequal(
  186. function (a) while a < 10 do a = a + 1 end end,
  187. function (a) while true do if not(a < 10) then break end; a = a + 1; end end
  188. )
  189. print 'OK'