code.lua 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. if T==nil then
  2. (Message or print)('\a\n >>> testC not active: skipping opcode tests <<<\n\a')
  3. return
  4. end
  5. print "testing code generation and optimizations"
  6. -- this code gave an error for the code checker
  7. do
  8. local function f (a)
  9. for k,v,w in a do end
  10. end
  11. end
  12. function check (f, ...)
  13. local arg = {...}
  14. local c = T.listcode(f)
  15. for i=1, #arg do
  16. -- print(arg[i], c[i])
  17. assert(string.find(c[i], '- '..arg[i]..' *%d'))
  18. end
  19. assert(c[#arg+2] == nil)
  20. end
  21. function checkequal (a, b)
  22. a = T.listcode(a)
  23. b = T.listcode(b)
  24. for i = 1, #a do
  25. a[i] = string.gsub(a[i], '%b()', '') -- remove line number
  26. b[i] = string.gsub(b[i], '%b()', '') -- remove line number
  27. assert(a[i] == b[i])
  28. end
  29. end
  30. -- some basic instructions
  31. check(function ()
  32. (function () end){f()}
  33. end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
  34. -- sequence of LOADNILs
  35. check(function ()
  36. local a,b,c
  37. local d; local e;
  38. local f,g,h;
  39. d = nil; d=nil; b=nil; a=nil; c=nil;
  40. end, 'LOADNIL', 'RETURN')
  41. check(function ()
  42. local a,b,c,d = 1,1,1,1
  43. d=nil;c=nil;b=nil;a=nil
  44. end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN')
  45. do
  46. local a,b,c,d = 1,1,1,1
  47. d=nil;c=nil;b=nil;a=nil
  48. assert(a == nil and b == nil and c == nil and d == nil)
  49. end
  50. -- single return
  51. check (function (a,b,c) return a end, 'RETURN')
  52. -- infinite loops
  53. check(function () while true do local a = -1 end end,
  54. 'LOADK', 'JMP', 'RETURN')
  55. check(function () while 1 do local a = -1 end end,
  56. 'LOADK', 'JMP', 'RETURN')
  57. check(function () repeat local x = 1 until true end,
  58. 'LOADK', 'RETURN')
  59. -- concat optimization
  60. check(function (a,b,c,d) return a..b..c..d end,
  61. 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN')
  62. -- not
  63. check(function () return not not nil end, 'LOADBOOL', 'RETURN')
  64. check(function () return not not false end, 'LOADBOOL', 'RETURN')
  65. check(function () return not not true end, 'LOADBOOL', 'RETURN')
  66. check(function () return not not 1 end, 'LOADBOOL', 'RETURN')
  67. -- direct access to locals
  68. check(function ()
  69. local a,b,c,d
  70. a = b*2
  71. c[4], a[b] = -((a + d/-20.5 - a[b]) ^ a.x), b
  72. end,
  73. 'LOADNIL',
  74. 'MUL',
  75. 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW',
  76. 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN')
  77. -- direct access to constants
  78. check(function ()
  79. local a,b
  80. a.x = 0
  81. a.x = b
  82. a[b] = 'y'
  83. a = 1 - a
  84. b = 1/a
  85. b = 5+4
  86. a[true] = false
  87. end,
  88. 'LOADNIL',
  89. 'SETTABLE', 'SETTABLE', 'SETTABLE', 'SUB', 'DIV', 'LOADK',
  90. 'SETTABLE', 'RETURN')
  91. -- constant folding
  92. local function f () return -((2^8 + -(-1)) % 8)/2 * 4 - 3 end
  93. check(f, 'LOADK', 'RETURN')
  94. assert(f() == -5)
  95. -- bug in constant folding for 5.1
  96. check(function () return -nil end,
  97. 'LOADNIL', 'UNM', 'RETURN')
  98. check(function ()
  99. local a,b,c
  100. b[c], a = c, b
  101. b[a], a = c, b
  102. a, b = c, a
  103. a = a
  104. end,
  105. 'LOADNIL',
  106. 'MOVE', 'MOVE', 'SETTABLE',
  107. 'MOVE', 'MOVE', 'MOVE', 'SETTABLE',
  108. 'MOVE', 'MOVE', 'MOVE',
  109. -- no code for a = a
  110. 'RETURN')
  111. -- x == nil , x ~= nil
  112. checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end,
  113. function () if (a==9) then a=1 end; if a~=9 then a=1 end end)
  114. check(function () if a==nil then a=1 end end,
  115. 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN')
  116. -- de morgan
  117. checkequal(function () local a; if not (a or b) then b=a end end,
  118. function () local a; if (not a and not b) then b=a end end)
  119. checkequal(function (l) local a; return 0 <= a and a <= l end,
  120. function (l) local a; return not (not(a >= 0) or not(a <= l)) end)
  121. -- if-goto optimizations
  122. check(function (a)
  123. if a == 1 then goto l1
  124. elseif a == 2 then goto l2
  125. elseif a == 3 then goto l2
  126. else if a == 4 then goto l3
  127. else goto l3
  128. end
  129. end
  130. ::l1:: ::l2:: ::l3:: ::l4::
  131. end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN')
  132. checkequal(
  133. function (a) while a < 10 do a = a + 1 end end,
  134. function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1;
  135. goto L2; ::L1:: end
  136. )
  137. checkequal(
  138. function (a) while a < 10 do a = a + 1 end end,
  139. function (a) while true do if not(a < 10) then break end; a = a + 1; end end
  140. )
  141. print 'OK'