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