diff options
Diffstat (limited to '')
-rw-r--r-- | testes/code.lua | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/testes/code.lua b/testes/code.lua new file mode 100644 index 00000000..0b9d142d --- /dev/null +++ b/testes/code.lua | |||
@@ -0,0 +1,239 @@ | |||
1 | -- $Id: code.lua,v 1.42 2016/11/07 13:04:32 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, 0, 0.0, 3.78/4, -3.78/4, -3.79/4, 3.0}) | ||
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 | -- print(arg[i], c[i]) | ||
48 | assert(string.find(c[i], '- '..arg[i]..' *%d')) | ||
49 | end | ||
50 | assert(c[#arg+2] == nil) | ||
51 | end | ||
52 | |||
53 | |||
54 | function checkequal (a, b) | ||
55 | a = T.listcode(a) | ||
56 | b = T.listcode(b) | ||
57 | for i = 1, #a do | ||
58 | a[i] = string.gsub(a[i], '%b()', '') -- remove line number | ||
59 | b[i] = string.gsub(b[i], '%b()', '') -- remove line number | ||
60 | assert(a[i] == b[i]) | ||
61 | end | ||
62 | end | ||
63 | |||
64 | |||
65 | -- some basic instructions | ||
66 | check(function () | ||
67 | (function () end){f()} | ||
68 | end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN') | ||
69 | |||
70 | |||
71 | -- sequence of LOADNILs | ||
72 | check(function () | ||
73 | local a,b,c | ||
74 | local d; local e; | ||
75 | local f,g,h; | ||
76 | d = nil; d=nil; b=nil; a=nil; c=nil; | ||
77 | end, 'LOADNIL', 'RETURN') | ||
78 | |||
79 | check(function () | ||
80 | local a,b,c,d = 1,1,1,1 | ||
81 | d=nil;c=nil;b=nil;a=nil | ||
82 | end, 'LOADK', 'LOADK', 'LOADK', 'LOADK', 'LOADNIL', 'RETURN') | ||
83 | |||
84 | do | ||
85 | local a,b,c,d = 1,1,1,1 | ||
86 | d=nil;c=nil;b=nil;a=nil | ||
87 | assert(a == nil and b == nil and c == nil and d == nil) | ||
88 | end | ||
89 | |||
90 | |||
91 | -- single return | ||
92 | check (function (a,b,c) return a end, 'RETURN') | ||
93 | |||
94 | |||
95 | -- infinite loops | ||
96 | check(function () while true do local a = -1 end end, | ||
97 | 'LOADK', 'JMP', 'RETURN') | ||
98 | |||
99 | check(function () while 1 do local a = -1 end end, | ||
100 | 'LOADK', 'JMP', 'RETURN') | ||
101 | |||
102 | check(function () repeat local x = 1 until true end, | ||
103 | 'LOADK', 'RETURN') | ||
104 | |||
105 | |||
106 | -- concat optimization | ||
107 | check(function (a,b,c,d) return a..b..c..d end, | ||
108 | 'MOVE', 'MOVE', 'MOVE', 'MOVE', 'CONCAT', 'RETURN') | ||
109 | |||
110 | -- not | ||
111 | check(function () return not not nil end, 'LOADBOOL', 'RETURN') | ||
112 | check(function () return not not false end, 'LOADBOOL', 'RETURN') | ||
113 | check(function () return not not true end, 'LOADBOOL', 'RETURN') | ||
114 | check(function () return not not 1 end, 'LOADBOOL', 'RETURN') | ||
115 | |||
116 | -- direct access to locals | ||
117 | check(function () | ||
118 | local a,b,c,d | ||
119 | a = b*2 | ||
120 | c[2], a[b] = -((a + d/2 - a[b]) ^ a.x), b | ||
121 | end, | ||
122 | 'LOADNIL', | ||
123 | 'MUL', | ||
124 | 'DIV', 'ADD', 'GETTABLE', 'SUB', 'GETTABLE', 'POW', | ||
125 | 'UNM', 'SETTABLE', 'SETTABLE', 'RETURN') | ||
126 | |||
127 | |||
128 | -- direct access to constants | ||
129 | check(function () | ||
130 | local a,b | ||
131 | a.x = 3.2 | ||
132 | a.x = b | ||
133 | a[b] = 'x' | ||
134 | end, | ||
135 | 'LOADNIL', 'SETTABLE', 'SETTABLE', 'SETTABLE', 'RETURN') | ||
136 | |||
137 | check(function () | ||
138 | local a,b | ||
139 | a = 1 - a | ||
140 | b = 1/a | ||
141 | b = 5-4 | ||
142 | end, | ||
143 | 'LOADNIL', 'SUB', 'DIV', 'LOADK', 'RETURN') | ||
144 | |||
145 | check(function () | ||
146 | local a,b | ||
147 | a[true] = false | ||
148 | end, | ||
149 | 'LOADNIL', 'SETTABLE', 'RETURN') | ||
150 | |||
151 | |||
152 | -- constant folding | ||
153 | local function checkK (func, val) | ||
154 | check(func, 'LOADK', 'RETURN') | ||
155 | local k = T.listk(func) | ||
156 | assert(#k == 1 and k[1] == val and math.type(k[1]) == math.type(val)) | ||
157 | assert(func() == val) | ||
158 | end | ||
159 | checkK(function () return 0.0 end, 0.0) | ||
160 | checkK(function () return 0 end, 0) | ||
161 | checkK(function () return -0//1 end, 0) | ||
162 | checkK(function () return 3^-1 end, 1/3) | ||
163 | checkK(function () return (1 + 1)^(50 + 50) end, 2^100) | ||
164 | checkK(function () return (-2)^(31 - 2) end, -0x20000000 + 0.0) | ||
165 | checkK(function () return (-3^0 + 5) // 3.0 end, 1.0) | ||
166 | checkK(function () return -3 % 5 end, 2) | ||
167 | checkK(function () return -((2.0^8 + -(-1)) % 8)/2 * 4 - 3 end, -5.0) | ||
168 | checkK(function () return -((2^8 + -(-1)) % 8)//2 * 4 - 3 end, -7.0) | ||
169 | checkK(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4) | ||
170 | checkK(function () return ~(~0xFF0 | 0xFF0) end, 0) | ||
171 | checkK(function () return ~~-100024.0 end, -100024) | ||
172 | checkK(function () return ((100 << 6) << -4) >> 2 end, 100) | ||
173 | |||
174 | |||
175 | -- no foldings | ||
176 | check(function () return -0.0 end, 'LOADK', 'UNM', 'RETURN') | ||
177 | check(function () return 3/0 end, 'DIV', 'RETURN') | ||
178 | check(function () return 0%0 end, 'MOD', 'RETURN') | ||
179 | check(function () return -4//0 end, 'IDIV', 'RETURN') | ||
180 | |||
181 | -- bug in constant folding for 5.1 | ||
182 | check(function () return -nil end, 'LOADNIL', 'UNM', 'RETURN') | ||
183 | |||
184 | |||
185 | check(function () | ||
186 | local a,b,c | ||
187 | b[c], a = c, b | ||
188 | b[a], a = c, b | ||
189 | a, b = c, a | ||
190 | a = a | ||
191 | end, | ||
192 | 'LOADNIL', | ||
193 | 'MOVE', 'MOVE', 'SETTABLE', | ||
194 | 'MOVE', 'MOVE', 'MOVE', 'SETTABLE', | ||
195 | 'MOVE', 'MOVE', 'MOVE', | ||
196 | -- no code for a = a | ||
197 | 'RETURN') | ||
198 | |||
199 | |||
200 | -- x == nil , x ~= nil | ||
201 | checkequal(function () if (a==nil) then a=1 end; if a~=nil then a=1 end end, | ||
202 | function () if (a==9) then a=1 end; if a~=9 then a=1 end end) | ||
203 | |||
204 | check(function () if a==nil then a='a' end end, | ||
205 | 'GETTABUP', 'EQ', 'JMP', 'SETTABUP', 'RETURN') | ||
206 | |||
207 | -- de morgan | ||
208 | checkequal(function () local a; if not (a or b) then b=a end end, | ||
209 | function () local a; if (not a and not b) then b=a end end) | ||
210 | |||
211 | checkequal(function (l) local a; return 0 <= a and a <= l end, | ||
212 | function (l) local a; return not (not(a >= 0) or not(a <= l)) end) | ||
213 | |||
214 | |||
215 | -- if-goto optimizations | ||
216 | check(function (a, b, c, d, e) | ||
217 | if a == b then goto l1 | ||
218 | elseif a == c then goto l2 | ||
219 | elseif a == d then goto l2 | ||
220 | else if a == e then goto l3 | ||
221 | else goto l3 | ||
222 | end | ||
223 | end | ||
224 | ::l1:: ::l2:: ::l3:: ::l4:: | ||
225 | end, 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'EQ', 'JMP', 'JMP', 'RETURN') | ||
226 | |||
227 | checkequal( | ||
228 | function (a) while a < 10 do a = a + 1 end end, | ||
229 | function (a) ::L2:: if not(a < 10) then goto L1 end; a = a + 1; | ||
230 | goto L2; ::L1:: end | ||
231 | ) | ||
232 | |||
233 | checkequal( | ||
234 | function (a) while a < 10 do a = a + 1 end end, | ||
235 | function (a) while true do if not(a < 10) then break end; a = a + 1; end end | ||
236 | ) | ||
237 | |||
238 | print 'OK' | ||
239 | |||