OLD | NEW |
| (Empty) |
1 // Copyright 2015 the V8 project authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/v8.h" | |
6 | |
7 #include "src/asmjs/typing-asm.h" | |
8 #include "src/ast/ast-expression-visitor.h" | |
9 #include "src/ast/ast.h" | |
10 #include "src/ast/scopes.h" | |
11 #include "src/parsing/parser.h" | |
12 #include "src/parsing/rewriter.h" | |
13 #include "src/type-cache.h" | |
14 #include "test/cctest/cctest.h" | |
15 #include "test/cctest/expression-type-collector-macros.h" | |
16 #include "test/cctest/expression-type-collector.h" | |
17 | |
18 // Macros for function types. | |
19 #define FUNC_FOREIGN_TYPE Bounds(Type::Function(Type::Any(), zone)) | |
20 #define FUNC_V_TYPE Bounds(Type::Function(Type::Undefined(), zone)) | |
21 #define FUNC_I_TYPE Bounds(Type::Function(cache.kAsmSigned, zone)) | |
22 #define FUNC_F_TYPE Bounds(Type::Function(cache.kAsmFloat, zone)) | |
23 #define FUNC_D_TYPE Bounds(Type::Function(cache.kAsmDouble, zone)) | |
24 #define FUNC_D2D_TYPE \ | |
25 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, zone)) | |
26 #define FUNC_N2F_TYPE \ | |
27 Bounds(Type::Function(cache.kAsmFloat, Type::Number(), zone)) | |
28 #define FUNC_I2I_TYPE \ | |
29 Bounds(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone)) | |
30 #define FUNC_II2D_TYPE \ | |
31 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmInt, cache.kAsmInt, zone)) | |
32 #define FUNC_II2I_TYPE \ | |
33 Bounds(Type::Function(cache.kAsmSigned, cache.kAsmInt, cache.kAsmInt, zone)) | |
34 #define FUNC_DD2D_TYPE \ | |
35 Bounds(Type::Function(cache.kAsmDouble, cache.kAsmDouble, cache.kAsmDouble, \ | |
36 zone)) | |
37 #define FUNC_NN2N_TYPE \ | |
38 Bounds(Type::Function(Type::Number(), Type::Number(), Type::Number(), zone)) | |
39 #define FUNC_N2N_TYPE \ | |
40 Bounds(Type::Function(Type::Number(), Type::Number(), zone)) | |
41 | |
42 // Macros for array types. | |
43 #define FLOAT64_ARRAY_TYPE Bounds(Type::Array(cache.kAsmDouble, zone)) | |
44 #define FUNC_I2I_ARRAY_TYPE \ | |
45 Bounds(Type::Array(Type::Function(cache.kAsmSigned, cache.kAsmInt, zone), \ | |
46 zone)) | |
47 | |
48 using namespace v8::internal; | |
49 | |
50 namespace { | |
51 | |
52 std::string Validate(Zone* zone, const char* source, | |
53 ZoneVector<ExpressionTypeEntry>* types) { | |
54 i::Isolate* isolate = CcTest::i_isolate(); | |
55 i::Factory* factory = isolate->factory(); | |
56 | |
57 i::Handle<i::String> source_code = | |
58 factory->NewStringFromUtf8(i::CStrVector(source)).ToHandleChecked(); | |
59 | |
60 i::Handle<i::Script> script = factory->NewScript(source_code); | |
61 | |
62 i::ParseInfo info(zone, script); | |
63 i::Parser parser(&info); | |
64 info.set_global(); | |
65 info.set_lazy(false); | |
66 info.set_allow_lazy_parsing(false); | |
67 info.set_toplevel(true); | |
68 | |
69 CHECK(i::Compiler::ParseAndAnalyze(&info)); | |
70 | |
71 FunctionLiteral* root = | |
72 info.scope()->declarations()->at(0)->AsFunctionDeclaration()->fun(); | |
73 AsmTyper typer(isolate, zone, *script, root); | |
74 if (typer.Validate()) { | |
75 ExpressionTypeCollector(isolate, root, typer.bounds(), types).Run(); | |
76 return ""; | |
77 } else { | |
78 return typer.error_message(); | |
79 } | |
80 } | |
81 | |
82 } // namespace | |
83 | |
84 TEST(ValidateMinimum) { | |
85 const char test_function[] = | |
86 "function GeometricMean(stdlib, foreign, buffer) {\n" | |
87 " \"use asm\";\n" | |
88 "\n" | |
89 " var exp = stdlib.Math.exp;\n" | |
90 " var log = stdlib.Math.log;\n" | |
91 " var values = new stdlib.Float64Array(buffer);\n" | |
92 "\n" | |
93 " function logSum(start, end) {\n" | |
94 " start = start|0;\n" | |
95 " end = end|0;\n" | |
96 "\n" | |
97 " var sum = 0.0, p = 0, q = 0;\n" | |
98 "\n" | |
99 " // asm.js forces byte addressing of the heap by requiring shifting " | |
100 "by 3\n" | |
101 " for (p = start << 3, q = end << 3; (p|0) < (q|0); p = (p + 8)|0) {\n" | |
102 " sum = sum + +log(values[p>>3]);\n" | |
103 " }\n" | |
104 "\n" | |
105 " return +sum;\n" | |
106 " }\n" | |
107 "\n" | |
108 " function geometricMean(start, end) {\n" | |
109 " start = start|0;\n" | |
110 " end = end|0;\n" | |
111 "\n" | |
112 " return +exp(+logSum(start, end) / +((end - start)|0));\n" | |
113 " }\n" | |
114 "\n" | |
115 " return { geometricMean: geometricMean };\n" | |
116 "}\n"; | |
117 | |
118 v8::V8::Initialize(); | |
119 HandleAndZoneScope handles; | |
120 Zone* zone = handles.main_zone(); | |
121 ZoneVector<ExpressionTypeEntry> types(zone); | |
122 CHECK_EQ("", Validate(zone, test_function, &types)); | |
123 TypeCache cache; | |
124 | |
125 CHECK_TYPES_BEGIN { | |
126 // Module. | |
127 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { | |
128 // function logSum | |
129 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) { | |
130 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
131 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
132 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
133 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
134 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
135 } | |
136 } | |
137 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
138 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
139 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
140 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
141 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
142 } | |
143 } | |
144 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
145 CHECK_VAR(sum, Bounds(cache.kAsmDouble)); | |
146 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
147 } | |
148 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
149 CHECK_VAR(p, Bounds(cache.kAsmInt)); | |
150 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
151 } | |
152 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
153 CHECK_VAR(q, Bounds(cache.kAsmInt)); | |
154 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
155 } | |
156 // for (p = start << 3, q = end << 3; | |
157 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
158 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
159 CHECK_VAR(p, Bounds(cache.kAsmInt)); | |
160 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
161 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
162 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
163 } | |
164 } | |
165 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
166 CHECK_VAR(q, Bounds(cache.kAsmInt)); | |
167 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
168 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
169 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
170 } | |
171 } | |
172 } | |
173 // (p|0) < (q|0); | |
174 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
175 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
176 CHECK_VAR(p, Bounds(cache.kAsmInt)); | |
177 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
178 } | |
179 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
180 CHECK_VAR(q, Bounds(cache.kAsmInt)); | |
181 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
182 } | |
183 } | |
184 // p = (p + 8)|0) { | |
185 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
186 CHECK_VAR(p, Bounds(cache.kAsmInt)); | |
187 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
188 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
189 CHECK_VAR(p, Bounds(cache.kAsmInt)); | |
190 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
191 } | |
192 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
193 } | |
194 } | |
195 // sum = sum + +log(values[p>>3]); | |
196 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
197 CHECK_VAR(sum, Bounds(cache.kAsmDouble)); | |
198 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
199 CHECK_VAR(sum, Bounds(cache.kAsmDouble)); | |
200 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
201 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
202 CHECK_VAR(log, FUNC_D2D_TYPE); | |
203 CHECK_EXPR(Property, Bounds(cache.kAsmDouble)) { | |
204 CHECK_VAR(values, FLOAT64_ARRAY_TYPE); | |
205 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
206 CHECK_VAR(p, Bounds(cache.kAsmInt)); | |
207 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
208 } | |
209 } | |
210 } | |
211 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
212 } | |
213 } | |
214 } | |
215 // return +sum; | |
216 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
217 CHECK_VAR(sum, Bounds(cache.kAsmDouble)); | |
218 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
219 } | |
220 } | |
221 // function geometricMean | |
222 CHECK_EXPR(FunctionLiteral, FUNC_II2D_TYPE) { | |
223 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
224 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
225 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
226 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
227 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
228 } | |
229 } | |
230 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
231 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
232 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
233 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
234 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
235 } | |
236 } | |
237 // return +exp(+logSum(start, end) / +((end - start)|0)); | |
238 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
239 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
240 CHECK_VAR(exp, FUNC_D2D_TYPE); | |
241 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
242 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
243 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
244 CHECK_VAR(logSum, FUNC_II2D_TYPE); | |
245 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
246 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
247 } | |
248 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
249 } | |
250 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
251 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
252 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
253 CHECK_VAR(end, Bounds(cache.kAsmInt)); | |
254 CHECK_VAR(start, Bounds(cache.kAsmInt)); | |
255 } | |
256 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
257 } | |
258 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
259 } | |
260 } | |
261 } | |
262 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
263 } | |
264 } | |
265 // "use asm"; | |
266 CHECK_EXPR(Literal, Bounds(Type::String())); | |
267 // var exp = stdlib.Math.exp; | |
268 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) { | |
269 CHECK_VAR(exp, FUNC_D2D_TYPE); | |
270 CHECK_EXPR(Property, FUNC_D2D_TYPE) { | |
271 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
272 CHECK_VAR(stdlib, Bounds::Unbounded()); | |
273 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
274 } | |
275 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
276 } | |
277 } | |
278 // var log = stdlib.Math.log; | |
279 CHECK_EXPR(Assignment, FUNC_D2D_TYPE) { | |
280 CHECK_VAR(log, FUNC_D2D_TYPE); | |
281 CHECK_EXPR(Property, FUNC_D2D_TYPE) { | |
282 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
283 CHECK_VAR(stdlib, Bounds::Unbounded()); | |
284 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
285 } | |
286 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
287 } | |
288 } | |
289 // var values = new stdlib.Float64Array(buffer); | |
290 CHECK_EXPR(Assignment, FLOAT64_ARRAY_TYPE) { | |
291 CHECK_VAR(values, FLOAT64_ARRAY_TYPE); | |
292 CHECK_EXPR(CallNew, FLOAT64_ARRAY_TYPE) { | |
293 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
294 CHECK_VAR(stdlib, Bounds::Unbounded()); | |
295 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
296 } | |
297 CHECK_VAR(buffer, Bounds::Unbounded()); | |
298 } | |
299 } | |
300 // return { geometricMean: geometricMean }; | |
301 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { | |
302 CHECK_VAR(geometricMean, FUNC_II2D_TYPE); | |
303 } | |
304 } | |
305 } | |
306 CHECK_TYPES_END | |
307 } | |
308 | |
309 TEST(MissingUseAsm) { | |
310 const char test_function[] = | |
311 "function foo() {\n" | |
312 " function bar() {}\n" | |
313 " return { bar: bar };\n" | |
314 "}\n"; | |
315 v8::V8::Initialize(); | |
316 HandleAndZoneScope handles; | |
317 Zone* zone = handles.main_zone(); | |
318 ZoneVector<ExpressionTypeEntry> types(zone); | |
319 CHECK_EQ("asm: line 1: missing \"use asm\"\n", | |
320 Validate(zone, test_function, &types)); | |
321 } | |
322 | |
323 TEST(WrongUseAsm) { | |
324 const char test_function[] = | |
325 "function foo() {\n" | |
326 " \"use wasm\"\n" | |
327 " function bar() {}\n" | |
328 " return { bar: bar };\n" | |
329 "}\n"; | |
330 v8::V8::Initialize(); | |
331 HandleAndZoneScope handles; | |
332 Zone* zone = handles.main_zone(); | |
333 ZoneVector<ExpressionTypeEntry> types(zone); | |
334 CHECK_EQ("asm: line 1: missing \"use asm\"\n", | |
335 Validate(zone, test_function, &types)); | |
336 } | |
337 | |
338 TEST(MissingReturnExports) { | |
339 const char test_function[] = | |
340 "function foo() {\n" | |
341 " \"use asm\"\n" | |
342 " function bar() {}\n" | |
343 "}\n"; | |
344 v8::V8::Initialize(); | |
345 HandleAndZoneScope handles; | |
346 Zone* zone = handles.main_zone(); | |
347 ZoneVector<ExpressionTypeEntry> types(zone); | |
348 CHECK_EQ("asm: line 2: last statement in module is not a return\n", | |
349 Validate(zone, test_function, &types)); | |
350 } | |
351 | |
352 #define HARNESS_STDLIB() \ | |
353 "var Infinity = stdlib.Infinity; " \ | |
354 "var NaN = stdlib.NaN; " \ | |
355 "var acos = stdlib.Math.acos; " \ | |
356 "var asin = stdlib.Math.asin; " \ | |
357 "var atan = stdlib.Math.atan; " \ | |
358 "var cos = stdlib.Math.cos; " \ | |
359 "var sin = stdlib.Math.sin; " \ | |
360 "var tan = stdlib.Math.tan; " \ | |
361 "var exp = stdlib.Math.exp; " \ | |
362 "var log = stdlib.Math.log; " \ | |
363 "var ceil = stdlib.Math.ceil; " \ | |
364 "var floor = stdlib.Math.floor; " \ | |
365 "var sqrt = stdlib.Math.sqrt; " \ | |
366 "var min = stdlib.Math.min; " \ | |
367 "var max = stdlib.Math.max; " \ | |
368 "var atan2 = stdlib.Math.atan2; " \ | |
369 "var pow = stdlib.Math.pow; " \ | |
370 "var abs = stdlib.Math.abs; " \ | |
371 "var imul = stdlib.Math.imul; " \ | |
372 "var fround = stdlib.Math.fround; " \ | |
373 "var E = stdlib.Math.E; " \ | |
374 "var LN10 = stdlib.Math.LN10; " \ | |
375 "var LN2 = stdlib.Math.LN2; " \ | |
376 "var LOG2E = stdlib.Math.LOG2E; " \ | |
377 "var LOG10E = stdlib.Math.LOG10E; " \ | |
378 "var PI = stdlib.Math.PI; " \ | |
379 "var SQRT1_2 = stdlib.Math.SQRT1_2; " \ | |
380 "var SQRT2 = stdlib.Math.SQRT2; " | |
381 | |
382 #define HARNESS_HEAP() \ | |
383 "var u8 = new stdlib.Uint8Array(buffer); " \ | |
384 "var i8 = new stdlib.Int8Array(buffer); " \ | |
385 "var u16 = new stdlib.Uint16Array(buffer); " \ | |
386 "var i16 = new stdlib.Int16Array(buffer); " \ | |
387 "var u32 = new stdlib.Uint32Array(buffer); " \ | |
388 "var i32 = new stdlib.Int32Array(buffer); " \ | |
389 "var f32 = new stdlib.Float32Array(buffer); " \ | |
390 "var f64 = new stdlib.Float64Array(buffer); " | |
391 | |
392 #define HARNESS_PREAMBLE() \ | |
393 const char test_function[] = \ | |
394 "function Module(stdlib, foreign, buffer) { " \ | |
395 "\"use asm\"; " HARNESS_STDLIB() HARNESS_HEAP() | |
396 | |
397 #define HARNESS_POSTAMBLE() \ | |
398 "return { foo: foo }; " \ | |
399 "} "; | |
400 | |
401 #define CHECK_VAR_MATH_SHORTCUT(name, type) \ | |
402 CHECK_EXPR(Assignment, type) { \ | |
403 CHECK_VAR(name, type); \ | |
404 CHECK_EXPR(Property, type) { \ | |
405 CHECK_EXPR(Property, Bounds::Unbounded()) { \ | |
406 CHECK_VAR(stdlib, Bounds::Unbounded()); \ | |
407 CHECK_EXPR(Literal, Bounds::Unbounded()); \ | |
408 } \ | |
409 CHECK_EXPR(Literal, Bounds::Unbounded()); \ | |
410 } \ | |
411 } | |
412 | |
413 #define CHECK_VAR_SHORTCUT(name, type) \ | |
414 CHECK_EXPR(Assignment, type) { \ | |
415 CHECK_VAR(name, type); \ | |
416 CHECK_EXPR(Property, type) { \ | |
417 CHECK_VAR(stdlib, Bounds::Unbounded()); \ | |
418 CHECK_EXPR(Literal, Bounds::Unbounded()); \ | |
419 } \ | |
420 } | |
421 | |
422 #define CHECK_VAR_NEW_SHORTCUT(name, type) \ | |
423 CHECK_EXPR(Assignment, type) { \ | |
424 CHECK_VAR(name, type); \ | |
425 CHECK_EXPR(CallNew, type) { \ | |
426 CHECK_EXPR(Property, Bounds::Unbounded()) { \ | |
427 CHECK_VAR(stdlib, Bounds::Unbounded()); \ | |
428 CHECK_EXPR(Literal, Bounds::Unbounded()); \ | |
429 } \ | |
430 CHECK_VAR(buffer, Bounds::Unbounded()); \ | |
431 } \ | |
432 } | |
433 | |
434 namespace { | |
435 | |
436 void CheckStdlibShortcuts1(Zone* zone, ZoneVector<ExpressionTypeEntry>& types, | |
437 size_t& index, int& depth, TypeCache& cache) { | |
438 // var exp = stdlib.*; | |
439 CHECK_VAR_SHORTCUT(Infinity, Bounds(cache.kAsmDouble)); | |
440 CHECK_VAR_SHORTCUT(NaN, Bounds(cache.kAsmDouble)); | |
441 // var x = stdlib.Math.x; | |
442 CHECK_VAR_MATH_SHORTCUT(acos, FUNC_D2D_TYPE); | |
443 CHECK_VAR_MATH_SHORTCUT(asin, FUNC_D2D_TYPE); | |
444 CHECK_VAR_MATH_SHORTCUT(atan, FUNC_D2D_TYPE); | |
445 CHECK_VAR_MATH_SHORTCUT(cos, FUNC_D2D_TYPE); | |
446 CHECK_VAR_MATH_SHORTCUT(sin, FUNC_D2D_TYPE); | |
447 CHECK_VAR_MATH_SHORTCUT(tan, FUNC_D2D_TYPE); | |
448 CHECK_VAR_MATH_SHORTCUT(exp, FUNC_D2D_TYPE); | |
449 CHECK_VAR_MATH_SHORTCUT(log, FUNC_D2D_TYPE); | |
450 | |
451 CHECK_VAR_MATH_SHORTCUT(ceil, FUNC_N2N_TYPE); | |
452 CHECK_VAR_MATH_SHORTCUT(floor, FUNC_N2N_TYPE); | |
453 CHECK_VAR_MATH_SHORTCUT(sqrt, FUNC_N2N_TYPE); | |
454 | |
455 CHECK_VAR_MATH_SHORTCUT(min, FUNC_NN2N_TYPE); | |
456 CHECK_VAR_MATH_SHORTCUT(max, FUNC_NN2N_TYPE); | |
457 | |
458 CHECK_VAR_MATH_SHORTCUT(atan2, FUNC_DD2D_TYPE); | |
459 CHECK_VAR_MATH_SHORTCUT(pow, FUNC_DD2D_TYPE); | |
460 | |
461 CHECK_VAR_MATH_SHORTCUT(abs, FUNC_N2N_TYPE); | |
462 CHECK_VAR_MATH_SHORTCUT(imul, FUNC_II2I_TYPE); | |
463 CHECK_VAR_MATH_SHORTCUT(fround, FUNC_N2F_TYPE); | |
464 } | |
465 | |
466 void CheckStdlibShortcuts2(Zone* zone, ZoneVector<ExpressionTypeEntry>& types, | |
467 size_t& index, int& depth, TypeCache& cache) { | |
468 // var exp = stdlib.Math.*; (D * 12) | |
469 CHECK_VAR_MATH_SHORTCUT(E, Bounds(cache.kAsmDouble)); | |
470 CHECK_VAR_MATH_SHORTCUT(LN10, Bounds(cache.kAsmDouble)); | |
471 CHECK_VAR_MATH_SHORTCUT(LN2, Bounds(cache.kAsmDouble)); | |
472 CHECK_VAR_MATH_SHORTCUT(LOG2E, Bounds(cache.kAsmDouble)); | |
473 CHECK_VAR_MATH_SHORTCUT(LOG10E, Bounds(cache.kAsmDouble)); | |
474 CHECK_VAR_MATH_SHORTCUT(PI, Bounds(cache.kAsmDouble)); | |
475 CHECK_VAR_MATH_SHORTCUT(SQRT1_2, Bounds(cache.kAsmDouble)); | |
476 CHECK_VAR_MATH_SHORTCUT(SQRT2, Bounds(cache.kAsmDouble)); | |
477 // var values = new stdlib.*Array(buffer); | |
478 CHECK_VAR_NEW_SHORTCUT(u8, Bounds(cache.kUint8Array)); | |
479 CHECK_VAR_NEW_SHORTCUT(i8, Bounds(cache.kInt8Array)); | |
480 CHECK_VAR_NEW_SHORTCUT(u16, Bounds(cache.kUint16Array)); | |
481 CHECK_VAR_NEW_SHORTCUT(i16, Bounds(cache.kInt16Array)); | |
482 CHECK_VAR_NEW_SHORTCUT(u32, Bounds(cache.kUint32Array)); | |
483 CHECK_VAR_NEW_SHORTCUT(i32, Bounds(cache.kInt32Array)); | |
484 CHECK_VAR_NEW_SHORTCUT(f32, Bounds(cache.kFloat32Array)); | |
485 CHECK_VAR_NEW_SHORTCUT(f64, Bounds(cache.kFloat64Array)); | |
486 } | |
487 | |
488 } // namespace | |
489 | |
490 #define CHECK_FUNC_TYPES_BEGIN(func) \ | |
491 HARNESS_PREAMBLE() \ | |
492 func "\n" HARNESS_POSTAMBLE(); \ | |
493 \ | |
494 v8::V8::Initialize(); \ | |
495 HandleAndZoneScope handles; \ | |
496 Zone* zone = handles.main_zone(); \ | |
497 ZoneVector<ExpressionTypeEntry> types(zone); \ | |
498 CHECK_EQ("", Validate(zone, test_function, &types)); \ | |
499 TypeCache cache; \ | |
500 \ | |
501 CHECK_TYPES_BEGIN { \ | |
502 /* Module. */ \ | |
503 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { | |
504 #define CHECK_FUNC_TYPES_END_1() \ | |
505 /* "use asm"; */ \ | |
506 CHECK_EXPR(Literal, Bounds(Type::String())); \ | |
507 /* stdlib shortcuts. */ \ | |
508 CheckStdlibShortcuts1(zone, types, index, depth, cache); \ | |
509 CheckStdlibShortcuts2(zone, types, index, depth, cache); | |
510 | |
511 #define CHECK_FUNC_TYPES_END_2() \ | |
512 /* return { foo: foo }; */ \ | |
513 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { \ | |
514 CHECK_VAR(foo, FUNC_V_TYPE); \ | |
515 } \ | |
516 } \ | |
517 } \ | |
518 CHECK_TYPES_END | |
519 | |
520 #define CHECK_FUNC_TYPES_END \ | |
521 CHECK_FUNC_TYPES_END_1(); \ | |
522 CHECK_FUNC_TYPES_END_2(); | |
523 | |
524 #define CHECK_FUNC_ERROR(func, message) \ | |
525 HARNESS_PREAMBLE() \ | |
526 func "\n" HARNESS_POSTAMBLE(); \ | |
527 \ | |
528 v8::V8::Initialize(); \ | |
529 HandleAndZoneScope handles; \ | |
530 Zone* zone = handles.main_zone(); \ | |
531 ZoneVector<ExpressionTypeEntry> types(zone); \ | |
532 CHECK_EQ(message, Validate(zone, test_function, &types)); | |
533 | |
534 TEST(BareHarness) { | |
535 CHECK_FUNC_TYPES_BEGIN("function foo() {}") { | |
536 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) {} | |
537 } | |
538 CHECK_FUNC_TYPES_END | |
539 } | |
540 | |
541 TEST(ReturnVoid) { | |
542 CHECK_FUNC_TYPES_BEGIN( | |
543 "function bar() { return; }\n" | |
544 "function foo() { bar(); }") { | |
545 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
546 // return undefined; | |
547 CHECK_EXPR(Literal, Bounds(Type::Undefined())); | |
548 } | |
549 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
550 CHECK_EXPR(Call, Bounds(Type::Undefined())) { | |
551 CHECK_VAR(bar, FUNC_V_TYPE); | |
552 } | |
553 } | |
554 } | |
555 CHECK_FUNC_TYPES_END | |
556 } | |
557 | |
558 TEST(EmptyBody) { | |
559 CHECK_FUNC_TYPES_BEGIN( | |
560 "function bar() { }\n" | |
561 "function foo() { bar(); }") { | |
562 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE); | |
563 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
564 CHECK_EXPR(Call, Bounds(Type::Undefined())) { | |
565 CHECK_VAR(bar, FUNC_V_TYPE); | |
566 } | |
567 } | |
568 } | |
569 CHECK_FUNC_TYPES_END | |
570 } | |
571 | |
572 TEST(DoesNothing) { | |
573 CHECK_FUNC_TYPES_BEGIN( | |
574 "function bar() { var x = 1.0; }\n" | |
575 "function foo() { bar(); }") { | |
576 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
577 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
578 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
579 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
580 } | |
581 } | |
582 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
583 CHECK_EXPR(Call, Bounds(Type::Undefined())) { | |
584 CHECK_VAR(bar, FUNC_V_TYPE); | |
585 } | |
586 } | |
587 } | |
588 CHECK_FUNC_TYPES_END | |
589 } | |
590 | |
591 TEST(ReturnInt32Literal) { | |
592 CHECK_FUNC_TYPES_BEGIN( | |
593 "function bar() { return 1; }\n" | |
594 "function foo() { bar(); }") { | |
595 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
596 // return 1; | |
597 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
598 } | |
599 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
600 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) { | |
601 CHECK_VAR(bar, FUNC_I_TYPE); | |
602 } | |
603 } | |
604 } | |
605 CHECK_FUNC_TYPES_END | |
606 } | |
607 | |
608 TEST(ReturnFloat64Literal) { | |
609 CHECK_FUNC_TYPES_BEGIN( | |
610 "function bar() { return 1.0; }\n" | |
611 "function foo() { bar(); }") { | |
612 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) { | |
613 // return 1.0; | |
614 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
615 } | |
616 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
617 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
618 CHECK_VAR(bar, FUNC_D_TYPE); | |
619 } | |
620 } | |
621 } | |
622 CHECK_FUNC_TYPES_END | |
623 } | |
624 | |
625 TEST(ReturnFloat32Literal) { | |
626 CHECK_FUNC_TYPES_BEGIN( | |
627 "function bar() { return fround(1.0); }\n" | |
628 "function foo() { bar(); }") { | |
629 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) { | |
630 // return fround(1.0); | |
631 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
632 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
633 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
634 } | |
635 } | |
636 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
637 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { CHECK_VAR(bar, FUNC_F_TYPE); } | |
638 } | |
639 } | |
640 CHECK_FUNC_TYPES_END | |
641 } | |
642 | |
643 TEST(ReturnFloat64Var) { | |
644 CHECK_FUNC_TYPES_BEGIN( | |
645 "function bar() { var x = 1.0; return +x; }\n" | |
646 "function foo() { bar(); }") { | |
647 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) { | |
648 // return 1.0; | |
649 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
650 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
651 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
652 } | |
653 // return 1.0; | |
654 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
655 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
656 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
657 } | |
658 } | |
659 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
660 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
661 CHECK_VAR(bar, FUNC_D_TYPE); | |
662 } | |
663 } | |
664 } | |
665 CHECK_FUNC_TYPES_END | |
666 } | |
667 | |
668 TEST(Addition2) { | |
669 CHECK_FUNC_TYPES_BEGIN( | |
670 "function bar() { var x = 1; var y = 2; return (x+y)|0; }\n" | |
671 "function foo() { bar(); }") { | |
672 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
673 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
674 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
675 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
676 } | |
677 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
678 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
679 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
680 } | |
681 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
682 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
683 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
684 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
685 } | |
686 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
687 } | |
688 } | |
689 CHECK_SKIP(); | |
690 } | |
691 CHECK_FUNC_TYPES_END | |
692 } | |
693 | |
694 #define TEST_COMPARE_OP(name, op) \ | |
695 TEST(name) { \ | |
696 CHECK_FUNC_TYPES_BEGIN("function bar() { return (0 " op \ | |
697 " 0)|0; }\n" \ | |
698 "function foo() { bar(); }") { \ | |
699 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { \ | |
700 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { \ | |
701 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { \ | |
702 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \ | |
703 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \ | |
704 } \ | |
705 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \ | |
706 } \ | |
707 } \ | |
708 CHECK_SKIP(); \ | |
709 } \ | |
710 CHECK_FUNC_TYPES_END \ | |
711 } | |
712 | |
713 TEST_COMPARE_OP(EqOperator, "==") | |
714 TEST_COMPARE_OP(LtOperator, "<") | |
715 TEST_COMPARE_OP(LteOperator, "<=") | |
716 TEST_COMPARE_OP(GtOperator, ">") | |
717 TEST_COMPARE_OP(GteOperator, ">=") | |
718 | |
719 TEST(NeqOperator) { | |
720 CHECK_FUNC_TYPES_BEGIN( | |
721 "function bar() { return (0 != 0)|0; }\n" | |
722 "function foo() { bar(); }") { | |
723 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
724 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
725 CHECK_EXPR(UnaryOperation, Bounds(cache.kAsmSigned)) { | |
726 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
727 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
728 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
729 } | |
730 } | |
731 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
732 } | |
733 } | |
734 CHECK_SKIP(); | |
735 } | |
736 CHECK_FUNC_TYPES_END | |
737 } | |
738 | |
739 TEST(NotOperator) { | |
740 CHECK_FUNC_TYPES_BEGIN( | |
741 "function bar() { var x = 0; return (!x)|0; }\n" | |
742 "function foo() { bar(); }") { | |
743 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
744 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
745 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
746 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
747 } | |
748 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
749 CHECK_EXPR(UnaryOperation, Bounds(cache.kAsmSigned)) { | |
750 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
751 } | |
752 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
753 } | |
754 } | |
755 CHECK_SKIP(); | |
756 } | |
757 CHECK_FUNC_TYPES_END | |
758 } | |
759 | |
760 TEST(InvertOperator) { | |
761 CHECK_FUNC_TYPES_BEGIN( | |
762 "function bar() { var x = 0; return (~x)|0; }\n" | |
763 "function foo() { bar(); }") { | |
764 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
765 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
766 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
767 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
768 } | |
769 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
770 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
771 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
772 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
773 } | |
774 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
775 } | |
776 } | |
777 CHECK_SKIP(); | |
778 } | |
779 CHECK_FUNC_TYPES_END | |
780 } | |
781 | |
782 TEST(InvertConversion) { | |
783 CHECK_FUNC_TYPES_BEGIN( | |
784 "function bar() { var x = 0.0; return (~~x)|0; }\n" | |
785 "function foo() { bar(); }") { | |
786 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
787 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
788 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
789 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
790 } | |
791 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
792 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
793 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
794 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
795 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
796 } | |
797 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
798 } | |
799 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
800 } | |
801 } | |
802 CHECK_SKIP(); | |
803 } | |
804 CHECK_FUNC_TYPES_END | |
805 } | |
806 | |
807 TEST(Ternary) { | |
808 CHECK_FUNC_TYPES_BEGIN( | |
809 "function bar() { var x = 1; var y = 1; return (x?y:5)|0; }\n" | |
810 "function foo() { bar(); }") { | |
811 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
812 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
813 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
814 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
815 } | |
816 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
817 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
818 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
819 } | |
820 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
821 CHECK_EXPR(Conditional, Bounds(cache.kAsmInt)) { | |
822 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
823 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
824 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
825 } | |
826 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
827 } | |
828 } | |
829 CHECK_SKIP(); | |
830 } | |
831 CHECK_FUNC_TYPES_END | |
832 } | |
833 | |
834 #define TEST_INT_BIN_OP(name, op) \ | |
835 TEST(name) { \ | |
836 CHECK_FUNC_TYPES_BEGIN("function bar() { var x = 0; return (x " op \ | |
837 " 123)|0; }\n" \ | |
838 "function foo() { bar(); }") { \ | |
839 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { \ | |
840 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { \ | |
841 CHECK_VAR(x, Bounds(cache.kAsmInt)); \ | |
842 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \ | |
843 } \ | |
844 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { \ | |
845 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { \ | |
846 CHECK_VAR(x, Bounds(cache.kAsmInt)); \ | |
847 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \ | |
848 } \ | |
849 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); \ | |
850 } \ | |
851 } \ | |
852 CHECK_SKIP(); \ | |
853 } \ | |
854 CHECK_FUNC_TYPES_END \ | |
855 } | |
856 | |
857 TEST_INT_BIN_OP(AndOperator, "&") | |
858 TEST_INT_BIN_OP(OrOperator, "|") | |
859 TEST_INT_BIN_OP(XorOperator, "^") | |
860 | |
861 TEST(SignedCompare) { | |
862 CHECK_FUNC_TYPES_BEGIN( | |
863 "function bar() { var x = 1; var y = 1; return ((x|0) < (y|0))|0; }\n" | |
864 "function foo() { bar(); }") { | |
865 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
866 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
867 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
868 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
869 } | |
870 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
871 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
872 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
873 } | |
874 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
875 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
876 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
877 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
878 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
879 } | |
880 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
881 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
882 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
883 } | |
884 } | |
885 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
886 } | |
887 } | |
888 CHECK_SKIP(); | |
889 } | |
890 CHECK_FUNC_TYPES_END | |
891 } | |
892 | |
893 TEST(SignedCompareConst) { | |
894 CHECK_FUNC_TYPES_BEGIN( | |
895 "function bar() { var x = 1; var y = 1; return ((x|0) < (1<<31))|0; }\n" | |
896 "function foo() { bar(); }") { | |
897 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
898 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
899 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
900 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
901 } | |
902 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
903 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
904 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
905 } | |
906 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
907 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
908 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
909 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
910 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
911 } | |
912 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
913 } | |
914 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
915 } | |
916 } | |
917 CHECK_SKIP(); | |
918 } | |
919 CHECK_FUNC_TYPES_END | |
920 } | |
921 | |
922 TEST(UnsignedCompare) { | |
923 CHECK_FUNC_TYPES_BEGIN( | |
924 "function bar() { var x = 1; var y = 1; return ((x>>>0) < (y>>>0))|0; }\n" | |
925 "function foo() { bar(); }") { | |
926 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
927 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
928 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
929 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
930 } | |
931 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
932 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
933 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
934 } | |
935 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
936 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
937 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
938 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
939 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
940 } | |
941 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
942 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
943 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
944 } | |
945 } | |
946 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
947 } | |
948 } | |
949 CHECK_SKIP(); | |
950 } | |
951 CHECK_FUNC_TYPES_END | |
952 } | |
953 | |
954 TEST(UnsignedCompareConst0) { | |
955 CHECK_FUNC_TYPES_BEGIN( | |
956 "function bar() { var x = 1; var y = 1; return ((x>>>0) < (0>>>0))|0; }\n" | |
957 "function foo() { bar(); }") { | |
958 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
959 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
960 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
961 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
962 } | |
963 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
964 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
965 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
966 } | |
967 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
968 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
969 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
970 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
971 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
972 } | |
973 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
974 } | |
975 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
976 } | |
977 } | |
978 CHECK_SKIP(); | |
979 } | |
980 CHECK_FUNC_TYPES_END | |
981 } | |
982 | |
983 TEST(UnsignedCompareConst1) { | |
984 CHECK_FUNC_TYPES_BEGIN( | |
985 "function bar() { var x = 1; var y = 1; return ((x>>>0) < " | |
986 "(0xffffffff>>>0))|0; }\n" | |
987 "function foo() { bar(); }") { | |
988 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
989 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
990 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
991 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
992 } | |
993 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
994 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
995 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
996 } | |
997 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
998 CHECK_EXPR(CompareOperation, Bounds(cache.kAsmSigned)) { | |
999 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1000 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1001 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1002 } | |
1003 CHECK_EXPR(Literal, Bounds(cache.kAsmUnsigned)); | |
1004 } | |
1005 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1006 } | |
1007 } | |
1008 CHECK_SKIP(); | |
1009 } | |
1010 CHECK_FUNC_TYPES_END | |
1011 } | |
1012 | |
1013 TEST(UnsignedDivide) { | |
1014 CHECK_FUNC_TYPES_BEGIN( | |
1015 "function bar() { var x = 1; var y = 1; return ((x>>>0) / (y>>>0))|0; }\n" | |
1016 "function foo() { bar(); }") { | |
1017 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
1018 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1019 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1020 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1021 } | |
1022 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1023 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1024 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1025 } | |
1026 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1027 CHECK_EXPR(BinaryOperation, Bounds(Type::None(), Type::Any())) { | |
1028 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1029 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1030 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1031 } | |
1032 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1033 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1034 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1035 } | |
1036 } | |
1037 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1038 } | |
1039 } | |
1040 CHECK_SKIP(); | |
1041 } | |
1042 CHECK_FUNC_TYPES_END | |
1043 } | |
1044 | |
1045 TEST(UnsignedFromFloat64) { | |
1046 CHECK_FUNC_ERROR( | |
1047 "function bar() { var x = 1.0; return (x>>>0)|0; }\n" | |
1048 "function foo() { bar(); }", | |
1049 "asm: line 1: left bitwise operand expected to be an integer\n"); | |
1050 } | |
1051 | |
1052 TEST(AndFloat64) { | |
1053 CHECK_FUNC_ERROR( | |
1054 "function bar() { var x = 1.0; return (x&0)|0; }\n" | |
1055 "function foo() { bar(); }", | |
1056 "asm: line 1: left bitwise operand expected to be an integer\n"); | |
1057 } | |
1058 | |
1059 TEST(TypeMismatchAddInt32Float64) { | |
1060 CHECK_FUNC_ERROR( | |
1061 "function bar() { var x = 1.0; var y = 0; return (x + y)|0; }\n" | |
1062 "function foo() { bar(); }", | |
1063 "asm: line 1: ill-typed arithmetic operation\n"); | |
1064 } | |
1065 | |
1066 TEST(TypeMismatchSubInt32Float64) { | |
1067 CHECK_FUNC_ERROR( | |
1068 "function bar() { var x = 1.0; var y = 0; return (x - y)|0; }\n" | |
1069 "function foo() { bar(); }", | |
1070 "asm: line 1: ill-typed arithmetic operation\n"); | |
1071 } | |
1072 | |
1073 TEST(TypeMismatchDivInt32Float64) { | |
1074 CHECK_FUNC_ERROR( | |
1075 "function bar() { var x = 1.0; var y = 0; return (x / y)|0; }\n" | |
1076 "function foo() { bar(); }", | |
1077 "asm: line 1: ill-typed arithmetic operation\n"); | |
1078 } | |
1079 | |
1080 TEST(TypeMismatchModInt32Float64) { | |
1081 CHECK_FUNC_ERROR( | |
1082 "function bar() { var x = 1.0; var y = 0; return (x % y)|0; }\n" | |
1083 "function foo() { bar(); }", | |
1084 "asm: line 1: ill-typed arithmetic operation\n"); | |
1085 } | |
1086 | |
1087 TEST(ModFloat32) { | |
1088 CHECK_FUNC_ERROR( | |
1089 "function bar() { var x = fround(1.0); return (x % x)|0; }\n" | |
1090 "function foo() { bar(); }", | |
1091 "asm: line 1: ill-typed arithmetic operation\n"); | |
1092 } | |
1093 | |
1094 TEST(TernaryMismatchInt32Float64) { | |
1095 CHECK_FUNC_ERROR( | |
1096 "function bar() { var x = 1; var y = 0.0; return (1 ? x : y)|0; }\n" | |
1097 "function foo() { bar(); }", | |
1098 "asm: line 1: then and else expressions in ? must have the same type " | |
1099 "and be int, float, or double\n"); | |
1100 } | |
1101 | |
1102 TEST(TernaryMismatchIntish) { | |
1103 CHECK_FUNC_ERROR( | |
1104 "function bar() { var x = 1; var y = 0; return (1 ? x + x : y)|0; }\n" | |
1105 "function foo() { bar(); }", | |
1106 "asm: line 1: then and else expressions in ? must have the same type " | |
1107 "and be int, float, or double\n"); | |
1108 } | |
1109 | |
1110 TEST(TernaryMismatchInt32Float32) { | |
1111 CHECK_FUNC_ERROR( | |
1112 "function bar() { var x = 1; var y = 2.0; return (x?fround(y):x)|0; }\n" | |
1113 "function foo() { bar(); }", | |
1114 "asm: line 1: then and else expressions in ? must have the same type " | |
1115 "and be int, float, or double\n"); | |
1116 } | |
1117 | |
1118 TEST(TernaryBadCondition) { | |
1119 CHECK_FUNC_ERROR( | |
1120 "function bar() { var x = 1; var y = 2.0; return (y?x:1)|0; }\n" | |
1121 "function foo() { bar(); }", | |
1122 "asm: line 1: condition must be of type int\n"); | |
1123 } | |
1124 | |
1125 TEST(BadIntishMultiply) { | |
1126 CHECK_FUNC_ERROR( | |
1127 "function bar() { var x = 1; return ((x + x) * 4) | 0; }\n" | |
1128 "function foo() { bar(); }", | |
1129 "asm: line 1: intish not allowed in multiply\n"); | |
1130 } | |
1131 | |
1132 TEST(IntToFloat32) { | |
1133 CHECK_FUNC_ERROR( | |
1134 "function bar() { var x = 1; return fround(x); }\n" | |
1135 "function foo() { bar(); }", | |
1136 "asm: line 1: illegal function argument type\n"); | |
1137 } | |
1138 | |
1139 TEST(Int32ToFloat32) { | |
1140 CHECK_FUNC_TYPES_BEGIN( | |
1141 "function bar() { var x = 1; return fround(x|0); }\n" | |
1142 "function foo() { bar(); }") { | |
1143 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) { | |
1144 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1145 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1146 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1147 } | |
1148 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1149 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1150 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1151 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1152 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1153 } | |
1154 } | |
1155 } | |
1156 CHECK_SKIP(); | |
1157 } | |
1158 CHECK_FUNC_TYPES_END | |
1159 } | |
1160 | |
1161 TEST(Uint32ToFloat32) { | |
1162 CHECK_FUNC_TYPES_BEGIN( | |
1163 "function bar() { var x = 1; return fround(x>>>0); }\n" | |
1164 "function foo() { bar(); }") { | |
1165 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) { | |
1166 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1167 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1168 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1169 } | |
1170 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1171 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1172 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1173 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1174 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1175 } | |
1176 } | |
1177 } | |
1178 CHECK_SKIP(); | |
1179 } | |
1180 CHECK_FUNC_TYPES_END | |
1181 } | |
1182 | |
1183 TEST(Float64ToFloat32) { | |
1184 CHECK_FUNC_TYPES_BEGIN( | |
1185 "function bar() { var x = 1.0; return fround(x); }\n" | |
1186 "function foo() { bar(); }") { | |
1187 CHECK_EXPR(FunctionLiteral, FUNC_F_TYPE) { | |
1188 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
1189 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
1190 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1191 } | |
1192 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1193 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1194 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
1195 } | |
1196 } | |
1197 CHECK_SKIP(); | |
1198 } | |
1199 CHECK_FUNC_TYPES_END | |
1200 } | |
1201 | |
1202 TEST(Int32ToFloat32ToInt32) { | |
1203 CHECK_FUNC_TYPES_BEGIN( | |
1204 "function bar() { var x = 1; return ~~fround(x|0) | 0; }\n" | |
1205 "function foo() { bar(); }") { | |
1206 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
1207 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1208 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1209 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1210 } | |
1211 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1212 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1213 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1214 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1215 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1216 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1217 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1218 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1219 } | |
1220 } | |
1221 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
1222 } | |
1223 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
1224 } | |
1225 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1226 } | |
1227 } | |
1228 CHECK_SKIP(); | |
1229 } | |
1230 CHECK_FUNC_TYPES_END | |
1231 } | |
1232 | |
1233 TEST(Addition4) { | |
1234 CHECK_FUNC_TYPES_BEGIN( | |
1235 "function bar() { var x = 1; var y = 2; return (x+y+x+y)|0; }\n" | |
1236 "function foo() { bar(); }") { | |
1237 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
1238 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1239 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1240 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1241 } | |
1242 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1243 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1244 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1245 } | |
1246 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1247 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
1248 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
1249 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
1250 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1251 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1252 } | |
1253 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1254 } | |
1255 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1256 } | |
1257 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1258 } | |
1259 } | |
1260 CHECK_SKIP(); | |
1261 } | |
1262 CHECK_FUNC_TYPES_END | |
1263 } | |
1264 | |
1265 TEST(Multiplication2) { | |
1266 CHECK_FUNC_ERROR( | |
1267 "function bar() { var x = 1; var y = 2; return (x*y)|0; }\n" | |
1268 "function foo() { bar(); }", | |
1269 "asm: line 1: multiply must be by an integer literal\n"); | |
1270 } | |
1271 | |
1272 TEST(Division4) { | |
1273 CHECK_FUNC_ERROR( | |
1274 "function bar() { var x = 1; var y = 2; return (x/y/x/y)|0; }\n" | |
1275 "function foo() { bar(); }", | |
1276 "asm: line 1: left and right side of integer / or % " | |
1277 "must match and be signed or unsigned\n"); | |
1278 } | |
1279 | |
1280 TEST(ModInt) { | |
1281 CHECK_FUNC_ERROR( | |
1282 "function bar() { var x = 1; var y = 2; return (x%y)|0; }\n" | |
1283 "function foo() { bar(); }", | |
1284 "asm: line 1: left and right side of integer / or % " | |
1285 "must match and be signed or unsigned\n"); | |
1286 } | |
1287 | |
1288 TEST(DivInt) { | |
1289 CHECK_FUNC_ERROR( | |
1290 "function bar() { var x = 1; var y = 2; return (x/y)|0; }\n" | |
1291 "function foo() { bar(); }", | |
1292 "asm: line 1: left and right side of integer / or % " | |
1293 "must match and be signed or unsigned\n"); | |
1294 } | |
1295 | |
1296 TEST(ModIntMismatch) { | |
1297 CHECK_FUNC_ERROR( | |
1298 "function bar() { var x = 1; var y = 2; return ((x|0)%(y>>>0))|0; }\n" | |
1299 "function foo() { bar(); }", | |
1300 "asm: line 1: left and right side of integer / or % " | |
1301 "must match and be signed or unsigned\n"); | |
1302 } | |
1303 | |
1304 TEST(DivIntMismatch) { | |
1305 CHECK_FUNC_ERROR( | |
1306 "function bar() { var x = 1; var y = 2; return ((x|0)/(y>>>0))|0; }\n" | |
1307 "function foo() { bar(); }", | |
1308 "asm: line 1: left and right side of integer / or % " | |
1309 "must match and be signed or unsigned\n"); | |
1310 } | |
1311 | |
1312 TEST(CompareToStringLeft) { | |
1313 CHECK_FUNC_ERROR( | |
1314 "function bar() { var x = 1; return ('hi' > x)|0; }\n" | |
1315 "function foo() { bar(); }", | |
1316 "asm: line 1: left and right side of comparison must match type " | |
1317 "and be signed, unsigned, float, or double\n"); | |
1318 } | |
1319 | |
1320 TEST(CompareToStringRight) { | |
1321 CHECK_FUNC_ERROR( | |
1322 "function bar() { var x = 1; return (x < 'hi')|0; }\n" | |
1323 "function foo() { bar(); }", | |
1324 "asm: line 1: left and right side of comparison must match type " | |
1325 "and be signed, unsigned, float, or double\n"); | |
1326 } | |
1327 | |
1328 TEST(CompareMismatchInt32Float64) { | |
1329 CHECK_FUNC_ERROR( | |
1330 "function bar() { var x = 1; var y = 2.0; return (x < y)|0; }\n" | |
1331 "function foo() { bar(); }", | |
1332 "asm: line 1: left and right side of comparison must match type " | |
1333 "and be signed, unsigned, float, or double\n"); | |
1334 } | |
1335 | |
1336 TEST(CompareMismatchInt32Uint32) { | |
1337 CHECK_FUNC_ERROR( | |
1338 "function bar() { var x = 1; var y = 2; return ((x|0) < (y>>>0))|0; }\n" | |
1339 "function foo() { bar(); }", | |
1340 "asm: line 1: left and right side of comparison must match type " | |
1341 "and be signed, unsigned, float, or double\n"); | |
1342 } | |
1343 | |
1344 TEST(CompareMismatchInt32Float32) { | |
1345 CHECK_FUNC_ERROR( | |
1346 "function bar() { var x = 1; var y = 2.0; return (x < fround(y))|0; }\n" | |
1347 "function foo() { bar(); }", | |
1348 "asm: line 1: left and right side of comparison must match type " | |
1349 "and be signed, unsigned, float, or double\n"); | |
1350 } | |
1351 | |
1352 TEST(FunctionRepeated) { | |
1353 CHECK_FUNC_ERROR( | |
1354 "function foo() { return 0; }\n" | |
1355 "function foo() { return 0; }", | |
1356 "asm: line 2: function repeated in module\n"); | |
1357 } | |
1358 | |
1359 TEST(Float64ToInt32) { | |
1360 CHECK_FUNC_TYPES_BEGIN( | |
1361 "function bar() { var x = 1; var y = 0.0; x = ~~y; }\n" | |
1362 "function foo() { bar(); }") { | |
1363 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1364 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1365 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1366 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1367 } | |
1368 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
1369 CHECK_VAR(y, Bounds(cache.kAsmDouble)); | |
1370 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1371 } | |
1372 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1373 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1374 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1375 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1376 CHECK_VAR(y, Bounds(cache.kAsmDouble)); | |
1377 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
1378 } | |
1379 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
1380 } | |
1381 } | |
1382 } | |
1383 CHECK_SKIP(); | |
1384 } | |
1385 CHECK_FUNC_TYPES_END | |
1386 } | |
1387 | |
1388 TEST(Load1) { | |
1389 CHECK_FUNC_TYPES_BEGIN( | |
1390 "function bar() { var x = 1; var y = i8[x>>0]|0; }\n" | |
1391 "function foo() { bar(); }") { | |
1392 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1393 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1394 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1395 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1396 } | |
1397 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1398 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1399 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1400 CHECK_EXPR(Property, Bounds(cache.kAsmInt)) { | |
1401 CHECK_VAR(i8, Bounds(cache.kInt8Array)); | |
1402 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1403 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1404 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1405 } | |
1406 } | |
1407 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1408 } | |
1409 } | |
1410 } | |
1411 CHECK_SKIP(); | |
1412 } | |
1413 CHECK_FUNC_TYPES_END | |
1414 } | |
1415 | |
1416 TEST(LoadDouble) { | |
1417 CHECK_FUNC_TYPES_BEGIN( | |
1418 "function bar() { var x = 1; var y = 0.0; y = +f64[x>>3]; }\n" | |
1419 "function foo() { bar(); }") { | |
1420 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1421 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1422 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1423 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1424 } | |
1425 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
1426 CHECK_VAR(y, Bounds(cache.kAsmDouble)); | |
1427 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1428 } | |
1429 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
1430 CHECK_VAR(y, Bounds(cache.kAsmDouble)); | |
1431 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
1432 CHECK_EXPR(Property, Bounds(cache.kAsmDouble)) { | |
1433 CHECK_VAR(f64, Bounds(cache.kFloat64Array)); | |
1434 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1435 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1436 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1437 } | |
1438 } | |
1439 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1440 } | |
1441 } | |
1442 } | |
1443 CHECK_SKIP(); | |
1444 } | |
1445 CHECK_FUNC_TYPES_END | |
1446 } | |
1447 | |
1448 TEST(Store1) { | |
1449 CHECK_FUNC_TYPES_BEGIN( | |
1450 "function bar() { var x = 1; i8[x>>0] = 0; }\n" | |
1451 "function foo() { bar(); }") { | |
1452 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1453 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1454 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1455 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1456 } | |
1457 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1458 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
1459 CHECK_VAR(i8, Bounds(cache.kInt8Array)); | |
1460 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1461 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1462 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1463 } | |
1464 } | |
1465 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1466 } | |
1467 } | |
1468 CHECK_SKIP(); | |
1469 } | |
1470 CHECK_FUNC_TYPES_END | |
1471 } | |
1472 | |
1473 TEST(StoreFloat) { | |
1474 CHECK_FUNC_TYPES_BEGIN( | |
1475 "function bar() { var x = fround(1.0); " | |
1476 "f32[0] = fround(x + fround(1.0)); }\n" | |
1477 "function foo() { bar(); }") { | |
1478 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1479 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
1480 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
1481 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1482 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1483 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1484 } | |
1485 } | |
1486 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
1487 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
1488 CHECK_VAR(f32, Bounds(cache.kFloat32Array)); | |
1489 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1490 } | |
1491 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1492 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1493 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmFloat)) { | |
1494 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
1495 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1496 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1497 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1498 } | |
1499 } | |
1500 } | |
1501 } | |
1502 } | |
1503 CHECK_SKIP(); | |
1504 } | |
1505 CHECK_FUNC_TYPES_END | |
1506 } | |
1507 | |
1508 TEST(StoreIntish) { | |
1509 CHECK_FUNC_TYPES_BEGIN( | |
1510 "function bar() { var x = 1; var y = 1; i32[0] = x + y; }\n" | |
1511 "function foo() { bar(); }") { | |
1512 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1513 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1514 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1515 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1516 } | |
1517 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1518 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1519 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1520 } | |
1521 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1522 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
1523 CHECK_VAR(i32, Bounds(cache.kInt32Array)); | |
1524 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1525 } | |
1526 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
1527 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1528 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1529 } | |
1530 } | |
1531 } | |
1532 CHECK_SKIP(); | |
1533 } | |
1534 CHECK_FUNC_TYPES_END | |
1535 } | |
1536 | |
1537 TEST(StoreFloatish) { | |
1538 CHECK_FUNC_TYPES_BEGIN( | |
1539 "function bar() { " | |
1540 "var x = fround(1.0); " | |
1541 "var y = fround(1.0); f32[0] = x + y; }\n" | |
1542 "function foo() { bar(); }") { | |
1543 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1544 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
1545 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
1546 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1547 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1548 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1549 } | |
1550 } | |
1551 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
1552 CHECK_VAR(y, Bounds(cache.kAsmFloat)); | |
1553 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
1554 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
1555 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
1556 } | |
1557 } | |
1558 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
1559 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
1560 CHECK_VAR(f32, Bounds(cache.kFloat32Array)); | |
1561 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1562 } | |
1563 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmFloat)) { | |
1564 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
1565 CHECK_VAR(y, Bounds(cache.kAsmFloat)); | |
1566 } | |
1567 } | |
1568 } | |
1569 CHECK_SKIP(); | |
1570 } | |
1571 CHECK_FUNC_TYPES_END | |
1572 } | |
1573 | |
1574 TEST(Load1Constant) { | |
1575 CHECK_FUNC_TYPES_BEGIN( | |
1576 "function bar() { var x = 1; var y = i8[5]|0; }\n" | |
1577 "function foo() { bar(); }") { | |
1578 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1579 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1580 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1581 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1582 } | |
1583 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1584 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1585 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1586 CHECK_EXPR(Property, Bounds(cache.kAsmInt)) { | |
1587 CHECK_VAR(i8, Bounds(cache.kInt8Array)); | |
1588 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1589 } | |
1590 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1591 } | |
1592 } | |
1593 } | |
1594 CHECK_SKIP(); | |
1595 } | |
1596 CHECK_FUNC_TYPES_END | |
1597 } | |
1598 | |
1599 TEST(FunctionTables) { | |
1600 CHECK_FUNC_TYPES_BEGIN( | |
1601 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n" | |
1602 "function func2(x) { x = x | 0; return (x * 25) | 0; }\n" | |
1603 "var table1 = [func1, func2];\n" | |
1604 "function bar(x, y) { x = x | 0; y = y | 0;\n" | |
1605 " return table1[x & 1](y)|0; }\n" | |
1606 "function foo() { bar(1, 2); }") { | |
1607 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) { | |
1608 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1609 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1610 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1611 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1612 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1613 } | |
1614 } | |
1615 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1616 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
1617 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1618 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1619 } | |
1620 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1621 } | |
1622 } | |
1623 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) { | |
1624 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1625 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1626 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1627 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1628 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1629 } | |
1630 } | |
1631 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1632 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmInt)) { | |
1633 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1634 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1635 } | |
1636 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1637 } | |
1638 } | |
1639 CHECK_EXPR(FunctionLiteral, FUNC_II2I_TYPE) { | |
1640 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1641 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1642 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1643 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1644 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1645 } | |
1646 } | |
1647 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1648 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1649 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1650 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1651 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1652 } | |
1653 } | |
1654 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1655 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) { | |
1656 CHECK_EXPR(Property, FUNC_I2I_TYPE) { | |
1657 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE); | |
1658 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1659 // TODO(bradnelson): revert this | |
1660 // CHECK_VAR(x, Bounds(cache.kAsmSigned)); | |
1661 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1662 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1663 } | |
1664 } | |
1665 CHECK_VAR(y, Bounds(cache.kAsmInt)); | |
1666 } | |
1667 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1668 } | |
1669 } | |
1670 CHECK_SKIP(); | |
1671 } | |
1672 CHECK_FUNC_TYPES_END_1(); | |
1673 CHECK_EXPR(Assignment, FUNC_I2I_ARRAY_TYPE) { | |
1674 CHECK_VAR(table1, FUNC_I2I_ARRAY_TYPE); | |
1675 CHECK_EXPR(ArrayLiteral, FUNC_I2I_ARRAY_TYPE) { | |
1676 CHECK_VAR(func1, FUNC_I2I_TYPE); | |
1677 CHECK_VAR(func2, FUNC_I2I_TYPE); | |
1678 } | |
1679 } | |
1680 CHECK_FUNC_TYPES_END_2(); | |
1681 } | |
1682 | |
1683 TEST(BadFunctionTable) { | |
1684 CHECK_FUNC_ERROR( | |
1685 "function func1(x) { x = x | 0; return (x * 5) | 0; }\n" | |
1686 "var table1 = [func1, 1];\n" | |
1687 "function bar(x, y) { x = x | 0; y = y | 0;\n" | |
1688 " return table1[x & 1](y)|0; }\n" | |
1689 "function foo() { bar(1, 2); }", | |
1690 "asm: line 2: array component expected to be a function\n"); | |
1691 } | |
1692 | |
1693 TEST(MissingParameterTypes) { | |
1694 CHECK_FUNC_ERROR( | |
1695 "function bar(x) { var y = 1; }\n" | |
1696 "function foo() { bar(2); }", | |
1697 "asm: line 1: missing parameter type annotations\n"); | |
1698 } | |
1699 | |
1700 TEST(InvalidTypeAnnotationBinaryOpDiv) { | |
1701 CHECK_FUNC_ERROR( | |
1702 "function bar(x) { x = x / 4; }\n" | |
1703 "function foo() { bar(2); }", | |
1704 "asm: line 1: invalid type annotation on binary op\n"); | |
1705 } | |
1706 | |
1707 TEST(InvalidTypeAnnotationBinaryOpMul) { | |
1708 CHECK_FUNC_ERROR( | |
1709 "function bar(x) { x = x * 4.0; }\n" | |
1710 "function foo() { bar(2); }", | |
1711 "asm: line 1: invalid type annotation on binary op\n"); | |
1712 } | |
1713 | |
1714 TEST(InvalidArgumentCount) { | |
1715 CHECK_FUNC_ERROR( | |
1716 "function bar(x) { return fround(4, 5); }\n" | |
1717 "function foo() { bar(); }", | |
1718 "asm: line 1: invalid argument count calling function\n"); | |
1719 } | |
1720 | |
1721 TEST(InvalidTypeAnnotationArity) { | |
1722 CHECK_FUNC_ERROR( | |
1723 "function bar(x) { x = max(x); }\n" | |
1724 "function foo() { bar(3); }", | |
1725 "asm: line 1: only fround allowed on expression annotations\n"); | |
1726 } | |
1727 | |
1728 TEST(InvalidTypeAnnotationOnlyFround) { | |
1729 CHECK_FUNC_ERROR( | |
1730 "function bar(x) { x = sin(x); }\n" | |
1731 "function foo() { bar(3); }", | |
1732 "asm: line 1: only fround allowed on expression annotations\n"); | |
1733 } | |
1734 | |
1735 TEST(InvalidTypeAnnotation) { | |
1736 CHECK_FUNC_ERROR( | |
1737 "function bar(x) { x = (x+x)(x); }\n" | |
1738 "function foo() { bar(3); }", | |
1739 "asm: line 1: invalid type annotation\n"); | |
1740 } | |
1741 | |
1742 TEST(WithStatement) { | |
1743 CHECK_FUNC_ERROR( | |
1744 "function bar() { var x = 0; with (x) { x = x + 1; } }\n" | |
1745 "function foo() { bar(); }", | |
1746 "asm: line 1: bad with statement\n"); | |
1747 } | |
1748 | |
1749 TEST(NestedFunction) { | |
1750 CHECK_FUNC_ERROR( | |
1751 "function bar() { function x() { return 1; } }\n" | |
1752 "function foo() { bar(); }", | |
1753 "asm: line 1: function declared inside another\n"); | |
1754 } | |
1755 | |
1756 TEST(UnboundVariable) { | |
1757 CHECK_FUNC_ERROR( | |
1758 "function bar() { var x = y; }\n" | |
1759 "function foo() { bar(); }", | |
1760 "asm: line 1: unbound variable\n"); | |
1761 } | |
1762 | |
1763 TEST(EqStrict) { | |
1764 CHECK_FUNC_ERROR( | |
1765 "function bar() { return (0 === 0)|0; }\n" | |
1766 "function foo() { bar(); }", | |
1767 "asm: line 1: illegal comparison operator\n"); | |
1768 } | |
1769 | |
1770 TEST(NeStrict) { | |
1771 CHECK_FUNC_ERROR( | |
1772 "function bar() { return (0 !== 0)|0; }\n" | |
1773 "function foo() { bar(); }", | |
1774 "asm: line 1: illegal comparison operator\n"); | |
1775 } | |
1776 | |
1777 TEST(InstanceOf) { | |
1778 CHECK_FUNC_ERROR( | |
1779 "function bar() { return (0 instanceof 0)|0; }\n" | |
1780 "function foo() { bar(); }", | |
1781 "asm: line 1: illegal comparison operator\n"); | |
1782 } | |
1783 | |
1784 TEST(InOperator) { | |
1785 CHECK_FUNC_ERROR( | |
1786 "function bar() { return (0 in 0)|0; }\n" | |
1787 "function foo() { bar(); }", | |
1788 "asm: line 1: illegal comparison operator\n"); | |
1789 } | |
1790 | |
1791 TEST(LogicalAndOperator) { | |
1792 CHECK_FUNC_ERROR( | |
1793 "function bar() { return (0 && 0)|0; }\n" | |
1794 "function foo() { bar(); }", | |
1795 "asm: line 1: illegal logical operator\n"); | |
1796 } | |
1797 | |
1798 TEST(LogicalOrOperator) { | |
1799 CHECK_FUNC_ERROR( | |
1800 "function bar() { return (0 || 0)|0; }\n" | |
1801 "function foo() { bar(); }", | |
1802 "asm: line 1: illegal logical operator\n"); | |
1803 } | |
1804 | |
1805 TEST(BitOrDouble) { | |
1806 CHECK_FUNC_ERROR( | |
1807 "function bar() { var x = 1.0; return x | 0; }\n" | |
1808 "function foo() { bar(); }", | |
1809 "asm: line 1: intish required\n"); | |
1810 } | |
1811 | |
1812 TEST(BadLiteral) { | |
1813 CHECK_FUNC_ERROR( | |
1814 "function bar() { return true | 0; }\n" | |
1815 "function foo() { bar(); }", | |
1816 "asm: line 1: illegal literal\n"); | |
1817 } | |
1818 | |
1819 TEST(MismatchedReturnTypeLiteral) { | |
1820 CHECK_FUNC_ERROR( | |
1821 "function bar() { if(1) { return 1; } return 1.0; }\n" | |
1822 "function foo() { bar(); }", | |
1823 "asm: line 1: return type does not match function signature\n"); | |
1824 } | |
1825 | |
1826 TEST(MismatchedReturnTypeExpression) { | |
1827 CHECK_FUNC_ERROR( | |
1828 "function bar() {\n" | |
1829 " var x = 1; var y = 1.0; if(1) { return x; } return +y; }\n" | |
1830 "function foo() { bar(); }", | |
1831 "asm: line 2: return type does not match function signature\n"); | |
1832 } | |
1833 | |
1834 TEST(AssignToFloatishToF64) { | |
1835 CHECK_FUNC_ERROR( | |
1836 "function bar() { var v = fround(1.0); f64[0] = v + fround(1.0); }\n" | |
1837 "function foo() { bar(); }", | |
1838 "asm: line 1: floatish assignment to double array\n"); | |
1839 } | |
1840 | |
1841 TEST(ForeignFunction) { | |
1842 CHECK_FUNC_TYPES_BEGIN( | |
1843 "var baz = foreign.baz;\n" | |
1844 "function bar() { return baz(1, 2)|0; }\n" | |
1845 "function foo() { bar(); }") { | |
1846 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
1847 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
1848 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) { | |
1849 CHECK_VAR(baz, FUNC_FOREIGN_TYPE); | |
1850 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1851 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1852 } | |
1853 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1854 } | |
1855 } | |
1856 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1857 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) { | |
1858 CHECK_VAR(bar, FUNC_I_TYPE); | |
1859 } | |
1860 } | |
1861 } | |
1862 CHECK_FUNC_TYPES_END_1() | |
1863 CHECK_EXPR(Assignment, Bounds(FUNC_FOREIGN_TYPE)) { | |
1864 CHECK_VAR(baz, Bounds(FUNC_FOREIGN_TYPE)); | |
1865 CHECK_EXPR(Property, Bounds(FUNC_FOREIGN_TYPE)) { | |
1866 CHECK_VAR(foreign, Bounds::Unbounded()); | |
1867 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
1868 } | |
1869 } | |
1870 CHECK_FUNC_TYPES_END_2() | |
1871 } | |
1872 | |
1873 TEST(ByteArray) { | |
1874 // Forbidden by asm.js spec, present in embenchen. | |
1875 CHECK_FUNC_TYPES_BEGIN( | |
1876 "function bar() { var x = 0; i8[x] = 2; }\n" | |
1877 "function foo() { bar(); }") { | |
1878 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1879 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1880 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1881 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1882 } | |
1883 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1884 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
1885 CHECK_VAR(i8, Bounds(cache.kInt8Array)); | |
1886 CHECK_VAR(x, Bounds(cache.kAsmUnsigned)); | |
1887 } | |
1888 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1889 } | |
1890 } | |
1891 CHECK_SKIP(); | |
1892 } | |
1893 CHECK_FUNC_TYPES_END | |
1894 } | |
1895 | |
1896 TEST(BadExports) { | |
1897 HARNESS_PREAMBLE() | |
1898 "function foo() {};\n" | |
1899 "return {foo: foo, bar: 1};" | |
1900 "}\n"; | |
1901 | |
1902 v8::V8::Initialize(); | |
1903 HandleAndZoneScope handles; | |
1904 Zone* zone = handles.main_zone(); | |
1905 ZoneVector<ExpressionTypeEntry> types(zone); | |
1906 CHECK_EQ("asm: line 2: non-function in function table\n", | |
1907 Validate(zone, test_function, &types)); | |
1908 } | |
1909 | |
1910 TEST(NestedHeapAssignment) { | |
1911 CHECK_FUNC_ERROR( | |
1912 "function bar() { var x = 0; i16[x = 1] = 2; }\n" | |
1913 "function foo() { bar(); }", | |
1914 "asm: line 1: expected >> in heap access\n"); | |
1915 } | |
1916 | |
1917 TEST(BadOperatorHeapAssignment) { | |
1918 CHECK_FUNC_ERROR( | |
1919 "function bar() { var x = 0; i16[x & 1] = 2; }\n" | |
1920 "function foo() { bar(); }", | |
1921 "asm: line 1: expected >> in heap access\n"); | |
1922 } | |
1923 | |
1924 TEST(BadArrayAssignment) { | |
1925 CHECK_FUNC_ERROR( | |
1926 "function bar() { i8[0] = 0.0; }\n" | |
1927 "function foo() { bar(); }", | |
1928 "asm: line 1: illegal type in assignment\n"); | |
1929 } | |
1930 | |
1931 TEST(BadStandardFunctionCallOutside) { | |
1932 CHECK_FUNC_ERROR( | |
1933 "var s0 = sin(0);\n" | |
1934 "function bar() { }\n" | |
1935 "function foo() { bar(); }", | |
1936 "asm: line 1: illegal variable reference in module body\n"); | |
1937 } | |
1938 | |
1939 TEST(BadFunctionCallOutside) { | |
1940 CHECK_FUNC_ERROR( | |
1941 "function bar() { return 0.0; }\n" | |
1942 "var s0 = bar(0);\n" | |
1943 "function foo() { bar(); }", | |
1944 "asm: line 2: illegal variable reference in module body\n"); | |
1945 } | |
1946 | |
1947 TEST(UnaryPlusOnIntForbidden) { | |
1948 CHECK_FUNC_ERROR( | |
1949 "function bar() { var x = 1; return +x; }\n" | |
1950 "function foo() { bar(); }", | |
1951 "asm: line 1: " | |
1952 "unary + only allowed on signed, unsigned, float?, or double?\n"); | |
1953 } | |
1954 | |
1955 TEST(MultiplyNon1ConvertForbidden) { | |
1956 CHECK_FUNC_ERROR( | |
1957 "function bar() { var x = 0.0; return x * 2.0; }\n" | |
1958 "function foo() { bar(); }", | |
1959 "asm: line 1: invalid type annotation on binary op\n"); | |
1960 } | |
1961 | |
1962 TEST(NestedVariableAssignment) { | |
1963 CHECK_FUNC_TYPES_BEGIN( | |
1964 "function bar() { var x = 0; x = x = 4; }\n" | |
1965 "function foo() { bar(); }") { | |
1966 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1967 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1968 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1969 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1970 } | |
1971 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1972 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1973 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1974 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1975 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1976 } | |
1977 } | |
1978 } | |
1979 CHECK_SKIP(); | |
1980 } | |
1981 CHECK_FUNC_TYPES_END | |
1982 } | |
1983 | |
1984 TEST(NestedAssignmentInHeap) { | |
1985 CHECK_FUNC_TYPES_BEGIN( | |
1986 "function bar() { var x = 0; i8[(x = 1) >> 0] = 2; }\n" | |
1987 "function foo() { bar(); }") { | |
1988 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
1989 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1990 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1991 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
1992 } | |
1993 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1994 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
1995 CHECK_VAR(i8, Bounds(cache.kInt8Array)); | |
1996 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmUnsigned)) { | |
1997 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
1998 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
1999 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2000 } | |
2001 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2002 } | |
2003 } | |
2004 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2005 } | |
2006 } | |
2007 CHECK_SKIP(); | |
2008 } | |
2009 CHECK_FUNC_TYPES_END | |
2010 } | |
2011 | |
2012 TEST(NegativeDouble) { | |
2013 CHECK_FUNC_TYPES_BEGIN( | |
2014 "function bar() { var x = -123.2; }\n" | |
2015 "function foo() { bar(); }") { | |
2016 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
2017 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2018 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2019 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2020 } | |
2021 } | |
2022 CHECK_SKIP(); | |
2023 } | |
2024 CHECK_FUNC_TYPES_END | |
2025 } | |
2026 | |
2027 TEST(NegativeInteger) { | |
2028 CHECK_FUNC_TYPES_BEGIN( | |
2029 "function bar() { var x = -123; }\n" | |
2030 "function foo() { bar(); }") { | |
2031 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
2032 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
2033 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
2034 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
2035 } | |
2036 } | |
2037 CHECK_SKIP(); | |
2038 } | |
2039 CHECK_FUNC_TYPES_END | |
2040 } | |
2041 | |
2042 TEST(AbsFunction) { | |
2043 CHECK_FUNC_TYPES_BEGIN( | |
2044 "function bar() { var x = -123.0; x = abs(x); }\n" | |
2045 "function foo() { bar(); }") { | |
2046 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
2047 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2048 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2049 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2050 } | |
2051 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2052 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2053 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
2054 CHECK_VAR(abs, FUNC_N2N_TYPE); | |
2055 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2056 } | |
2057 } | |
2058 } | |
2059 CHECK_SKIP(); | |
2060 } | |
2061 CHECK_FUNC_TYPES_END | |
2062 } | |
2063 | |
2064 TEST(CeilFloat) { | |
2065 CHECK_FUNC_TYPES_BEGIN( | |
2066 "function bar() { var x = fround(3.1); x = ceil(x); }\n" | |
2067 "function foo() { bar(); }") { | |
2068 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
2069 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
2070 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
2071 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
2072 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
2073 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2074 } | |
2075 } | |
2076 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
2077 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
2078 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
2079 CHECK_VAR(ceil, FUNC_N2N_TYPE); | |
2080 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
2081 } | |
2082 } | |
2083 } | |
2084 CHECK_SKIP(); | |
2085 } | |
2086 CHECK_FUNC_TYPES_END | |
2087 } | |
2088 | |
2089 TEST(FloatReturnAsDouble) { | |
2090 CHECK_FUNC_TYPES_BEGIN( | |
2091 "function bar() { var x = fround(3.1); return +fround(x); }\n" | |
2092 "function foo() { bar(); }") { | |
2093 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) { | |
2094 CHECK_EXPR(Assignment, Bounds(cache.kAsmFloat)) { | |
2095 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
2096 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
2097 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
2098 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2099 } | |
2100 } | |
2101 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
2102 CHECK_EXPR(Call, Bounds(cache.kAsmFloat)) { | |
2103 CHECK_VAR(fround, FUNC_N2F_TYPE); | |
2104 CHECK_VAR(x, Bounds(cache.kAsmFloat)); | |
2105 } | |
2106 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2107 } | |
2108 } | |
2109 CHECK_SKIP(); | |
2110 } | |
2111 CHECK_FUNC_TYPES_END | |
2112 } | |
2113 | |
2114 TEST(TypeConsistency) { | |
2115 v8::V8::Initialize(); | |
2116 TypeCache cache; | |
2117 // Check the consistency of each of the main Asm.js types. | |
2118 CHECK(cache.kAsmFixnum->Is(cache.kAsmFixnum)); | |
2119 CHECK(cache.kAsmFixnum->Is(cache.kAsmSigned)); | |
2120 CHECK(cache.kAsmFixnum->Is(cache.kAsmUnsigned)); | |
2121 CHECK(cache.kAsmFixnum->Is(cache.kAsmInt)); | |
2122 CHECK(!cache.kAsmFixnum->Is(cache.kAsmFloat)); | |
2123 CHECK(!cache.kAsmFixnum->Is(cache.kAsmDouble)); | |
2124 | |
2125 CHECK(cache.kAsmSigned->Is(cache.kAsmSigned)); | |
2126 CHECK(cache.kAsmSigned->Is(cache.kAsmInt)); | |
2127 CHECK(!cache.kAsmSigned->Is(cache.kAsmFixnum)); | |
2128 CHECK(!cache.kAsmSigned->Is(cache.kAsmUnsigned)); | |
2129 CHECK(!cache.kAsmSigned->Is(cache.kAsmFloat)); | |
2130 CHECK(!cache.kAsmSigned->Is(cache.kAsmDouble)); | |
2131 | |
2132 CHECK(cache.kAsmUnsigned->Is(cache.kAsmUnsigned)); | |
2133 CHECK(cache.kAsmUnsigned->Is(cache.kAsmInt)); | |
2134 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmSigned)); | |
2135 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmFixnum)); | |
2136 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmFloat)); | |
2137 CHECK(!cache.kAsmUnsigned->Is(cache.kAsmDouble)); | |
2138 | |
2139 CHECK(cache.kAsmInt->Is(cache.kAsmInt)); | |
2140 CHECK(!cache.kAsmInt->Is(cache.kAsmUnsigned)); | |
2141 CHECK(!cache.kAsmInt->Is(cache.kAsmSigned)); | |
2142 CHECK(!cache.kAsmInt->Is(cache.kAsmFixnum)); | |
2143 CHECK(!cache.kAsmInt->Is(cache.kAsmFloat)); | |
2144 CHECK(!cache.kAsmInt->Is(cache.kAsmDouble)); | |
2145 | |
2146 CHECK(cache.kAsmFloat->Is(cache.kAsmFloat)); | |
2147 CHECK(!cache.kAsmFloat->Is(cache.kAsmInt)); | |
2148 CHECK(!cache.kAsmFloat->Is(cache.kAsmUnsigned)); | |
2149 CHECK(!cache.kAsmFloat->Is(cache.kAsmSigned)); | |
2150 CHECK(!cache.kAsmFloat->Is(cache.kAsmFixnum)); | |
2151 CHECK(!cache.kAsmFloat->Is(cache.kAsmDouble)); | |
2152 | |
2153 CHECK(cache.kAsmDouble->Is(cache.kAsmDouble)); | |
2154 CHECK(!cache.kAsmDouble->Is(cache.kAsmInt)); | |
2155 CHECK(!cache.kAsmDouble->Is(cache.kAsmUnsigned)); | |
2156 CHECK(!cache.kAsmDouble->Is(cache.kAsmSigned)); | |
2157 CHECK(!cache.kAsmDouble->Is(cache.kAsmFixnum)); | |
2158 CHECK(!cache.kAsmDouble->Is(cache.kAsmFloat)); | |
2159 } | |
2160 | |
2161 TEST(SwitchTest) { | |
2162 CHECK_FUNC_TYPES_BEGIN( | |
2163 "function switcher(x) {\n" | |
2164 " x = x|0;\n" | |
2165 " switch (x|0) {\n" | |
2166 " case 1: return 23;\n" | |
2167 " case 2: return 43;\n" | |
2168 " default: return 66;\n" | |
2169 " }\n" | |
2170 " return 0;\n" | |
2171 "}\n" | |
2172 "function foo() { switcher(1); }") { | |
2173 CHECK_EXPR(FunctionLiteral, FUNC_I2I_TYPE) { | |
2174 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
2175 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
2176 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
2177 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
2178 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2179 } | |
2180 } | |
2181 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
2182 CHECK_VAR(.switch_tag, Bounds(cache.kAsmInt)); | |
2183 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
2184 CHECK_VAR(x, Bounds(cache.kAsmInt)); | |
2185 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2186 } | |
2187 } | |
2188 CHECK_EXPR(Literal, Bounds(Type::Undefined())); | |
2189 CHECK_VAR(.switch_tag, Bounds(cache.kAsmSigned)); | |
2190 // case 1: return 23; | |
2191 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2192 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
2193 // case 2: return 43; | |
2194 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2195 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
2196 // default: return 66; | |
2197 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
2198 // return 0; | |
2199 CHECK_EXPR(Literal, Bounds(cache.kAsmSigned)); | |
2200 } | |
2201 CHECK_SKIP(); | |
2202 } | |
2203 CHECK_FUNC_TYPES_END | |
2204 } | |
2205 | |
2206 TEST(BadSwitchRange) { | |
2207 CHECK_FUNC_ERROR( | |
2208 "function bar() { switch (1) { case -1: case 0x7fffffff: } }\n" | |
2209 "function foo() { bar(); }", | |
2210 "asm: line 1: case range too large\n"); | |
2211 } | |
2212 | |
2213 TEST(DuplicateSwitchCase) { | |
2214 CHECK_FUNC_ERROR( | |
2215 "function bar() { switch (1) { case 0: case 0: } }\n" | |
2216 "function foo() { bar(); }", | |
2217 "asm: line 1: duplicate case value\n"); | |
2218 } | |
2219 | |
2220 TEST(BadSwitchOrder) { | |
2221 CHECK_FUNC_ERROR( | |
2222 "function bar() { switch (1) { default: case 0: } }\n" | |
2223 "function foo() { bar(); }", | |
2224 "asm: line 1: default case out of order\n"); | |
2225 } | |
2226 | |
2227 TEST(BadForeignCall) { | |
2228 const char test_function[] = | |
2229 "function TestModule(stdlib, foreign, buffer) {\n" | |
2230 " \"use asm\";\n" | |
2231 " var ffunc = foreign.foo;\n" | |
2232 " function test1() { var x = 0; ffunc(x); }\n" | |
2233 " return { testFunc1: test1 };\n" | |
2234 "}\n"; | |
2235 v8::V8::Initialize(); | |
2236 HandleAndZoneScope handles; | |
2237 Zone* zone = handles.main_zone(); | |
2238 ZoneVector<ExpressionTypeEntry> types(zone); | |
2239 CHECK_EQ( | |
2240 "asm: line 4: foreign call argument expected to be int, double, or " | |
2241 "fixnum\n", | |
2242 Validate(zone, test_function, &types)); | |
2243 } | |
2244 | |
2245 TEST(BadImports) { | |
2246 const char test_function[] = | |
2247 "function TestModule(stdlib, foreign, buffer) {\n" | |
2248 " \"use asm\";\n" | |
2249 " var fint = (foreign.bar | 0) | 0;\n" | |
2250 " function test1() {}\n" | |
2251 " return { testFunc1: test1 };\n" | |
2252 "}\n"; | |
2253 v8::V8::Initialize(); | |
2254 HandleAndZoneScope handles; | |
2255 Zone* zone = handles.main_zone(); | |
2256 ZoneVector<ExpressionTypeEntry> types(zone); | |
2257 CHECK_EQ("asm: line 3: illegal computation inside module body\n", | |
2258 Validate(zone, test_function, &types)); | |
2259 } | |
2260 | |
2261 TEST(BadVariableReference) { | |
2262 const char test_function[] = | |
2263 "function TestModule(stdlib, foreign, buffer) {\n" | |
2264 " \"use asm\";\n" | |
2265 " var x = 0;\n" | |
2266 " var y = x;\n" | |
2267 " function test1() {}\n" | |
2268 " return { testFunc1: test1 };\n" | |
2269 "}\n"; | |
2270 v8::V8::Initialize(); | |
2271 HandleAndZoneScope handles; | |
2272 Zone* zone = handles.main_zone(); | |
2273 ZoneVector<ExpressionTypeEntry> types(zone); | |
2274 CHECK_EQ("asm: line 4: illegal variable reference in module body\n", | |
2275 Validate(zone, test_function, &types)); | |
2276 } | |
2277 | |
2278 TEST(BadForeignVariableReferenceValueOr) { | |
2279 const char test_function[] = | |
2280 "function TestModule(stdlib, foreign, buffer) {\n" | |
2281 " \"use asm\";\n" | |
2282 " var fint = foreign.bar | 1;\n" | |
2283 "}\n"; | |
2284 v8::V8::Initialize(); | |
2285 HandleAndZoneScope handles; | |
2286 Zone* zone = handles.main_zone(); | |
2287 ZoneVector<ExpressionTypeEntry> types(zone); | |
2288 CHECK_EQ("asm: line 3: illegal integer annotation value\n", | |
2289 Validate(zone, test_function, &types)); | |
2290 } | |
2291 | |
2292 TEST(BadForeignVariableReferenceValueOrDot) { | |
2293 const char test_function[] = | |
2294 "function TestModule(stdlib, foreign, buffer) {\n" | |
2295 " \"use asm\";\n" | |
2296 " var fint = foreign.bar | 1.0;\n" | |
2297 "}\n"; | |
2298 v8::V8::Initialize(); | |
2299 HandleAndZoneScope handles; | |
2300 Zone* zone = handles.main_zone(); | |
2301 ZoneVector<ExpressionTypeEntry> types(zone); | |
2302 CHECK_EQ("asm: line 3: illegal integer annotation value\n", | |
2303 Validate(zone, test_function, &types)); | |
2304 } | |
2305 | |
2306 TEST(BadForeignVariableReferenceValueMul) { | |
2307 const char test_function[] = | |
2308 "function TestModule(stdlib, foreign, buffer) {\n" | |
2309 " \"use asm\";\n" | |
2310 " var fint = foreign.bar * 2.0;\n" | |
2311 "}\n"; | |
2312 v8::V8::Initialize(); | |
2313 HandleAndZoneScope handles; | |
2314 Zone* zone = handles.main_zone(); | |
2315 ZoneVector<ExpressionTypeEntry> types(zone); | |
2316 CHECK_EQ("asm: line 3: illegal double annotation value\n", | |
2317 Validate(zone, test_function, &types)); | |
2318 } | |
2319 | |
2320 TEST(BadForeignVariableReferenceValueMulNoDot) { | |
2321 const char test_function[] = | |
2322 "function TestModule(stdlib, foreign, buffer) {\n" | |
2323 " \"use asm\";\n" | |
2324 " var fint = foreign.bar * 1;\n" | |
2325 "}\n"; | |
2326 v8::V8::Initialize(); | |
2327 HandleAndZoneScope handles; | |
2328 Zone* zone = handles.main_zone(); | |
2329 ZoneVector<ExpressionTypeEntry> types(zone); | |
2330 CHECK_EQ("asm: line 3: ill-typed arithmetic operation\n", | |
2331 Validate(zone, test_function, &types)); | |
2332 } | |
2333 | |
2334 TEST(Imports) { | |
2335 const char test_function[] = | |
2336 "function TestModule(stdlib, foreign, buffer) {\n" | |
2337 " \"use asm\";\n" | |
2338 " var ffunc = foreign.foo;\n" | |
2339 " var fint = foreign.bar | 0;\n" | |
2340 " var fdouble = +foreign.baz;\n" | |
2341 " function test1() { return ffunc(fint|0, fdouble) | 0; }\n" | |
2342 " function test2() { return +ffunc(fdouble, fint|0); }\n" | |
2343 " return { testFunc1: test1, testFunc2: test2 };\n" | |
2344 "}\n"; | |
2345 | |
2346 v8::V8::Initialize(); | |
2347 HandleAndZoneScope handles; | |
2348 Zone* zone = handles.main_zone(); | |
2349 ZoneVector<ExpressionTypeEntry> types(zone); | |
2350 CHECK_EQ("", Validate(zone, test_function, &types)); | |
2351 TypeCache cache; | |
2352 | |
2353 CHECK_TYPES_BEGIN { | |
2354 // Module. | |
2355 CHECK_EXPR(FunctionLiteral, Bounds::Unbounded()) { | |
2356 // function test1 | |
2357 CHECK_EXPR(FunctionLiteral, FUNC_I_TYPE) { | |
2358 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
2359 CHECK_EXPR(Call, Bounds(cache.kAsmSigned)) { | |
2360 CHECK_VAR(ffunc, FUNC_FOREIGN_TYPE); | |
2361 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
2362 CHECK_VAR(fint, Bounds(cache.kAsmInt)); | |
2363 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2364 } | |
2365 CHECK_VAR(fdouble, Bounds(cache.kAsmDouble)); | |
2366 } | |
2367 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2368 } | |
2369 } | |
2370 // function test2 | |
2371 CHECK_EXPR(FunctionLiteral, FUNC_D_TYPE) { | |
2372 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
2373 CHECK_EXPR(Call, Bounds(cache.kAsmDouble)) { | |
2374 CHECK_VAR(ffunc, FUNC_FOREIGN_TYPE); | |
2375 CHECK_VAR(fdouble, Bounds(cache.kAsmDouble)); | |
2376 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
2377 CHECK_VAR(fint, Bounds(cache.kAsmInt)); | |
2378 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2379 } | |
2380 } | |
2381 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2382 } | |
2383 } | |
2384 // "use asm"; | |
2385 CHECK_EXPR(Literal, Bounds(Type::String())); | |
2386 // var func = foreign.foo; | |
2387 CHECK_EXPR(Assignment, Bounds(FUNC_FOREIGN_TYPE)) { | |
2388 CHECK_VAR(ffunc, Bounds(FUNC_FOREIGN_TYPE)); | |
2389 CHECK_EXPR(Property, Bounds(FUNC_FOREIGN_TYPE)) { | |
2390 CHECK_VAR(foreign, Bounds::Unbounded()); | |
2391 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
2392 } | |
2393 } | |
2394 // var fint = foreign.bar | 0; | |
2395 CHECK_EXPR(Assignment, Bounds(cache.kAsmInt)) { | |
2396 CHECK_VAR(fint, Bounds(cache.kAsmInt)); | |
2397 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmSigned)) { | |
2398 CHECK_EXPR(Property, Bounds(Type::Number())) { | |
2399 CHECK_VAR(foreign, Bounds::Unbounded()); | |
2400 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
2401 } | |
2402 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2403 } | |
2404 } | |
2405 // var fdouble = +foreign.baz; | |
2406 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2407 CHECK_VAR(fdouble, Bounds(cache.kAsmDouble)); | |
2408 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
2409 CHECK_EXPR(Property, Bounds(Type::Number())) { | |
2410 CHECK_VAR(foreign, Bounds::Unbounded()); | |
2411 CHECK_EXPR(Literal, Bounds::Unbounded()); | |
2412 } | |
2413 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2414 } | |
2415 } | |
2416 // return { testFunc1: test1, testFunc2: test2 }; | |
2417 CHECK_EXPR(ObjectLiteral, Bounds::Unbounded()) { | |
2418 CHECK_VAR(test1, FUNC_I_TYPE); | |
2419 CHECK_VAR(test2, FUNC_D_TYPE); | |
2420 } | |
2421 } | |
2422 } | |
2423 CHECK_TYPES_END | |
2424 } | |
2425 | |
2426 TEST(StoreFloatFromDouble) { | |
2427 CHECK_FUNC_TYPES_BEGIN( | |
2428 "function bar() { f32[0] = 0.0; }\n" | |
2429 "function foo() { bar(); }") { | |
2430 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
2431 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2432 CHECK_EXPR(Property, Bounds::Unbounded()) { | |
2433 CHECK_VAR(f32, Bounds(cache.kFloat32Array)); | |
2434 CHECK_EXPR(Literal, Bounds(cache.kAsmFixnum)); | |
2435 } | |
2436 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2437 } | |
2438 } | |
2439 CHECK_SKIP(); | |
2440 } | |
2441 CHECK_FUNC_TYPES_END | |
2442 } | |
2443 | |
2444 TEST(NegateDouble) { | |
2445 CHECK_FUNC_TYPES_BEGIN( | |
2446 "function bar() { var x = 0.0; x = -x; }\n" | |
2447 "function foo() { bar(); }") { | |
2448 CHECK_EXPR(FunctionLiteral, FUNC_V_TYPE) { | |
2449 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2450 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2451 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2452 } | |
2453 CHECK_EXPR(Assignment, Bounds(cache.kAsmDouble)) { | |
2454 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2455 CHECK_EXPR(BinaryOperation, Bounds(cache.kAsmDouble)) { | |
2456 CHECK_VAR(x, Bounds(cache.kAsmDouble)); | |
2457 CHECK_EXPR(Literal, Bounds(cache.kAsmDouble)); | |
2458 } | |
2459 } | |
2460 } | |
2461 CHECK_SKIP(); | |
2462 } | |
2463 CHECK_FUNC_TYPES_END | |
2464 } | |
OLD | NEW |